I have a shell script start.sh
whose job is to spawn multiple java processes in the background and then exit normally like so:
java -jar jar1.jar &
java -jar jar2.jar &
...
exit 0
A bunch of output is printed:
Starting jar1
Starting jar2
...
Now I want nodejs to invoke start.sh
keep track of the output so I can act on it when starter.sh
is done
Problem is Nodejs considers starter.sh
to be done only when all the java processes that have been started are dead.
Which is weird because from a shell, starter.sh
exits right away and does not have any relations with the java processes anymore
How I can make starter.sh
behave the same way when invoked from node?
This is the code I use to spawn starter.sh
:
const process = spawn('starter.sh', []);
process.stdout.on('data', (data) => {
console.log(`stdout: ${data}`);
// prints 'Starting jarx' like expected
});
process.stderr.on('data', (data) => {
console.log(`stderr: ${data}`);
});
process.on('close', (code) => {
console.log(`child process exited with code ${code}`);
// Not called unless all the spawned java processes are dead :(
});
I a have feeling that my problem is related to the child processes sharing stdio
with the node parent. Indeed where would the java
processes write if they didn't have a stdout
to write to. Thus node has to wait for them to be done to consider starter.sh
done
I have settled for giving the child process it's own stdio
and write starter.sh
output to a file:
const out = fs.openSync('/tmp/command.out', 'w');
const err = fs.openSync('/tmp/command.err', 'w');
const process = spawn(command, args, {detached: true, stdio: ['ignore', out , err]});
process.unref();
process.on('close', (code) => {
console.log(`child process exited with code ${code}`);
console.log(fs.readFileSync('/tmp/command.out', 'utf8');
console.log(fs.readFileSync('/tmp/command.err', 'utf8'));
});
That way the close
call back is called as soon as starter.sh
is done and I can still access it's output.