【问题标题】:Electron kill child_process.exec电子杀死 child_process.exec
【发布时间】:2018-11-30 22:12:05
【问题描述】:

我有一个电子应用程序,它使用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);
});

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

【问题讨论】:

  • 期望的行为是什么,在应用关闭时自动终止子进程,还是让它继续运行直到完成然后自动关闭?
  • @mscdex 最好杀死所有子进程然后退出应用程序这可能吗?
  • 另外,当你调用 child processes 时,你应该得到 pids 并通过它杀死它。
  • @shriek 我试图获取 PID,但它只在进程结束时给我 PID。我一定做得不对。我已经编辑了我最初的问题以包含脚本的那部分内容。有任何想法吗?谢谢
  • 对于长时间运行的任务child_process.spawn{ detached: true } 更合适,我已经在我的电子应用程序中使用它。

标签: node.js electron


【解决方案1】:

因此,在每个人都很棒的 cmets 之后,我能够通过一些添加来更新我的代码以使其正常工作,所以我将我的更新发布给其他人。

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

感谢大家的帮助。

【讨论】:

  • 嘿,这是一个非常好的解决方案,解决了我遇到的问题。我很失望当 Renderer 进程退出时没有“析构函数”功能,它会使这样的清理更容易!
【解决方案2】:

ChildProcess 在进程完成时发出一个exit 事件 - 如果您跟踪数组中的当前进程,并在exit 事件触发后让它们自行删除,您应该能够只@当您退出应用程序时,987654324@ 超过其余运行 ChildProcess.kill() 的代码。

这可能不是 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();
  }
});

编辑:正如 shreik 在评论中提到的,您也可以只将 PID 存储在数组中而不是 ChildProcess 对象中,然后使用 process.kill(pid) 来杀死它们。可能效率更高一点!

【讨论】:

  • 我一直收到一个错误说 proc.kill();不是函数
【解决方案3】:

另一种解决方案。如果你想继续使用exec()

为了杀死exec() 运行的子进程,请查看模块ps-tree。他们解释正在发生的事情。

在 UNIX 中,进程可以通过使用 exit 调用终止,它是 父进程可以通过使用 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 })));
});

【讨论】:

    猜你喜欢
    • 2012-01-03
    • 2016-01-24
    • 1970-01-01
    • 2010-12-08
    • 1970-01-01
    • 1970-01-01
    • 2021-09-21
    • 2019-01-18
    • 2014-09-30
    相关资源
    最近更新 更多