我知道如何使用$?检查以前执行的命令的状态,我们可以使用exit命令来创建该状态。但是对于bash中的循环总是返回状态0并且有任何方法可以打破具有某种状态的循环。
#!/bin/bash
while true
do
if [ -f "/test" ] ; then
break ### Here I would like to exit with some status
fi
done
echo $? ## Here I want to check the status.
答案 0 :(得分:20)
循环的状态是执行的最后一个命令的状态。您可以使用break来突破循环,但如果中断成功,则循环的状态将为0
。但是,您可以使用子shell并退出而不是中断。换句话说:
for i in foo bar; do echo $i; false; break; done; echo $? # The loop succeeds
( for i in foo bar; do echo $i; false; exit; done ); echo $? # The loop fails
你也可以把循环放在一个函数中并从中返回一个值。
答案 1 :(得分:2)
这样的东西?
while true; do
case $RANDOM in *0) exit 27 ;; esac
done
或者喜欢这个?
rc=0
for file in *; do
grep fnord "$file" || rc=$?
done
exit $rc
真正的问题是如果一次迭代失败,则决定循环的退出代码是成功还是失败。在某些情况下,一个人比另一个人更有意义,而另一些人则根本不清楚。
答案 2 :(得分:1)
bash手册说:
while list-1; do list-2; done
until list-1; do list-2; done
[..]The exit status of the while and until commands is the exit status
of the last command executed in list-2, or zero if none was executed.[..]
在循环中执行的最后一个命令是break
。 break
的退出值为0(请参阅:help break
)。
这就是你的程序一直以0退出的原因。
答案 3 :(得分:0)
我认为你应该问的是:我怎么能等到另一个进程创建文件或目录(false
)?
到目前为止,您正在进行的是全力投票。您的循环将分配高达100%的一个核心处理能力。关键字是“轮询”,这在计算机科学家的标准下符合道德规范错误。
有两种补救措施:
/test
之类的通知机制(参见:inotify
);优点:没有CPU负载,响应速度快,没有延迟,代码中没有任意常量;缺点:man inotify
是一个内核API - 您需要一些代码来访问它:inotify
或一些C / Perl / Python代码。看看inotify and bash!答案 4 :(得分:0)
为bash构建的break确实允许你完成你正在做的事情,只是打破一个负值并且$返回的状态?将是1:
while true
do
if [ -f "./test" ] ; then
break -1
fi
done
echo $? ## You'll get 1 here..
请注意,这已在break builtin的帮助中记录:
help break
break:break [n]退出for,while或者直到循环。
退出FOR,WHILE或UNTIL循环。如果指定了N,则将N括起来 环路。
退出状态:退出状态为0,除非N不大于或 等于1。
你可以突破n个循环或发送负值以打破非零回报,即1
我同意@hagello作为睡眠和改变循环的一个选择:
#!/bin/bash
timeout=120
waittime=0
sleepinterval=3
until [[ -f "./test" || ($waittime -eq $timeout) ]]
do
$(sleep $sleepinterval)
waittime=$((waittime + sleepinterval))
echo "waittime is $waittime"
done
if [ $waittime -lt $sleepinterval ]; then
echo "file already exists"
elif [ $waittime -lt $timeout ]; then
echo "waited between $((waittime-3)) and $waittime seconds for this to finish..."
else
echo "operation timed out..."
fi
答案 5 :(得分:0)
我想提交一个更简单,更优雅的替代解决方案:
(while true
do
if [ -f "test" ] ; then
break
fi
done
Of course of this is part of a script then you could user return 1 instead of exit 1
exit 1
)
echo "Exit status is: $?"
答案 6 :(得分:0)
Git 2.27(2020年第2季度)很好地说明了循环中的退出状态,此处是在尽早中止失败的测试(例如退出循环)的情况下,即“返回1”。 / p>
请参见commit 7cc112d的Junio C Hamano (gitster
)(2020年3月27日)。
(由Junio C Hamano -- gitster
--在commit b07c721中合并,2020年4月28日)
t/README
:建议如何在失败后尽早退出测试帮助者:杰夫·金
随着时间的流逝,我们在测试框架中添加了支持,以使其易于在失败时及早退出测试,但是
t/README
中并未明确记录该文档以帮助开发人员编写新测试。
循环时要小心
您可能需要循环验证多个内容,但以下内容无法正常工作:
test_expect_success 'test three things' ' for i in one two three do test_something "$i" done && test_something_else '
由于循环本身的状态是上一轮
test_something
的退出状态,因此当“ {{ 1}}“或”test_something
“失败。
这不是你想要的。相反,看到故障时,您可以立即退出循环。
由于所有one
代码段都是在函数内部执行的,因此“two
”可用于在失败后立即使测试失败:test_expect_*
请注意,我们仍然
return 1
链接循环以传播早期命令的故障。
答案 7 :(得分:0)
使用人工退出代码?
在中断循环之前,先设置一个变量,然后将其作为循环的状态码进行检查,如下所示:
while true; do
if [ -f "/test" ] ; then
{broken=1 && break; };
fi
done
echo $broken #check the status with [[ -n $broken ]]