bash - 如何获取管道命令的pid?

标签 bash

(或如何杀死子进程)?

inotifywait -mqr --format '%w %f %e' $feedDir | while read dir file event
do
#something
done &

echo $! #5431

例如:

 >$ ps
  PID TTY          TIME CMD
 2867 pts/3    00:00:02 bash
 5430 pts/3    00:00:00 inotifywait
 5431 pts/3    00:00:00 bash
 5454 pts/3    00:00:00 ps

似乎如果我杀死 5431 那么 5430 (inotifywait) 将继续运行,但如果我杀死 5430 然后两个进程都死了。我不认为我可以可靠地假设 inotifywait 的 pid 总是比 $! 小 1?

最佳答案

当我们运行管道时,每个命令都在一个单独的进程中执行。解释器等待最后一个,但如果我们使用和号 (&)。

cmd1 | cmd2 &

进程的 pid 可能很接近,但我们不能可靠地假设它。在最后一个命令是 bash 保留字的情况下,它会创建一个专用的 bash(这就是为什么你的 'dir'、'file' 变量在 done 关键字之后不存在)。示例:

ps # shows one bash process
echo "azerty" | while read line; do ps; done # shows one more bash

当第一个命令退出时,第二个命令将终止,因为管道上的读取返回 EOF。 当第二个命令退出时,第一个命令在尝试写入管道时将被 signal SIGPIPE(在没有读取器的管道上写入)终止。但是,如果命令无限期地等待……它不会终止。

echo “$!”打印在后台执行的最后一个命令的 pid。在您的例子中,是执行 while 循环的 bash 进程。

您可以使用以下语法找到“inotifywait”的 pid。但它很丑陋:

(inotifywait ... & echo "$!">inotifywait.pid) | \
while read dir file event
do
    #something
done &
cat inotifywait.pid # prints pid of inotifywait

如果你不想要 pid,但只是确定进程将被终止,你可以使用 inotifywait 的 -t 选项:

(while true; do inotifywait -t 10 ...; done)| \
while read dir file event
do
    #something
done &
kill "$!" # kill the while loop

这些解决方案都不好。你真正的成就是什么?也许我们可以找到更优雅的解决方案。

关于bash - 如何获取管道命令的pid?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23616431/

相关文章:

c - 如何从 bash 读取部分输入的文本?

bash - 将 bash 变量传递给内联 perl 脚本

bash - 运行具有多个并行动态程序的 Shell 脚本

linux - 在bash中解析conf文件

javascript - 您如何使用 Electron 应用程序检查文件是否存在于本地

regex - 如何在以下命令中将 bash 变量通过管道传输到 GREP 正则表达式中?

linux - 无法从嵌套子 shell 传递变量

macos - 以 root 身份运行 rsync : Operations Not Permitted

bash - 使用 sed 将变量打印到文件末尾

python - 进程组中的所有 child 并不总是看到信号