Bash 检查while循环中调用的程序的退出代码
我想在bash中编写一个循环,直到某个命令停止失败为止(返回非零退出代码),如下所示:Bash 检查while循环中调用的程序的退出代码,bash,shell,Bash,Shell,我想在bash中编写一个循环,直到某个命令停止失败为止(返回非零退出代码),如下所示: while ! my_command; do # do something done 但是在这个循环中,我需要检查返回的退出代码my_命令,所以我尝试了以下方法: while ! my_command; do if [ $? -eq 5 ]; then echo "Error was 5" else echo "Error was not 5"
while ! my_command; do
# do something
done
但是在这个循环中,我需要检查返回的退出代码my_命令
,所以我尝试了以下方法:
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_命令
(称为循环头)的退出代码,而不使用while true
循环(如上图所示的中断条件)?如果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
但是从那里你可以更好地使用除了众所周知的
while
循环之外,POSIX还提供了直到循环,消除了否定我的_命令退出状态的需要
# 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
您可以从PIPESTATUS
内置变量中获取否定命令的状态:
while ! my_command ; do
some_code_dependent_on_exit_code "${PIPESTATUS[0]}"
done
chepner的解决方案在这种情况下更好,但是对于类似的问题,PIPESTATUS
有时很有用。因此在我的情况下,我还需要忽略一些退出代码,并希望向用户提供一些有用的输出,因此我写了以下内容:
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
retrycmd(){
味精=$1
忽略=2美元
班次2
局部睡眠\u T=5
局部L_CNT=5
局部C_CNT=0
而((C_CNT++<${L_CNT}))&&&!$@;do
RET=${PIPESTATUS[0]}
#回显“RET:${RET}”
对于${IGNORE/,/};do#bashism中的I:replace(/)all(/)match(,)为(/)value()
如果(${RET}=${I}));那么
#回声“${RET}=${I}”
突破2
fi
完成
回显“${MSG}故障${C_CNT}”
睡眠${sleep\u T}
完成
如果(${C_CNT}>${L_CNT})),那么
回显“${MSG}失败”
断电
fi
}
#retrycmd“正在执行任务”“忽略,CSV”
retrycmd“Ping google”0“Ping www.google.com
回答得好!我从来不知道,当command1;命令2;做…
works在我看来是迄今为止的赢家。我喜欢!当你知道有一个until
循环时,这是非常明显的!RTFM给我。我认为这是最好的答案,很有道理。我不知道PIPESTATUS
在这种情况下也起作用。这是。
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