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.
In computer science, an anonymous pipe is a simplex FIFO communication channel that may be used for one-way interprocess communication (IPC). An implementation is often integrated into the operating system's file IO subsystem.
In Linux, we have two types of pipes: pipes (also known as anonymous or unnamed pipes) and FIFO's (also known as named pipes).
How to create an unnamed pipe? call the following function (system call): int pipe (int fd[2]); The input parameter is an array of two file descriptors fd[0] and fd[1]. A file descriptor is in fact an integer value.
Also called an anonymous pipe (or simply pipe), it is typically used to communicate between a parent process and a child process. Within SAS, the SAS System is the parent process that invokes (and reads data from) a child process. named pipe. handles one-way or two-way communication between two unrelated processes.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With