【问题标题】:Can't kill a Bash command that sleeps in a loop无法杀死在循环中休眠的 Bash 命令
【发布时间】:2016-11-29 11:04:46
【问题描述】:

我试着跑了

$ (while true; do cat some_small_file ; sleep 1; done) | some_script

测试some_script,但some_script不在我的$PATH中,所以打印出来

some_script command not found

奇怪的是Bash 没有返回,而Ctrl-C 什么也不做。

我什至尝试用

杀死sleep
ps -u maxb | grep sleep | cut -f1 -d " " | xargs kill -9

在另一个终端中,但这当然只是继续下一个循环迭代。

是否可以让Bash 终止该命令?

【问题讨论】:

  • 顺便说一句,请考虑使用pkill 而不是ps | grep | xargs kill

标签: linux bash ubuntu ubuntu-14.04


【解决方案1】:

您可以在这里采取一些方法。

一种是将catsleep 移动到while 语法的条件部分,这样一旦这些命令中的任何一个不成功,循环就会失败:

while cat some_small_file && sleep 1; do :; done | some_script

类似的选择是将明确的break 放入循环中,以此类失败为条件(再次):

while :; do cat some_small_file && sleep 1 || break; done | some_script

请注意,:true 的同义词。 (在我见过的每个 shell 中——不仅仅是 bash,甚至是 Busybox ash——它们实际上是由相同的内部函数实现的。


还请注意,此解决方案最重要的部分是在 cat 失败时退出循环,而不是在 sleep 失败时退出循环:在 sleep 失败时退出将解决 kill问题,但在 cat 失败时退出将处理(更有可能)some_script 已退出的情况,因此写入它会导致 SIGPIPE


顺便说一句 - 直接删除 ( )s 或用 { ...; } 替换它们是一种可能减少瞬态子外壳数量的方法:虽然管道总是创建隐式子外壳,但没有特别的理由使用语法可能(在某些情况下——有相关的细节是实现而不是标准定义的)除了强制性的隐式子shell外,还会创建一个显式的子shell。

因此,这是一个非常小的效率改进,但对于这个答案来说不是必不可少的:如果您坚持原来的括号但以相同的方式修改流控制结构,您会得到相同的行为。

【讨论】:

  • 也许会指出,虽然大括号可能因您所说的原因而有用,但 while stuff; do other things; done | some_script 也是有效的语法。
  • @tripleee,很棒的电话。真的,我应该证明这一点,因为我们不需要前缀、后缀或需要分组运算符的类似情况。编辑得当。
猜你喜欢
  • 1970-01-01
  • 2015-04-02
  • 2015-12-22
  • 1970-01-01
  • 2013-02-10
  • 1970-01-01
  • 2015-07-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多