2

Say I start a node.js process like so:

node script.js &

is there a way to pipe data into that process after it has started?

normally, we do this:

cat <file> | node script.js 

but the problem I am seeing is that sometimes the node.js process won't actually start up beforehand.

My goal is to ensure that the node.js process starts up no matter what, even if there is no data in the file.

So I was thinking of starting node.js process as background process, then connecting it to a pipe, not sure if that's possible.

Alexander Mills
  • 9,330
  • 19
  • 95
  • 180

1 Answers1

4

It sounds like you're looking for some variant of named pipes (fifos) created with mkfifo.

Then you can do something like this:

mkfifo my-pipe
node script.js < my-pipe &

Note that will block until something opens my-pipe for writing. So if you want script.js to be able to open the file (but not of course read anything from it yet), then you need to open it for writing; a trivial way is just to redirect a sleep to it (sleep 3650d > my-pipe &). This will also stop script.js from getting an EOF (end of file) until you kill the sleep (when nothing has a fifo open for write and all the data is gone, the reading side gets an EOF).

Now, you can feed it more lines whenever by writing to my-pipe. Any write that doesn't seek (or mmap, etc.) will work. You could test with echo 'DATA' > my-pipe.

So, taken together:

mkfifo my-pipe
node script.js < my-pipe &
sleep 3650d > my-pipe &
sleep_pid=$!
get-data-command > my-pipe     # placeholder for real command to get data
get-data-command > my-pipe
# and so on, for more data.
kill $sleep_pid                # kill the sleep, giving script.js an EOF.

As Wildcard points out, you may actually want script.js to open a listening socket and accept data that way. You can use Unix domain sockets if you want to avoid having to deal with authentication as you'd have to on a TCP socket (because Unix sockets use file permissions instead).

derobert
  • 107,579
  • 20
  • 231
  • 279
  • Interesting use of `sleep`, +1. It seems that's a bit hacky, though. Could it be that the Original Poster is actually trying to reinvent listening sockets? – Wildcard Jul 08 '17 at 04:57
  • I tried this `echo "dummy" | cat my.fifo | node script.js` ....... it still blocks, the node.js script will not start, I do not get it – Alexander Mills Jul 08 '17 at 05:26
  • my goal is to hook up the pipe, but to get the node.js script to start running, no matter what – Alexander Mills Jul 08 '17 at 05:27
  • @AlexanderMills that isn't the right syntax—the echo there doesn't make sense... I'll add in a complete example at the end.... – derobert Jul 08 '17 at 05:41
  • 1
    @AlexanderMills does that full example help? It shows how to start up the script, the sleep, and then how to feed data through the fifo. Finally, it shows how to kill the sleep, so it gets an EOF on the fifo. – derobert Jul 08 '17 at 05:46
  • @Wildcard true, I've added a note to the end of the question pointing that out. – derobert Jul 08 '17 at 05:49
  • Instead of this trick with `sleep` you can make `bash` open the fifo: `exec 3>my-pipe`. Then close it eventually: `3>&-`. – Kamil Maciorowski Jul 08 '17 at 05:54
  • @KamilMaciorowski yep, but I'm guessing OP doesn't actually want to leave the starting shell running, but rather leave the script running daemon-ish. – derobert Jul 08 '17 at 05:56
  • @derobert, in that case he would need `exec node script.js` rather than `node script.js &`, wouldn't he? – Wildcard Jul 08 '17 at 05:58
  • Don't we need `nohup` or something then? Closing the shell will kill all those background processes, I think. – Kamil Maciorowski Jul 08 '17 at 05:58
  • @Wildcard well, ideally he'd set up a systemd (etc.) service for it, but... Anyway, can't just exec it, because need to set up the sleep. Though I guess the sleep could come first. But getting it working at all comes first, I think. – derobert Jul 08 '17 at 06:01
  • 1
    @KamilMaciorowski depends on where its running from. If that's from a system startup script, cron @reboot, etc., then not needed. From an interactive login shell, might be—though `disown` would probably be sufficient. (Though at least my bash has huponexit unset, and I think that's the default). – derobert Jul 08 '17 at 06:03
  • @derobert OK then, upvoted. – Kamil Maciorowski Jul 08 '17 at 06:06