The BEAM/Erlang/Elixir-way is to open a port with the command (you can pass env vars by hoisting into a shell call for example) then just hold the port passing data back and forth if necessary (or not if not), then just close the port when done (which gets closed with the BEAM system shutting down too).
Closing the port closes the pipe between the processes, which is stdin to the other process. Any process that correctly obeys the POSIX standard will either fork when opened to persist, or will die when it’s stdin closes (after cleaning up of course).
However a lot of node programmers do not like to follow the standards and like to live like zombies, not forking, not closing when stdin closes, nothing, so you get stuff like what you are experiencing now.
I’d probably just write a shell script and have the port open that, just have the shell script call yarn start with whatever env vars (that you could pass in even), background it, get it’s PID (
$!) and have it just ‘wait’ on its stdin (
cat is perfectly fine for this) and when it closes (
cat would exit) then just kill the pid that you saved earlier and be done.
Blame this on node authors not following the standards properly.
Or you can use something like erlexec to open the node process and have ‘it’ send a kill signal when done. it is an easy to use library that uses ports and a runner program to manage external programs like yarn that are not programmed correctly.