Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bash Anonymous Pipes

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.

like image 715
Fabraxias Avatar asked Nov 17 '15 09:11

Fabraxias


People also ask

What is anonymous pipe in Linux?

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.

Is FIFO unnamed pipe?

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 can you create unnamed pipes in Unix?

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.

What is the difference between named pipe and anonymous pipe?

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.


1 Answers

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.

like image 119
Juan Cespedes Avatar answered Sep 19 '22 00:09

Juan Cespedes