我打算将程序的输出通过管道传输到while read VAR循环中,并break在找到模式时,但事实并非如此。
概念证明:
inotifywait -qm -e create . | while read line; do echo $line; break; done
./ CREATE newfile
Run Code Online (Sandbox Code Playgroud)
..
tail -f /var/log/syslog | while read line; do echo $line; break; done
Nov 6 22:44:05 section9 ntpdate[2381]: adjust time server 91.189.89.199 offset 0.272779 sec
Run Code Online (Sandbox Code Playgroud)
无论源程序输出什么,这些都永远不会退出。set -x预先设置表明循环永远不会迭代到第二个read。$BASH_SUBSHELL在这些示例中为 1。
tail、inotifywait、 等不应该接收 SIGPIPE 并退出吗?
请注意,进程替换 ( while read ... break; done < <(tail -f ...)) 工作正常。$BASH_SUBSHELL在这种情况下为 0。
Joh*_*024 13
关键是,在 bash 下(其他 shell 可能有所不同),直到管道中的所有命令都完成后,管道才会终止。
为了理解,让我们考虑:
inotifywait -qm -e create . | while read line; do echo $line; break; done
Run Code Online (Sandbox Code Playgroud)
当read读取一行时,它被回显,然后break被执行,最后一个进程终止。但是,第一个过程会继续,直到写入 stdout 失败。因此,循环将至少持续到inotifywait尝试写入其第二行输出。由于缓冲的变化无常,即使那样也可能不会发生。在发现发生之前可能需要几行。当尝试写入失败时,会发出 SIGPIPE。
现在,考虑另一种情况:
while read line; do echo $line; break; done < <(inotifywait -qm -e create .)
Run Code Online (Sandbox Code Playgroud)
在这里,没有管道。当break被执行时,while循环完成。
从“管道”部分man bash:
shell等待管道中的所有命令终止......
这种行为是由 做出的选择bash。它不是 POSIX 强制要求的。 POSIX指出:
如果管道不在后台(参见异步列表),shell 将等待管道中指定的最后一个命令完成,也可能等待所有命令完成。
| 归档时间: |
|
| 查看次数: |
6990 次 |
| 最近记录: |