Bash while while循环意外停止

war*_*dva 5 linux bash while-loop

我正在分析两个脚本,其中包含一些我不理解的行为:

#/bin/bash
tijd=${1-60}
oud=`ls -l $MAIL`
while : ; do
   nieuw=`ls -l $MAIL`
   echo $oud $nieuw
   sleep $tijd
done | { read a b rest ; echo $a ; echo $b ; echo $rest ; }
Run Code Online (Sandbox Code Playgroud)

此脚本中的while循环在一次迭代后停止.

#/bin/bash
tijd=${1-60}
oud=`ls -l $MAIL`
while : ; do
   nieuw=`ls -l $MAIL`
   echo $oud $nieuw
   sleep $tijd
done | cat
Run Code Online (Sandbox Code Playgroud)

此脚本中的while循环是无限的.

有什么不同?我认为它与管道和括号有关,但我无法解释它.

anu*_*ava 3

带有readafter管道的循环在第一次迭代后终止,因为调用了SIGPIPEread信号,该信号发生在管道的 LHS 写入到其输出未被读取的管道中,因为RHS 上没有 while 循环)。我们的示例cat不会退出,因为cat 连续读取输入,而 as在读取一行后read 终止。

要理解这种行为,首先减少您的示例:

while : ; do pwd; done | { read -r line; echo $line; }
/Users/admin
Run Code Online (Sandbox Code Playgroud)

所以read在第一行之后终止。要验证此启用,pipefail请使用:

set -o pipefail
Run Code Online (Sandbox Code Playgroud)

并检查退出状态:

while : ; do pwd; done | { read -r line; echo "$line"; }
echo $?
141
Run Code Online (Sandbox Code Playgroud)

存在状态141是由于SIGPIPE.


要解决此问题,请立即更改readwhile 循环内管道的 RHS:

while : ; do pwd; sleep 5; done | { while read -r line; do echo "$line"; done; }
/Users/admin
/Users/admin
/Users/admin
Run Code Online (Sandbox Code Playgroud)

现在您将根本看不到命令​​退出,因为while read它不断从管道的 LHS 捕获所有数据。