当子进程更改磁盘上的文件时,Bash 循环失败

当子进程更改磁盘上的文件时,Bash 循环失败

这段代码已经失效好几天了,我都快疯了。也许有人能帮忙。

我编写了一个 bash 脚本,用于循环遍历托管 Linux 系统。它调用另一个 bash 脚本来获取包含 8 个字段的记录:

local cmd="/usr/local/sbin/zlsexpirations -s -l $nodeList"
local expList                            # list of nodes and expiration days
expList=`$cmd`                           # run the command

...

因此变量“expList”包含记录。然后它应该循环遍历所有记录,并将它们传递给函数 zSetOneSystem(),以便一次处理一个系统。这是主循环(expList 周围的双引号是传递记录所需的,而不仅仅是一个标记):

local nextLine
while read nextLine; do
  zVerbose "calling zSetOneSystem $nextLine"
  zSetOneSystem $nextLine
done < <(echo "$expList")

这是我第一次尝试循环:

echo "$expList" |
while read nextLine; do
  zVerbose "calling zSetOneSystem $nextLine"
  zSetOneSystem $nextLine
done

上述两种循环都有以下行为:

  1. 如果传递了 -n 标志(无操作),则循环运行顺利直至完成。
  2. 如果未传递该标志,则循环运行,处理一个系统(导致磁盘上的文件被更改),但然后循环停止。

当我跟踪它时,“读取下一行”失败。我在循环后打印出“expList”,所有记录仍然在原位。子进程怎么能以这种方式影响父进程?我已将其缩小到两个嵌套在 zSetOneSystem() 中的 bash 脚本调用。如果我注释掉这两个,循环就会成功。如果我取消注释这两个 bash 脚本中的任何一个,循环就会像描述的那样失败。很奇怪。

任何帮助将不胜感激。

谢谢。

答案1

您正在将输入传递给while标准输入(文件描述符 0)的循环。任何命令里面从标准输入读取的循环将消耗该流,使得内容read第二次不可用。这是将标准输入传递给实际上是多个命令的命令时常见的问题。解决此问题的最简单方法是使用循环内的命令不太可能使用的文件描述符,例如:

while read -u "$fd" line
do
    commands…
done {fd}< <(input command(s))

相关内容