How to pipe commands to a process running in the background?

I guess that is impossible with a "real" pipeline.

Instead you can use a FIFO (named pipe, see man mkfifo) or (more elegant but more complicated) a Unix socket (AF_UNIX).

./background-proc </path/to/fifo &
cat >/path/to/fifo
# typing commands into cat

I am not a developer so my only relation to sockets is socat. But that may help as a start.

You need a "server" which communicates with your program. Such a pipeline would be started in the background:

socat UNIX-LISTEN:/tmp/sockettest,fork STDOUT | sed 's/./&_/g'

The sed is just for testing.

Then you start one or more

socat STDIN UNIX-CONNECT:/tmp/sockettest

If you have a program which generates the commands for your background program then you would use a pipeline here, too:

cmd_prog | socat STDIN UNIX-CONNECT:/tmp/sockettest

The advantage in comparison with a FIFO is that (with the option fork on the server side) you can disconnect and reconnect the client. Using a FIFO you would need tricks for keeping the receiving side running:

while true; do cat /path/to/fifo; done | background_prog

If you wanted to start the command in background and have a file descriptor to send data to it via a pipe.

With zsh or bash, you could use a redirection to a process substitution.

exec 3> >(cmd)

And then send output with:

echo something >&3

And tell end-of-file with exec 3>&-.

Sill with zsh and bash, you can also do:

{ coproc cmd >&3 3>&-; } >&3

That is start cmd as a co-process, which starts the process with two pipes, one for input, one for output, but here as we only want the one for input, we restore cmd's stdout to that of the rest of the shell.

To send output:

echo something >&p # with zsh
echo something >&"${COPROC[1]}" # with bash

With yash, you can use process redirection:

exec 3>(cmd)

With any Bourne-like shell, you can always do:

{ {
  echo something >&3
  echo whatever
  ...
} 3>&1 >&4 4>&- | cmd; } 4>&1

That's not exactly the same as starting cmd in background and run commands that send their output to cmd in that those commands run in a subshell and, for interactive shells, cmd is also in the foreground (is affected by Ctrl+C for instance), but apart from that, it's mostly functionally equivalent.


Generally, you can't change what files a process has open and where they point to from outside that process after the process has been started. There are exceptions in the form of debugging interfaces and tools like repty that can do this in a limited fashion.

When you started your program with

myLoop &

its standard input was connected to your terminal (because you didn't redirect it anywhere else) and that's not going to change to a pipe.

See also How to attach terminal to detached process?