[英]Spawn and kill a process in node.js
我試圖在 javascript 中生成一個進程,並在一段時間后將其終止(出於測試目的)。
最后,這個過程將是一個無限循環,我需要在指定的時間用不同的 arguments 重新啟動,所以我認為產生這個過程並殺死它是最好的方法。
我的測試代碼是:
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);
});
結果是:
#~$ node test.js
Timeout
kill
但是我還是需要發送ctrl+C來結束程序。 我錯過了什么?
在 Raspbian 節點 0.10.17 上,omxplayer 是一個二進制文件(視頻播放器)。
我試過了:
chmod +x
到應用程序。 我還在應用程序運行時啟動了一個ps
命令:
2145 bash
2174 node
2175 omxplayer
2176 omxplayer.bin
2177 ps
所以omxplayer是一個wrapper,誰不在結束的時候殺掉它的子進程,有沒有辦法得到wrapped進程的pid?
仍然咬灰塵,試過這個:
spawn('kill', ['-QUIT', '-$(ps opgid= '+child.pid+')']);
我認為這會殺死 omxplayer 的所有孩子,我不知道這樣使用 spawn 是錯誤的還是代碼不起作用。
我所做的最后一次編輯是很好的答案,但必須進行一些編輯。
我創建了一個 sh 文件(具有執行權限),如下所示:
PID=$1
PGID=$(ps opgid= "$PID")
kill -QUIT -"$PGID"
我這樣開始:
execF('kill.sh', [child.pid], function(){
console.log('killed');
});
而不是child.kill
。
我不確定這是否是最好的方法,也不確定代碼是否干凈,但它確實有效。
我接受任何以更清晰的方式或更好的方式進行回答,而無需執行文件。
參考這個討論
一旦您開始在 stdin 上監聽數據,node 將等待 stdin 上的輸入,直到它被告知不要這樣做。 當用戶按下 ctrl-d(表示輸入結束)或程序調用 stdin.pause() 時,節點停止等待 stdin。
節點程序不會退出,除非它無事可做或等待。 發生的事情是,它正在等待標准輸入,因此永遠不會退出。
嘗試將您的 setTimeout 回調更改為
console.log('kill');
child.stdin.pause();
child.kill();
我希望這應該有效。
有一個非常簡潔的 npm 包,稱為tree-kill
,它可以非常輕松有效地完成此操作。 它會殺死子進程以及該子進程可能已啟動的所有子進程。
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);
});
我在使用 omxplayer 時遇到了與您完全相同的問題, 這篇博文中的解決方案對我有用。
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);
為什么不直接在標准輸入管道中發送“q”值? 它會殺死 omxplayer 進程。
您已經生成了一個已成功終止的子進程。 但是,您的主線程仍在執行,這就是您必須按 Ctrl+C 的原因。
最后,我找到了沒有腳本的方法:
exec('pkill omxplayer', function(err, stdout, stderr){
if (stdout){console.log('stdout:'+stdout);}
if (stderr){console.log('stderr:'+stderr);}
if (err){throw err;}
//...
}
在node:16
中,我被要求在發送kill()
之前destroy()
( pause()
我還不夠) std
通道。 像這樣:
cmd.stdout.destroy();
cmd.stderr.destroy();
cmd.kill('SIGINT');
嘗試使用這里的child_process.execFile()
方法。
child_process.execFile() 函數與 child_process.exec() 類似,只是它不產生 shell。 相反,指定的可執行文件作為新進程直接生成,使其比 child_process.exec() 稍微高效一些。
它適用於我的情況。
您必須指定信號:
child.kill('SIGKILL')
https://nodejs.org/api/child_process.html#child_process_subprocess_kill_signal
可能不完全適合您的用例的替代方法是將detached
選項設置為true
並忽略標准輸入。 然后,您可以稍后使用其 PID 終止您的進程。
const process = child_process.spawn(
'omxplayer', ['test.mp4'],
{
detached: true,
stdio: ['ignore', 'pipe', 'pipe'],
}
);
setTimeout(() => {
child_process.spawnSync(
'kill', [process.pid.toString()]
);
}, 1200);
結合並澄清@Superdrac + @Evil的答案。
如果您正在運行具有退出命令的程序,請嘗試直接使用該命令。
例如,大多數程序都需要q
+ enter
退出。 所以你可以運行:
child.stdin.write("q\n");
並且該過程將以相同的方式解釋它,從而使其能夠自行清理。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.