'Spawn and kill a process in node.js
I'm trying to spawn a process in javascript, and kill it after some time (for testing purposes).
In the end, the process will be a infinite loop that I need to restart with different arguments at specified time, so I thought that spawning the process and killing it was the best way to do this.
My test code is:
var spawn=require('child_process').spawn
, child=null;
child=spawn('omxplayer', ['test.mp4'], function(){console.log('end');}, {timeout:6000});
console.log('Timeout');
setTimeout(function(){
console.log('kill');
child.kill();
}, 1200);
child.stdout.on('data', function(data){
console.log('stdout:'+data);
});
child.stderr.on('data', function(data){
console.log('stderr:'+data);
});
child.stdin.on('data', function(data){
console.log('stdin:'+data);
});
The result is:
#~$ node test.js
Timeout
kill
But I still need to send ctrl+C to end the program. What am I missing?
On Raspbian, node 0.10.17, omxplayer is a binary (video player).
I tried:
- Added
chmod +xto the app. - Launched as root.
- Paused stdin of the child process. Using all terminate-related signal in the kill command.
I also launched a ps command while the app was running:
2145 bash
2174 node
2175 omxplayer
2176 omxplayer.bin
2177 ps
So omxplayer is a wrapper, who don t kill it's child process when it end, is there any way to get the pid of the wrapped process?
Still biting dust, tried this:
spawn('kill', ['-QUIT', '-$(ps opgid= '+child.pid+')']);
Which I thought would kill all children of omxplayer, I don t know if using spawn like that is wrong or if it's the code that doesn't work.
The last edit I made was the good answer, but had to be edited a bit.
I created a sh file (with execute right) like this:
PID=$1
PGID=$(ps opgid= "$PID")
kill -QUIT -"$PGID"
Which I start like this:
execF('kill.sh', [child.pid], function(){
console.log('killed');
});
Instead of child.kill.
I'm not sure if it s the best way to do, nor if the code is clean, but it does work.
I'll accept any answer which make it in a cleaner way or, even better, without having to execute a file.
Solution 1:[1]
There is a really neat npm package called tree-kill which does this very easily and effectively. It kills the child process, and all child processes that child may have started.
var kill = require('tree-kill');
const spawn = require('child_process').spawn;
var scriptArgs = ['myScript.sh', 'arg1', 'arg2', 'youGetThePoint'];
var child = spawn('sh', scriptArgs);
// some code to identify when you want to kill the process. Could be
// a button on the client-side??
button.on('someEvent', function(){
// where the killing happens
kill(child.pid);
});
Solution 2:[2]
I've had exactly the same issue as you with omxplayer and the solution in this blog post worked for me.
var psTree = require('ps-tree');
var kill = function (pid, signal, callback) {
signal = signal || 'SIGKILL';
callback = callback || function () {};
var killTree = true;
if(killTree) {
psTree(pid, function (err, children) {
[pid].concat(
children.map(function (p) {
return p.PID;
})
).forEach(function (tpid) {
try { process.kill(tpid, signal) }
catch (ex) { }
});
callback();
});
} else {
try { process.kill(pid, signal) }
catch (ex) { }
callback();
}
};
// elsewhere in code
kill(child.pid);
Solution 3:[3]
Why don't you just send the 'q' value in the stdin pipe ? It kill the omxplayer process.
Solution 4:[4]
You've spawned a child process which was successfully killed. However, your main thread is still executing, which is why you have to press Ctrl+C.
Solution 5:[5]
Finally, I found how to do it without script:
exec('pkill omxplayer', function(err, stdout, stderr){
if (stdout){console.log('stdout:'+stdout);}
if (stderr){console.log('stderr:'+stderr);}
if (err){throw err;}
//...
}
Solution 6:[6]
Try to use child_process.execFile() method from here.
The child_process.execFile() function is similar to child_process.exec() except that it does not spawn a shell. Rather, the specified executable file is spawned directly as a new process making it slightly more efficient than child_process.exec().
It works in my case.
Solution 7:[7]
You must specify the signal:
child.kill('SIGKILL')
https://nodejs.org/api/child_process.html#child_process_subprocess_kill_signal
Solution 8:[8]
In node:16 I was required to destroy() (pause() i not enough) the std channels before sending kill(). Like this:
cmd.stdout.destroy();
cmd.stderr.destroy();
cmd.kill('SIGINT');
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | mikenolan |
| Solution 3 | Superdrac |
| Solution 4 | apscience |
| Solution 5 | Rajesh Ujade |
| Solution 6 | Community |
| Solution 7 | Dharman |
| Solution 8 |
