【问题标题】:Two piped programs, one continues to run after another is killed两个管道程序,一个在另一个被杀死后继续运行
【发布时间】:2016-11-30 21:31:07
【问题描述】:

我的 bash 脚本中有两个程序:

program1 | program2

问题是程序 2 可能会崩溃,我想确保当它崩溃时,程序 1 也会结束。我试图通过杀死 program2 来测试这一点

pkill program2

在执行期间,但程序 1 继续运行。

据我了解,很多人都在问如何让program1继续运行,因为它默认被杀死。我错过了什么吗?

【问题讨论】:

  • program1 在尝试写入管道之前不会注意到 program2 已死。大多数程序一旦这样做就会退出。
  • 解决方法:让您的程序 1 打印进度条或点或其他东西。
  • 实际上 program1 在某个时期为 program2 提供持续输入,当 program2 死机时,我在控制台上收到某种 program1 的内部错误日志(libpng 错误:写入错误)
  • 但它仍在尝试每 x 秒写入一次

标签: linux bash process pipe


【解决方案1】:

不要使用匿名管道,而是使用命名管道,让您可以更好地控制每一端。

mkfifo p
program1 > p &  p1_pid=$!
program2 < p
kill "$p1_pid"

在这个 sn-p 中,我们创建了一个名为 p 的命名管道,然后在后台运行 program1,并将其标准输出重定向到 pp1_pid 存储了program1 的进程ID,供以后使用。请注意,program1 已启动,但会立即阻塞,直到有东西打开 pfor eading. We runprogram2with its standard input redirected fromp`,然后在运行时阻塞。

program2 因任何原因退出时,kill 命令将发送SIGTERMprogram1 以在必要时终止它。这有两个好处:

  1. 它可以更快地杀死program1,因为您不必等待program1 写入管道并接收SIGPIPE 信号。

  2. 如果program1 正在处理SIGPIPE,它可能也在处理其他信号。您可以使用kill 发送任何必要的信号(直到并包括SIGKILL,如果确实有必要)来终止进程。

【讨论】:

  • 这是mkfifo 的一个很好的用例。我很少看到这些!值得注意的是p会在文件系统上创建。
  • 有没有办法将程序 2 的标准输出重定向到文件?以前我有 &> 日志文件,但我不确定现在正确的语法是什么
  • 当然; program2 &lt; p &gt; output 2&gt; error&amp;&gt; logfile 适用于将两者重定向到同一个文件(2&gt;&amp;1 &gt; logfile 的缩写)。
【解决方案2】:

这个呢:

program1 | program2
rc="$?"; if [ "$rc" -ne 0 ]; then killall program1 > /dev/null 2>&1; fi

如果以上不行,可以尝试添加

set -o pipefail

到脚本的开头。该命令将退出其中一个步骤失败并返回第一个失败脚本的返回码的管道。

【讨论】:

  • 我的 bash 脚本的其余部分有类似的代码,但它没有被执行,因为它的 program1 仍然存在
  • 我添加了一个替代代码,检查它是否适合你。
  • 好的,好吧,chepner 的回答“解决”了这个问题。
猜你喜欢
  • 1970-01-01
  • 2011-08-26
  • 1970-01-01
  • 2019-11-22
  • 1970-01-01
  • 2012-05-31
  • 2017-03-02
相关资源
最近更新 更多