Bash Anonymous Pipes

2019-04-05 08:13发布

When designing a chain of commands to perform a certain task, i ran into the problem that anonymous pipes do not behave like expected. As the original command that i am running is too complex to explain here, i've created an example that shows the problem (i know that all these commands are doing basically nothing). Also, i am using pv to show whether the data is actually copied from input to output.

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

This works as expected. (copy data from /dev/zero to /dev/null)

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

This also works as expected (duplicate the data and send both copies to /dev/null)

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

This command only partially works. While the copy from STDIN to STDOUT still works, (one pv will show progress for a short time), the whole command gets stalled by the anonymous pipe, which does not receive anything and thus tee stalls as one of the outputs cannot be written to (I checked this by letting it write to files instead of /dev/null).

If anyone has an Idea why this does not work (as expected ?) in bash, i'd be glad for the help.

PS: If I use zsh instead of bash, the command runs as expected. Unfortunately, the system this needs to run on has no zsh and there is no way for me to get zsh on that system deployed.

1条回答
我想做一个坏孩纸
2楼-- · 2019-04-05 09:07

Whe you use <( ... ) for process substitution, the process running inside does not have a controlling terminal. But pv always shows its results to the terminal; if there isn't any, it gets stopped.

If you execute your code and, while it is running, do a ps axf, you will see something like this:

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

...which tells you that the pv -c executed inside the process substitution (the one below the second bash) is in T state, stopped. It is waiting to have a controlling terminal in order to run. It does not have any, so it will stop forever, and bash eventually stops sending data to that pipe.

查看更多
登录 后发表回答