【问题标题】:Bash while loop stops unexpectedlyBash while 循环意外停止
【发布时间】:2015-08-06 01:08:34
【问题描述】:

我正在分析两个具有我不理解的行为的脚本:

#/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 ; }

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

#/bin/bash
tijd=${1-60}
oud=`ls -l $MAIL`
while : ; do
   nieuw=`ls -l $MAIL`
   echo $oud $nieuw
   sleep $tijd
done | cat

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

有什么区别?我认为这是管道和括号的问题,但我无法解释。

【问题讨论】:

  • Don't use ls 获取MAIL 目录的内容。见
  • 我说我在“分析”两个脚本。这只是编写 shell 脚本的练习,而不是真正使用的脚本。无论如何感谢您的信息:)

标签: linux bash while-loop


【解决方案1】:

问题在于 {read a b rest; ..} 块只执行一次,并且读取命令读取一行输入,而您希望它读取多行.

你想写的是这样的:

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

这是一种更“标准”的方式。它还避免了使用 pipe |,这会强制 {read ..} 块作为单独的进程运行,从而导致无法观察 strong> 主 shell 中 read 命令的效果。

的东西称为 进程替换。它基本上执行包含的块,同时将其输出捕获到临时文件中,然后返回该临时文件名。

【讨论】:

    【解决方案2】:

    pipe 之后带有read 的循环在第一次迭代后终止,因为调用了 SIGPIPE 信号,该信号发生在管道的 LHS 写入未读取输出的管道中因为 RHS 上的 read 周围没有 while 循环)。您的cat 示例不会退出,因为cat 连续 从输入中读取,而read 在读取一行后终止

    要理解这种行为,首先要减少你的例子:

    while : ; do pwd; done | { read -r line; echo $line; }
    /Users/admin
    

    所以read 在第一行之后终止。要验证这一点,请使用以下命令启用 pipefail

    set -o pipefail
    

    并检查退出状态:

    while : ; do pwd; done | { read -r line; echo "$line"; }
    echo $?
    141
    

    存在状态141 是由于SIGPIPE


    要解决此问题,现在在 while 循环内更改管道 RHS 上的 read

    while : ; do pwd; sleep 5; done | { while read -r line; do echo "$line"; done; }
    /Users/admin
    /Users/admin
    /Users/admin
    

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

    【讨论】:

    • 好的,但是为什么 cat 的例子可以工作。我通过 cat 也从标准输入中读取。有什么区别?在我的课程中,我还看到了一个在管道之后带有 awk 语句的示例,这也很有效。我看不出 read 与 cat 或 awk 有什么不同。
    • 你一定见过一个稍微不同的例子。只要while 循环继续产生输出,catawk 都不会“自愿”退出。
    • @WardVanAssche:这是因为cat连续从输入中读取,而read在读取一行后终止
    猜你喜欢
    • 2018-09-07
    • 1970-01-01
    • 2021-08-18
    • 2013-03-12
    • 1970-01-01
    • 1970-01-01
    • 2015-03-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多