Shell中test测试条件表达式的真假,你可能不知道的秘密

今天晚上在看测试系统安装的问题,脚本安装是成功的,但是我自己手动make却是失败的;仔细研究发现是test表达式的误用,这个bug都存在系统中好几年了,^_^
用的是Bash,其中一个函数如下:
function install_tet()
{
    local ret=0
    local temp_file=mktemp
    cd $XVS_HG_REPO/validation/dependencies/tet/
    make > $temp_file 2>&1 || ret=1
    file_tet_rpm=$(grep "RPMS" $temp_file | grep -v "SRPMS" | grep -v "tet_testsuite_dependency-debuginfo" | awk '{print $NF}')
    run_quiet rpm -ivh $file_tet_rpm --nodeps
    run_quiet cd -
    if [ $? -a $ret ];then
        return 0
    fi
    return 1
}
看出什么问题了吗?
我手动直接执行cd $XVS_HG_REPO/validation/dependencies/tet/,然后执行make命令,其实是报错了的,其错误信息如下:
error: File /root/rpmbuild/SOURCES/tet_testsuite_dependency-3.3.2.tgz: No such file or directory
我们先不管导致这个错误的原因(其实是rhel6中rpmbuild的一些东西和rhel5u5中不一致,而我们脚本以前都是基于rhel5的)。
手动执行make命令都错误了,然后如果脚本自动运行却提示为install_tet函数是执行成功的(我们将return 0标志执行成功)。
经过仔细分析就会发现,函数中return 1是永远不可能执行到的,就不管函数执行过程中有没有错误发生,都会永远return 0.
那么问题的根本原因就浮出水面了,是下面这小段条件表达式的test的问题。
    if [ $? -a $ret ];then
        return 0
    fi
如下的几段代码,都会return 0:
if [ 0 -a 0 ]; then
    return 0
fi
if [ 1 -a 1 ]; then
    return 0
fi
if [ false ]; then
    return 0
fi
而下面两种情况是会return 1的:
if [ ]; then
    return 0
else
    return 1
fi
if test ''; then
    return 0
else
    return 1
fi
总结一下吧:
test某个条件表达式结果的真假,条件表达式必须进行了某个测试,例如-eq, -d等;也就是说一个表达式,无论是数字、字符串,test的结果都是true,例如
S=0
test $S
无论S取值什么都是true。但是如果 test $S -eq $S2,即用到了test所支持的表达式有了真假。
test(即[])没有参数时,会返回1(表示false);只有一个参数时,当且仅当该参数为空时,才会返回1.
更多详细信息,可以man bash找到 test expr处有详细的说明:
test expr
       [ expr ]
              Return  a status of 0 or 1 depending on the evaluation of the conditional expression
              expr.  Each operator and operand must be a separate argument.  Expressions are  com-
              posed of the primaries described above under CONDITIONAL EXPRESSIONS.  test does not
              accept any options, nor does it accept and ignore an argument of  --  as  signifying
              the end of options.

              Expressions  may  be  combined  using  the following operators, listed in decreasing
              order of precedence.  The evaluation depends on the number of arguments; see  below.
              ! expr True if expr is false.
              ( expr )
                     Returns  the  value  of expr.  This may be used to override the normal prece-
                     dence of operators.
              expr1 -a expr2
                     True if both expr1 and expr2 are true.
              expr1 -o expr2
                     True if either expr1 or expr2 is true.

              test and [ evaluate conditional expressions using a set of rules based on the number
              of arguments.

              0 arguments
                     The expression is false.
              1 argument
                     The expression is true if and only if the argument is not null.
              2 arguments
                     If  the first argument is !, the expression is true if and only if the second
                     argument is null.  If the first argument is  one  of  the  unary  conditional
                     operators  listed above under CONDITIONAL EXPRESSIONS, the expression is true
                     if the unary test is true.  If the first argument is not a valid unary condi-
                     tional operator, the expression is false.
              3 arguments
                     If  the  second  argument  is  one of the binary conditional operators listed
                     above under CONDITIONAL EXPRESSIONS, the result  of  the  expression  is  the
                     result  of  the  binary test using the first and third arguments as operands.
                     The -a and -o operators are considered binary operators when there are  three
                     arguments.  If the first argument is !, the value is the negation of the two-
                     argument test using the second and third arguments.  If the first argument is
                     exactly ( and the third argument is exactly ), the result is the one-argument
                     test of the second argument.  Otherwise, the expression is false.
              4 arguments
                     If the first argument is !, the result is the negation of the  three-argument
                     expression composed of the remaining arguments.  Otherwise, the expression is
                     parsed and evaluated according to precedence using the rules listed above.
              5 or more arguments
                     The expression is parsed and evaluated  according  to  precedence  using  the
                     rules listed above.

master

Stay hungry, stay foolish.

发表评论

邮箱地址不会被公开。 必填项已用*标注

*