无法杀死在循环中休眠的Bash命令

时间:2016-07-25 23:46:31

标签: linux bash ubuntu ubuntu-14.04

我试图运行

$ (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终止该命令?

1 个答案:

答案 0 :(得分:3)

您可以采取一些方法。

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

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会导致( ) }。

顺便说一句 - 要么直接删除{ ...; },要么用T& T::operator+=( const T& ) { // ... implementation ... return *this; } T operator+( const T& lhs, const T& rhs ) { T temp( lhs ); return temp += rhs; } 替换它们是合适的,可以减少瞬态子壳的数量:虽然管道总是创建隐式子壳,但是没有使用语法的特殊原因(在某些情况下 - 有相关的细节是实现而不是标准定义)除了强制隐式的一个(s)之外还创建一个显式的子shell。

这是一个非常小的效率提升,但对于这个答案并不重要:如果你坚持使用原始括号但是以相同的方式修改了流控制结构,你会得到相同的行为。