child_process.exec
を使用して長時間実行されるタスクを実行する電子アプリがあります。これらのタスク中にユーザーがアプリを終了するタイミングを管理するのに苦労しています。
それらが私のアプリを終了するか、閉じるを押すと、子プロセスは終了するまで実行を続けますが、電子アプリウィンドウはすでに閉じて終了しています。
プロセスがまだ実行中であることをユーザーに通知し、プロセスが終了したらアプリウィンドウを閉じる方法はありますか?
main.js
にあるのは、標準コードだけです。
// Quit when all windows are closed.
app.on('window-all-closed', function() {
// On OS X it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform != 'darwin') {
app.quit();
}
});
どこかに小切手を追加する必要がありますか?
ご協力いただきありがとうございます
編集済み
child_process
のPIDは、完了するまで取得できないようです。これは私のchild_process
コードです
var loader = child_process.exec(cmd, function(error, stdout, stderr) {
console.log(loader.pid)
if (error) {
console.log(error.message);
}
console.log('Loaded: ', value);
});
別の方法で取得しようとすべきですか?
それで、みんなの素晴らしいコメントの後、私はそれを機能させるためにいくつかの追加で私のコードを更新することができたので、他のみんなのために私の更新を投稿しています。
1)child_process.execからchild_process.spawnに変更します
var loader = child_process.spawn('program', options, { detached: true })
2)Electron ipcRendererを使用して、モジュールからmain.jsスクリプトに通信します。これにより、PIDをmain.jsに送信できます
ipcRenderer.send('pid-message', loader.pid);
ipcMain.on('pid-message', function(event, arg) {
console.log('Main:', arg);
pids.Push(arg);
});
3)それらのPIDをアレイに追加します
4)main.jsに次のコードを追加して、アプリを終了する前に配列に存在するPIDをすべて強制終了します。
// App close handler
app.on('before-quit', function() {
pids.forEach(function(pid) {
// A simple pid lookup
ps.kill( pid, function( err ) {
if (err) {
throw new Error( err );
}
else {
console.log( 'Process %s has been killed!', pid );
}
});
});
});
みんなの助けをありがとう。
ChildProcess
は、プロセスが終了するとexit
イベントを発行します。配列内の現在のプロセスを追跡し、exit
イベントが発生した後、それらを削除する場合は、アプリを終了すると、ChildProcess.kill()
を実行している残りの配列をforeach
だけ実行できるはずです。
私は今それをテストする立場にないので、これは100%動作するコードではないかもしれません/物事を行うための最良の方法ではありませんが、正しい道を歩むには十分なはずです。
_var processes = [];
// Adding a process
var newProcess = child_process.exec("mycommand");
processes.Push(newProcess);
newProcess.on("exit", function () {
processes.splice(processes.indexOf(newProcess), 1);
});
// App close handler
app.on('window-all-closed', function() {
if (process.platform != 'darwin') {
processes.forEach(function(proc) {
proc.kill();
});
app.quit();
}
});
_
EDIT: shreikがコメントで述べたように、ChildProcess
オブジェクトの代わりにPIDを配列に格納し、process.kill(pid)
を使用してそれらを強制終了することもできます。もう少し効率的かもしれません!
別の解決策。 exec()
を使い続けたい場合
exec()
によって実行されている子プロセスを強制終了するには、モジュール _ps-tree
_ を調べてください。彼らは何が起こっているのかを説明します。
uNIXでは、プロセスはexit呼び出しを使用して終了する場合があり、その親プロセスは、waitシステム呼び出しを使用してそのイベントを待機する場合があります。待機システムコールは、終了した子のプロセスIDを返すため、親は、おそらく多くの子のどれが終了したかを通知します。ただし、親が終了した場合、そのすべての子は新しい親としてinitプロセスを割り当てます。したがって、子には、ステータスと実行統計を収集するための親がまだあります。 (「オペレーティングシステムの概念」から)
解決策:_
ps-tree
_を使用して、_child_process
_が開始した可能性のあるすべてのプロセスを取得します。
exec()
は実際には次のように機能します:
_function exec (cmd, cb) {
spawn('sh', ['-c', cmd]);
...
}
_
例を確認して、ニーズに合わせて調整してください
_var cp = require('child_process'),
psTree = require('ps-tree');
var child = cp.exec("node -e 'while (true);'", function () { /*...*/ });
psTree(child.pid, function (err, children) {
cp.spawn('kill', ['-9'].concat(children.map(function (p) { return p.PID })));
});
_