簡體   English   中英

在 node.js 中產生並殺死一個進程

[英]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到應用程序。
  • 以 root 身份啟動。
  • 子進程的暫停標准輸入。 在 kill 命令中使用所有與終止相關的信號。

我還在應用程序運行時啟動了一個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');

查看exec()源代碼如何處理kill()

嘗試使用這里的child_process.execFile()方法。

child_process.execFile() 函數與 child_process.exec() 類似,只是它不產生 shell。 相反,指定的可執行文件作為新進程直接生成,使其比 child_process.exec() 稍微高效一些。

它適用於我的情況。

可能不完全適合您的用例的替代方法是將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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM