我的$?命令成功代码失败,为什么?

时间:2015-12-12 18:53:37

标签: bash

在我的bash脚本中,如果在放弃之前失去与目标的连接,我试图让rsync重试10次。

我知道这段代码会记录所有错误,但我现在可以忍受这个错误。

我的代码是:

lops="0"
while true; do
    let "lops++"
    rsync $OPT $SRCLINUX $TRG 2>&1 | tee --append ${LOGFILE}
    if [ "$?" -eq "0" ]; then
        echolog "rsync finished WITHOUT error after $lops times"
        break 
    else
        echolog "Re-starting rsync for the ${lops}th time due to ERRORS"
    fi
    if [[ "$lops" == "10" ]]; then
        echolog "GAVE UP DUE TO TOO MANY rsync ERRORS - BACKUP NOT FINISHED"
        break 
    fi
done

它没有按预期工作,这是第一个错误发生的事情:

TDBG6/
rsync: connection unexpectedly closed (131505 bytes received so far) [sender]
rsync error: error in rsync protocol data stream (code 12) at io.c(226) [sender=3.1.1]
rsync finished WITHOUT error after 1 times

这是因为$?包含tee的返回值,而不是rsync

我该如何解决这个问题? (我个人Linux语法有限:)

3 个答案:

答案 0 :(得分:3)

我发现至少有两种方法可以解决您的问题:

  1. 使用PIPESTATUS

      

    一个数组变量,包含最近执行的前台管道(可能只包含一个命令)中的进程的退出状态值列表。

    将其用作:

    rsync $OPT $SRCLINUX $TRG 2>&1 | tee --append ${LOGFILE}
    if (( PIPESTATUS[0] == 0 )); then
    
  2. 使用rsync的{​​{1}}选项。

  3. 注意:

    • 您的代码中缺少很多引号!
    • 不要使用大写变量名。
    • 请勿使用--log-file并使用let进行算术。

答案 1 :(得分:2)

除了解决管道混乱退出代码的其他建议之外,你可以像process substitution这样使用this answer来避免管道:

rsync "$OPT" "$SRCLINUX" "$TRG" &> >( tee --append "${LOGFILE}" )

会将stdoutstderr(即&>部分)重定向到与{{1}内的stdin进程相关联的“文件”在这种情况下,您需要>(...)命令。所以它非常像管道,但没有管道(管道连接左边的tee到幕后右边的stdout,我们只是在这里打开了它。

答案 2 :(得分:1)

我认为状态是管道中最后一个命令的状态。

我一般都不知道如何处理这个问题,但对于这种特殊情况,你可以重定向整个循环的输出:

while true; do
    ...
done | tee -a "$LOGFILE"

取决于它的用途,这也可能意味着您不需要" echolog"功能