电子杀死child_process.exec

时间:2016-03-16 09:27:28

标签: node.js electron

我有一个使用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);
});

我应该尝试以不同的方式获取它吗?

3 个答案:

答案 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 })));
});