我有一个使用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();
}
});
我应该在某处添加支票吗?
感谢您的帮助
EDITED
我似乎无法获得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);
});
我应该尝试以不同的方式获取它吗?
答案 0 :(得分:11)
所以在每个人都发表了很好的评论之后,我能够通过一些新增功能来更新我的代码,以便让它发挥作用,所以我会为其他人发布我的更新。
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 );
}
});
});
});
感谢大家的帮助。
答案 1 :(得分:4)
ChildProcess
会发出exit
事件 - 如果您跟踪数组中的当前进程,并在exit
事件触发后将它们自行删除,那么当您退出应用时,应该能够foreach
只剩下ChildProcess.kill()
个{。}}。
这可能不是100%的工作代码/不是最好的做事方式,因为我现在无法测试它,但它应该足以让你走上正确的道路。 / p>
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();
}
});
编辑:正如shreik在评论中提到的那样,您也可以将PID存储在数组中而不是ChildProcess
个对象中,然后使用process.kill(pid)
来终止它们。可能会更有效率!
答案 2 :(得分:1)
另一种解决方案。如果您想继续使用exec()
为了终止exec()
运行的子进程,请查看模块ps-tree
。他们突然发生了正在发生的事情。
在UNIX中,进程可以通过使用退出调用终止,并且它可以终止 父进程可以使用等待系统调用等待该事件。 wait系统调用返回已终止的进程标识符 孩子,让父母告诉可能有多少孩子 终止。但是,如果父母终止了,那么所有孩子都有 被指定为新父进程的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 })));
});