终止无限循环

how*_*rdh 64 bash signals

我有一个命令,每次它终止时我都想自动再次运行,所以我运行了这样的命令:

while [ 1 ]; do COMMAND; done;
Run Code Online (Sandbox Code Playgroud)

但如果我不能停止循环,Ctrl-c因为那只会杀死COMMAND而不是整个循环。

我将如何实现类似的功能,但无需关闭终端即可停止?

小智 60

您可以在工作运行时停止并将工作置于后台使用ctrl+ z。然后你可以用以下方法结束你的工作:

$ kill %1
Run Code Online (Sandbox Code Playgroud)

其中 [1] 是您的工作编号。

  • 这个相对较新的答案只是简单有效。需要点赞。+1 (2认同)

Kyl*_*nes 45

检查命令的退出状态。如果命令被信号终止,退出代码将为 128 + 信号编号。来自bashGNU 在线文档

出于 shell 的目的,以零退出状态退出的命令已成功。非零退出状态表示失败。使用这种看似违反直觉的方案,因此有一种明确定义的方式来表示成功,并有多种方式来表示各种失败模式。当命令在编号为 N 的致命信号上终止时,Bash 使用值 128+N 作为退出状态。

POSIX 还指定由信号终止的命令的值大于 128,但似乎没有像 GNU 那样指定其确切值:

由于收到信号而终止的命令的退出状态应报告为大于 128。

例如,如果您使用 control-C 中断命令,则退出代码将为 130,因为 SIGINT 在 Unix 系统上是信号 2。所以:

while [ 1 ]; do COMMAND; test $? -gt 128 && break; done
Run Code Online (Sandbox Code Playgroud)

  • 需要说明的是,这并不能保证,实际上很多应用程序都不会这样做。 (11认同)

eph*_*ith 25

我会说最好将无限循环放在脚本中并在那里处理信号。这是一个基本的起点。我相信你会想要修改它以适应。该脚本用于trap捕获ctrl- c(或SIGTERM),终止命令(我在sleep这里用作测试)并退出。

cleanup ()
{
kill -s SIGTERM $!
exit 0
}

trap cleanup SIGINT SIGTERM

while [ 1 ]
do
    sleep 60 &
    wait $!
done
Run Code Online (Sandbox Code Playgroud)

  • 好的。下面是我如何使用这个技巧来制作自动重启 netcat 包装器:`trap "exit 0" SIGINT SIGTERM; 虽然是真的;做 netcat -l -p 3000; 完成` (4认同)
  • 如果您将此 `trap` 方法添加到要终止无限循环的相同(bash)脚本中,请使用 `$$` 而不是 `$!`(请参阅 [此处](http://tldp.org/LDP/ abs/html/internalvariables.html)) (2认同)

jw0*_*013 15

我一般只是按住Ctrl-C。迟早它会在COMMAND's之间注册,从而终止while循环。也许有更好的方法。


Bre*_*ong 10

如果你用-e它运行 bash将在任何错误情况下退出:

#!/bin/bash -e
false # returns 1
echo This won't be printed
Run Code Online (Sandbox Code Playgroud)


Dal*_*son 10

为什么不简单,

while [ 1 ]; do COMMAND || break; done;
Run Code Online (Sandbox Code Playgroud)

或者在脚本中使用时,

#!/bin/bash
while [ 1 ]; do
  # ctrl+c terminates COMMAND and exits the while loop
  # (assuming COMMAND responds to ctrl+c)
  COMMAND || break
done;
Run Code Online (Sandbox Code Playgroud)

  • 非常优雅的解决方案。但这不是只有在 COMMAND 始终返回成功退出状态时才有效吗? (2认同)