流程替换被管道破坏

时间:2019-02-14 15:35:15

标签: bash pipe io-redirection command-substitution

我今天做了一件愚蠢的事:

read x <( ps -fu $LOGNAME | grep ' /usr/bin/ps$' )

它挂了,再也没有回来。我不得不打破它。

你们中的有些人现在正对我开怀大笑。 :)

我只花了一分钟的时间就知道为什么这行不通,但是我想把它作为一个问题发布(我也将在下面简短回答,但也可以自由发表),以防它绊倒了某人。

2 个答案:

答案 0 :(得分:2)

如果将read x替换为cat,要花多长时间?

问题是您执行了以下命令:

read x /dev/fd/63

(通过运行echo read x <(…)可以看到) read坐在那里,等着您输入要放入x的内容。

$ read x <( ps -fu $LOGNAME | grep ' /usr/bin/ps$' )
asc def
-bash: read: `/dev/fd/63': not a valid identifier
$

shell正在等待您键入内容,仅此而已。你不耐烦。

如果要将输入重定向到read命令,则需要一个单独的<来执行此操作(我需要更改grep正则表达式以获取任何输出):< / p>

$ read x < <( ps -fu $LOGNAME | grep ' /usr/bin/ps' )
$ echo $x
501 16166 16164 0 7:50AM ttys000 0:00.00 grep /usr/bin/ps
$

请注意,如上一条read命令所示,使用直接重定向时,将只读取来自进程替换的第一行输入;其余的将丢失。如果您需要在while循环中处理多行,则需要重定向整个循环:

while read x
do
    whatever -with "$x"
done < <(ps -fu $LOGNAME | grep ' /usr/bin/ps')

另请参阅Process Substitution上的Bash手册,其中指出:

  

进程替换允许使用文件名引用进程的输入或输出。

结果是一个文件名(至少在Mac上,它以/dev/fd/xx的形式表示xx的某些数值)可用于引用过程中命令的输出替代。

答案 1 :(得分:-1)

进程替换将标准输出重定向到读取。没有任何东西进入grep的管道中。

因此,grep正在耐心地等待并阻塞,并且命令链从未完成。

我是这样做的:

read x pid x <<< "$( ps -fu $LOGNAME | grep ' /usr/bin/ps$' )"

那很好。整个过程运行,创建字符串输出,然后然后将结果传递到read

必须注意您的数据流。 :)