检查while循环中调用的程序的退出代码

时间:2016-02-15 14:30:35

标签: bash shell

我想在bash中编写一个循环,执行直到某个命令停止失败(返回非零退出代码),如下所示:

while ! my_command; do
    # do something
done

但是在这个循环中我需要检查返回的退出代码my_command,所以我尝试了这个:

while ! my_command; do
    if [ $? -eq 5 ]; then
        echo "Error was 5"
    else
        echo "Error was not 5"
    fi
    # potentially, other code follows...
done

然后特殊变量?在循环体内变为0。 显而易见的解决方案是:

while true; do
    my_command
    EC=$?
    if [ $EC -eq 0 ]; then
        break
    fi
    some_code_dependent_on_exit_code $EC
done

如何检查循环体内my_command的退出代码(在循环标题中调用),而不使用带有中断条件的while true循环重写此示例,如上所示?

4 个答案:

答案 0 :(得分:15)

除了众所周知的while循环之外,POSIX还提供until循环,无需否定my_command的退出状态。

# To demonstrate
my_command () { read number; return $number; }

until my_command; do
    if [ $? -eq 5 ]; then
        echo "Error was 5"
    else
        echo "Error was not 5"
    fi
    # potentially, other code follows...
done

答案 1 :(得分:4)

如果true命令伤害了你的敏感度,你可以写:

while my_command ; ret=$? ; [ $ret -ne 0 ];do
    echo do something with $ret
  done

这可以简化:

while my_command ; ((ret=$?)) ;do
    echo do something with $ret
  done

但如果您不需要 ResultCode ,您可以简单地:

while my_command ; [ $? -ne 0 ];do
    echo Loop on my_command
  done

while my_command ; (($?)) ;do
    echo Loop on my_command
  done

但是从那里你可以更好地使用until as chepner suggest

答案 2 :(得分:2)

您可以从PIPESTATUS内置变量中获取否定命令的状态:

while ! my_command ; do
    some_code_dependent_on_exit_code $PIPESTATUS
done
在这种情况下,chepner的解决方案更好,但PIPESTATUS有时对类似的问题很有用。

答案 3 :(得分:0)

因此,在我的情况下,我还需要忽略一些退出代码,并希望向用户提供一些有用的输出,因此我将其写成:

retrycmd(){
  MSG=$1
  IGNORE=$2
  shift 2
  local SLEEP_T=5
  local L_CNT=5
  local C_CNT=0
  while ((C_CNT++ < ${L_CNT})) && ! $@;do
    RET=${PIPESTATUS[0]}
    #echo "RET: ${RET}"
    for I in ${IGNORE//,/ };do # bashism: replace(/) all(/) match(,) with(/) value(<space>)
      if ((${RET} == ${I}));then
        #echo "${RET} = ${I}"
        break 2
      fi
    done
    echo "${MSG} failure ${C_CNT}"
    sleep ${SLEEP_T}
  done
  if ((${C_CNT} > ${L_CNT}));then
    echo "${MSG} failed"
    poweroff
  fi
}

#retrycmd "Doing task" "IGNORE,CSV" <CMD>
retrycmd "Ping google" "0" ping www.google.com