代码之家  ›  专栏  ›  技术社区  ›  seladb

如果其中一个语句返回错误代码,则返回Bash-break条件子句!=0

  •  1
  • seladb  · 技术社区  · 7 年前

    我有以下bash脚本,它在我的CI上运行,并打算在物理MacOS和几个docker Linux映像上运行我的代码:

    if [[ "$OS_NAME" == "mac_os" ]]; then
           make all;
           run_test1;
           run_test2;
           make install;
        else
           docker exec -i my_docker_image bash -c "make all";
           docker exec -i my_docker_image bash -c "run_test1";
           docker exec -i my_docker_image bash -c "run_test2"; 
           docker exec -i my_docker_image bash -c "make install";
        fi
    

    如果测试失败( run_test1 run_test2 )它们返回错误代码1。如果通过,则返回错误代码0。

    整个脚本使用 set -e 因此,每当它看到除0之外的退出代码时,它就会停止并使整个构建失败。

    问题是,目前 运行测试1 在条件子句内-当它们失败并返回错误代码1时,条件子句不会中断,并且生成成功,尽管测试没有通过。

    我有两个问题:

    • 如果其中一个命令返回非0的错误代码,如何中断条件子句?
    • 如何打破条件子句,使整个子句返回错误代码(因此整个构建将失败)?
    1 回复  |  直到 7 年前
        1
  •  1
  •   PesaThe    7 年前

    您的代码应该按预期工作,让我们演示一下:

    #!/usr/bin/env bash
    
    set -e  
    
    var="test"   
    if [[ $var = test ]]; then
        echo "Hello"
        cat non_existing_file &> /dev/null
        echo "World"
    else
        echo "Else hello"
        cat non_existing file &> /dev/null
    fi 
    
    echo I am done
    

    正如预期的那样,这将只输出“Hello”。如果它对您的工作方式不同,则意味着您没有提供足够的代码。让我们尝试更改上面的代码,并在以下情况下显示一些示例: set -e 被忽略,就像您的情况一样:

    引用 Bash Reference manual :

    如果复合命令或shell函数在-e的上下文中执行 被忽略时,在化合物内执行的任何命令 命令或函数体将受到-e设置的影响,即使 -设置e,命令返回故障状态。

    现在,让我们引用同一手册,看看忽略-e的一些情况:

    如果失败的命令是 紧跟在while或until关键字之后的命令列表,部分 if语句中的测试,是在&&或 ||除最后一个命令后面的命令外,列出&或||,任何命令 在管道中,但在最后一个管道中,或者如果命令的返回状态为 反转为!。

    从这里我们可以看到,例如,如果你在一个函数中有上面的代码,并用 if 集合-e 将被忽略:

    #!/usr/bin/env bash
    
    set -e  
    
    f() {
       var="test"
       if [[ $var = test ]]; then
           echo "Hello"
           cat non_existing_file &> /dev/null
           echo "World"
       else
           echo "Else hello"
           cat non_existing file &> /dev/null
       fi
    }
    
    if f; then echo "Function OK!"; fi
    
    echo I am done
    

    作用 f 在以下上下文中执行: 集合-e 被忽略(如果是语句),这意味着 集合-e 不会影响此函数中执行的任何命令。该代码输出:

    你好

    世界

    功能正常!

    在a&中执行函数时,同样的规则适用&或| |列表。如果你换线 if f; then echo "Function OK!"; fi f && echo "Function OK" ,您将获得相同的输出。我相信后者可能是你的情况。

    即便如此,你的 第二个问题 可以通过添加 || exit :

    run_test1 || exit 1;
    run_test2 || exit 1;
    

    你的 第一个问题 例如,如果你在一个函数中,它是微不足道的。然后你可以简单地 return . 或者在一个循环中,然后你可以 break . 如果你没有这样做,那么打破条件从句就不那么容易了。看看这个 answer .

    集合-e 这可能是一件令人惊讶的事情,因为它在许多情况下被忽视。小心使用,并注意这些情况。