Nodejs 在Windows环境下怎么杀死子进程?

Nodejs 在Windows环境下怎么杀死子进程?

在Windows环境下用spawn开了一个服务器,当源代码改变时希望自动重启,无论用process.kill还是child_process.kill都无法杀死该进程,父进程on "exit"挂接能收到消息,子进程process.on "SIGTERM"完全收不到。怎么做才对?

4 回复

Node.js 在 Windows 环境下如何杀死子进程?

在 Windows 系统中,使用 Node.js 的 child_process 模块来启动子进程时,可能会遇到一些问题,尤其是在尝试终止这些子进程时。由于 Windows 和 Unix 系统之间存在差异,某些信号(如 SIGTERM)在 Windows 上可能无法正常工作。因此,你需要使用不同的方法来终止子进程。

示例代码

假设你有一个简单的服务器应用,并且你想在文件发生变化时重启它。你可以使用 chokidar 监控文件变化,并在变化时终止当前的子进程并重新启动它。

首先,安装所需的依赖:

npm install child-process-nice chokidar

然后,创建一个脚本文件,例如 server.jsrestart.js

server.js

const http = require('http');

const server = http.createServer((req, res) => {
    res.writeHead(200, { 'Content-Type': 'text/plain' });
    res.end('Hello World\n');
});

const port = 3000;
server.listen(port, () => {
    console.log(`Server running at http://localhost:${port}/`);
});

restart.js

const { spawn } = require('child_process');
const chokidar = require('chokidar');
const path = require('path');

let childProcess;

function startServer() {
    childProcess = spawn('node', [path.join(__dirname, 'server.js')], {
        detached: true,
        stdio: 'inherit'
    });

    childProcess.on('close', (code) => {
        console.log(`Child process exited with code ${code}`);
        startServer(); // 重启服务器
    });
}

// 启动服务器
startServer();

// 使用 chokidar 监控文件变化
const watcher = chokidar.watch('.', {
    ignored: /(^|[\/\\])\../, // 忽略隐藏文件
    persistent: true
});

watcher.on('change', (filePath) => {
    console.log(`File ${filePath} has been changed. Restarting server...`);
    
    if (childProcess) {
        childProcess.kill('SIGINT'); // 发送 SIGINT 信号
        childProcess.unref();
    }
});

解释

  1. 启动服务器:在 restart.js 中,我们使用 spawn 方法启动 server.jsdetached: true 使得子进程与父进程分离。

  2. 监听退出事件:子进程的 close 事件用于捕获进程退出,然后重新启动服务器。

  3. 监控文件变化:使用 chokidar 监听文件变化。当检测到文件变化时,发送 SIGINT 信号给子进程,尝试终止它。

  4. 重启服务器:当子进程被终止后,重新启动服务器。

通过这种方式,你可以在 Windows 环境下有效地管理和重启子进程。


找到办法了,必须调用taskkill命令 https://github.com/remy/nodemon/blob/master/nodemon.js

嗯,taskkill +1

在Windows环境下,由于信号处理机制与Unix系统不同,process.killchild_process.kill 方法可能无法按预期工作。你可以使用 Process Explorertaskkill 命令来手动或编程方式终止子进程。

下面提供一种使用 taskkill 终止子进程的方法:

示例代码

const { spawn } = require('child_process');
const { exec } = require('child_process');

// 启动子进程
const child = spawn('node', ['server.js'], {
    stdio: 'inherit'
});

// 监听退出事件
child.on('exit', (code) => {
    console.log(`子进程退出,退出码: ${code}`);
});

// 当文件发生变化时,执行终止子进程的命令
function restartServer() {
    // 使用 taskkill 杀死子进程
    exec('taskkill /F /PID ' + child.pid, (error, stdout, stderr) => {
        if (error) {
            console.error(`执行出错: ${error}`);
            return;
        }
        console.log(`stdout: ${stdout}`);
        console.log(`stderr: ${stderr}`);

        // 重新启动子进程
        child.kill();
        child = spawn('node', ['server.js'], {
            stdio: 'inherit'
        });
    });
}

// 模拟文件变化事件
setTimeout(restartServer, 5000); // 5秒后重启

解释

  1. 启动子进程

    • 使用 spawn 方法启动子进程。
  2. 监听退出事件

    • 通过监听 exit 事件,可以得知子进程何时退出。
  3. 重启子进程

    • 定义一个函数 restartServer,该函数使用 exec 方法执行 taskkill 命令来杀死子进程。
    • taskkill /F /PID <pid>/F 参数表示强制结束进程,/PID 参数指定要终止的进程ID。
    • taskkill 命令执行后,重新启动子进程。
  4. 模拟文件变化事件

    • 使用 setTimeout 模拟文件变化事件,实际应用中可以通过监控文件系统的变化来触发重启逻辑。

通过这种方式,你可以在Windows环境中有效地管理和重启子进程。

回到顶部