为什么下面的命令不退出?循环不是无限运行,而不是退出。
尽管我使用更复杂的设置发现了此行为,但命令的最简单形式简化为以下形式。
不退出:
while /usr/bin/true ; do echo "ok" | cat ; done | exit 1
上面没有错别字。每个“ |” 是管子。“出口1”代表另一个已运行并已退出的过程。
我希望“退出1”会在while循环上导致SIGPIPE(在没有读取器的管道上进行写操作)并使循环中断。但是,循环继续运行。
为什么命令不停止?
这是由于在实现中的选择。
在Solaris上与一起运行相同的脚本ksh93
会产生不同的行为:
$ while /usr/bin/true ; do echo "ok" | cat ; done | exit 1
cat: write error [Broken pipe]
触发该问题的是内部管道,如果没有内部管道,则无论shell / OS是什么,循环都会退出:
$ while /usr/bin/true ; do echo "ok" ; done | exit 1
$
cat
在bash下获取SIGPIPE信号,但是shell无论如何都在循环。
Process 5659 suspended
[pid 28801] execve("/bin/cat", ["cat"], [/* 63 vars */]) = 0
[pid 28801] --- SIGPIPE (Broken pipe) @ 0 (0) ---
Process 5659 resumed
Process 28801 detached
Process 28800 detached
--- SIGCHLD (Child exited) @ 0 (0) ---
Process 28802 attached
Process 28803 attached
[pid 28803] execve("/bin/cat", ["cat"], [/* 63 vars */]) = 0
Process 5659 suspended
[pid 28803] --- SIGPIPE (Broken pipe) @ 0 (0) ---
Process 5659 resumed
Process 28803 detached
Process 28802 detached
--- SIGCHLD (Child exited) @ 0 (0) ---
Process 28804 attached
Process 28805 attached (waiting for parent)
Process 28805 resumed (parent 5659 ready)
Process 5659 suspended
[pid 28805] execve("/bin/cat", ["cat"], [/* 63 vars */]) = 0
[pid 28805] --- SIGPIPE (Broken pipe) @ 0 (0) ---
Process 5659 resumed
Process 28805 detached
Process 28804 detached
--- SIGCHLD (Child exited) @ 0 (0) ---
Bash文档指出:
在返回值之前,shell等待管道中的所有命令终止。
Ksh文档指出:
除最后一条命令外,每个命令都作为单独的进程运行;Shell等待最后一条命令终止。
POSIX指出:
如果管道不在后台(请参见异步列表),则外壳程序应等待管道中指定的最后一个命令完成,也可以等待所有命令完成。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句