10

在设计执行某个任务的命令链时,我遇到了匿名管道的行为不像预期的问题。由于我正在运行的原始命令太复杂,无法在这里解释,我创建了一个显示问题的示例(我知道所有这些命令基本上什么都不做)。另外,我正在使用 pv 来显示数据是否实际从输入复制到输出。

cat /dev/zero | pv > /dev/null

这按预期工作。(将数据从 /dev/zero 复制到 /dev/null)

cat /dev/zero | tee /dev/null | pv > /dev/null

这也可以按预期工作(复制数据并将两个副本发送到 /dev/null)

cat /dev/zero | tee >(pv -c > /dev/null) | pv -c > /dev/null

此命令仅部分有效。虽然从 STDIN 到 STDOUT 的副本仍然有效(一个 pv 将在短时间内显示进度),但整个命令被匿名管道停止,该管道不接收任何内容,因此 tee 停止,因为其中一个输出无法写入(我通过让它写入文件而不是 /dev/null 来检查这一点)。

如果有人有一个想法,为什么这在 bash 中不起作用(如预期的那样?),我会很高兴得到帮助。

PS:如果我使用 zsh 而不是 bash,命令会按预期运行。不幸的是,需要在其上运行的系统没有 zsh,我无法在该系统上部署 zsh。

4

1 回答 1

1

当您<( ... )用于进程替换时,内部运行的进程没有控制终端。但pv总是向终端显示其结果;如果没有,它就会停止。

如果您执行您的代码,并在它运行时执行 a ps axf,您将看到如下内容:

23412 pts/16   S      0:00  \_ bash
24255 pts/16   S+     0:00      \_ cat /dev/zero
24256 pts/16   S+     0:00      \_ tee /dev/fd/63
24258 pts/16   S      0:00      |   \_ bash
24259 pts/16   T      0:00      |       \_ pv -c
24257 pts/16   S+     0:00      \_ pv -c

...它告诉您pv -c在进程替换中执行的(第二个下面的那个bash)处于T状态,停止。它正在等待有一个控制终端才能运行。它没有任何内容,因此它将永远停止,并bash最终停止向该管道发送数据。

于 2015-11-19T12:39:22.137 回答