【问题标题】:Set return (exit) code in find, while loop在 find、while 循环中设置返回(退出)代码
【发布时间】:2012-03-14 13:42:21
【问题描述】:

我有这样的事情:

find $1 | grep -E $2  | while read prom; do
            if [[ $prom =~ (cmd-given) ]];
            then
                ...
                RETURN_PATH=$PWD
                cd $WORKING_PATH
                ...
                if [[ -s "stdout-delta" ]] || [[ -s "stderr-delta" ]] || [[ -s "status-delta" ]];
                then
                    RET_ERROR=1
                    RESULT="FAILED"
                else
                    RESULT="OK"
                fi
                ...
                echo "$TEST: $RESULT\n" > /dev/stderr
                cd $RETURN_PATH
            fi
        done

我想测试是否在每个具有 cmd-given 的文件夹中检查空文件 x-delta。如果这些文件中的任何一个不为空,我想写 FAILED 并将返回码设置为 1。但我想检查所有文件夹,所以我认为我使用变量,将其设置为 1,最后检查它是否等于 1退出 1 否则退出 0。但是有问题,当我从那个循环中退出时,我的变量中没有 1。那我应该怎么解决呢?

【问题讨论】:

    标签: bash variables loops global-variables exit-code


    【解决方案1】:

    循环在子进程中运行,因此您必须使用某种形式的 IPC 与原始进程(shell)进行通信。

    最简单的解决方案可能是将错误消息回显到 stdout 并在 while 循环之后添加一个管道来解析输出。一个简单的 grep 就足够了。只要确保没有其他命令可以将“FAILED”写入标准输出。

    find $1 | grep -E $2  | while read prom; do
                if [[ $prom =~ (cmd-given) ]];
                then
                    ...
                    RETURN_PATH=$PWD
                    cd $WORKING_PATH
                    ...
                    if [[ -s "stdout-delta" ]] || [[ -s "stderr-delta" ]] || [[ -s "status-delta" ]];
                    then
                        RET_ERROR=1
                        RESULT="FAILED"
                        echo $RESULT
                    else
                        RESULT="OK"
                    fi
                    ...
                    echo "$TEST: $RESULT\n" > /dev/stderr
                    cd $RETURN_PATH
                fi
            done | grep -q FAILED
    [ "$?" == 0 ] && exit 1
    

    编辑:基于临时文件的解决方案:

    TMPFILE=$0.tmp
    trap "rm -f $TMPFILE; exit 1" 0 1 2 3 13 15
    find $1 | grep -E $2  | while read prom; do
                if [[ $prom =~ (cmd-given) ]];
                then
                    ...
                    RETURN_PATH=$PWD
                    cd $WORKING_PATH
                    ...
                    if [[ -s "stdout-delta" ]] || [[ -s "stderr-delta" ]] || [[ -s "status-delta" ]];
                    then
                        RET_ERROR=1
                        RESULT="FAILED"
                        echo $RESULT >> $TMPFILE
                    else
                        RESULT="OK"
                    fi
                    ...
                    echo "$TEST: $RESULT\n" > /dev/stderr
                    cd $RETURN_PATH
                fi
            done
    
    grep -q FAILED $TMPFILE && rm $TMPFILE && exit 1
    rm $TMPFILE && exit 0
    

    编辑 2:基于函数的解决方案

    process () {
        find $1 | grep -E $2 | (cat; echo EXIT_MARKER) | while read prom; do
                [[ $prom == "EXIT_MARKER" ]] && exit $EXIT_STATUS
                if [[ $prom =~ (cmd-given) ]];
                then
                    ...
                    RETURN_PATH=$PWD
                    cd $WORKING_PATH
                    ...
                    if [[ -s "stdout-delta" ]] || [[ -s "stderr-delta" ]] || [[ -s "status-delta" ]];
                    then
                        RET_ERROR=1
                        RESULT="FAILED"
                        EXIT_STATUS=1
                    else
                        RESULT="OK"
                    fi
                    ...
                    echo "$TEST: $RESULT\n" > /dev/stderr
                    cd $RETURN_PATH
                fi
            done
        exit 0
    }
    
    process $1 $2
    exit $?
    

    【讨论】:

    • 我理解您的解决方案,但是我使用 echo 来编写获得了哪个测试以及哪个结果会有问题,所以我不能仅将它用于错误代码。我知道在我的代码中我会回显到 stderr,但是当 echo "$TEST..." 转到 stdout 时我需要一个解决方案。
    • 如果打印的 any 行在任何地方包含“FAILED”,则最后的 grep 将返回 TRUE。因此,如果我理解正确,即使将各种内容回显到标准输出,它也应该仍然有效;前提是那里没有任何不需要的“FAILED”字符串。
    • 这是我需要的,我喜欢它,但我有问题 grep 总是在 $? 中返回 1。我并不关心它总是返回 1 的任何地方是否有“FAILED”。
    • 我错了。请使用新版本重试(最后一行已更改)。
    • 现在它工作得很好,但这是输出到 /dev/stderr 的一部分,我需要在更改参数时它应该回显 "$TEST: $RESULT\n" > /dev/stdout 但 grep 正在占用所有标准输出。所以最后一件事,你如何改变它?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-05-15
    • 1970-01-01
    • 2016-01-30
    • 1970-01-01
    • 1970-01-01
    • 2020-04-13
    • 2019-11-06
    相关资源
    最近更新 更多