Communicate backwards in a pipe

No. A pipeline is a one-way communication channel. That's why it's called a "pipeline"; you couldn't send oil back up a pipeline if you tried, either.

However, if bar.js has to talk to foo.js too, you do have a few options:

  • Create a unix domain socket instead of a pipeline, and start both foo.js and bar.js separately (i.e., don't pipe the output of foo.js into bar.js anymore). I don't know how you do that from node, but essentially a unix domain socket is a network socket that uses filenames rather than IP addresses and works inside the kernel. Sockets are meant for bidirectional communication, but require more setup than a simple pipe (e.g., a listening socket can talk to multiple instances of bar.js). You may find unix domain sockets in the filesystem, but it's not strictly necessary (and indeed Linux allows creating a unix domain socket without a trace on the filesystem).
  • Use mkfifo to create a named pipe (or use some node API to create one, if that exists; again, I do not know node). Then, in foo.js, open that named pipe and read from it. Your bar.js script can open the same named pipe and write to it.

The latter will be easiest to transition to, since you still use file I/O (opening a named pipe requires opening a file on the filesystem), but would still be unidirectional (although you'd have two channels, one in each direction). The former is slightly cleaner and also allows you to more easily migrate one of the two scripts to a different host if that ever should become necessary.

At any rate, if your scripts are now communicating bidirectionally, then for clarity I would suggest you start them as separate processes, rather than having one process pipe into the other. IMHO, they're equal partners now, and your command line should show that. That's just a detail though, and certainly not technically required.

On systems where pipes are bidirectional (NetBSD, FreeBSD, SVR4-derived Unices (all those where pipes use STREAMS at least), but not Linux):

node foo.js <&1 | node bar.js >&0

Beside the named pipe already mentioned, you can also use a socketpair:

perl -MSocket -e '
  socketpair(A, B, AF_UNIX, SOCK_STREAM, PF_UNSPEC);
  if (fork) {
    open STDIN, "<&A";
    open STDOUT, ">&B";
    exec "node", "foo.js";
  } else {
    open STDIN, "<&B";
    open STDOUT, ">&A";
    exec "node", "bar.js";

Or two unnamed pipes, for instance using a coproc.

With zsh:

coproc node foo.js
node bar.js <&p >&p


node foo.js |&
node bar.js <&p >&p

bash 4+:

coproc node foo.js
node bar.js <&"${COPROC[0]}" >&"${COPROC[1]}"

Or with yash's x>>|y pipe operator:

{ node foo.js <&3 3<&- | node bar.js 3<&-; } >>|3