nodejs使用child_process模块启动(exec和spawn)子线程任务,子进程实例的kill()方法无效的问题

以下内容在win10环境下的执行分析(这里就不对进程和线程做区分了):

  1. child_process.execchild_process.spawn启动进程的区别。
shell <string> Shell to execute the command with. See Shell requirements and Default Windows shell. Default: '/bin/sh' on Unix, process.env.ComSpec on Windows.
> shell <string> 使用shell执行命令。请参阅外壳要求和默认Windows外壳。默认值:Unix上的“/bin/sh”,process.env。Windows上的ComSpec。
shell <boolean> | <string> If true, runs command inside of a shell. Uses '/bin/sh' on Unix, and process.env.ComSpec on Windows. A different shell can be specified as a string. See Shell requirements and Default Windows shell. Default: false (no shell).
> shell <boolean> | <string> 如果为true,则在shell内运行命令。在Unix上使用'/bin/sh'和process.env。Windows上的ComSpec。可以将其他shell指定为字符串。请参阅shell要求和默认Windows shell。默认值:false(无shell)。

child_process.exec启动的进程是先启动cmd命令,在把你通过exec传入的command字符串放到cmd中执行,
这样就会导致有2个进程,1个是进程是cmd命令所启动的,另一个进程是你传入的command命令所启动的。
这就会导致你通过exec获取到的进程实例其实是cmd进程的PID,而cmd进程所启动的命令的进程你是获取不到的,
自然就无法通过kill停止了,因为你停止的只是cmd进程,而不是你传入执行的command字符串命令所在的进程。

正是因此,所以exec适合短时间运行的命令任务,例如dir,tasklist等这种会自己结束的命令。


child_process.spawn命令默认是不在shell中执行,因为shell的默认值是false吗!这里我们举一个spawn命令的例子来说明怎么使用。

const ls = spawn('C:\\Windows\\System32\\PING.EXE', ['-n 600 127.0.0.1'], {
    shell: false,
    windowsVerbatimArguments : true,
});

ls.stdout.on('data', (data) => {
    debugger
    console.log(`stdout: ${iconv.decode(data, 'gbk')}`);
});

ls.stderr.on('data', (data) => {
    console.error(`stderr: ${data}`);
});

ls.on('close', (code) => {
    console.log(`child process close exited with code ${code}`);
});

ls.on('exit', (code) => {
    console.log(`child process exited with code ${code}`);
});

// 2分钟后停止子进程。
setTimeout(()=>{
    let kill = ls.kill();
    console.log("模仿主进程停止,停止子进程成功?" + kill);
}, 1000 * 60 * 2)

spawn命令的参数我这里简单说明下,详细的看Nodejs官方文档
spawn命令的第一个参数是要执行的命令的完整路径(不要携带参数,否则会执行报错,提示找不到命令),

spawn('C:/a/b/c.exe -n 100')这种使用就是错误的,正确的使用方式是spawn('C:/a/b/c.exe')这种方式。
而第二个参数是要提供一个String[]字符串数组,但是这个数组有2种传值的方式。
第一种方式是['-n 100'],如果你传入这个参数,当前spawn执行的命令进程会执行后就会瞬间退出,因为命令对这个参数无法解析,这主要是nodejs对命令的参数解析后,
在实际执行的时候参数就不认识了,但是当你配置上windowsVerbatimArguments参数为true值,就可以解决这个解析参数的问题。

windowsVerbatimArguments 在Windows上不进行参数的引用或转义。在 Unix 上被忽略。当指定 shell 且为 CMD 时,此值自动设置为 true。默认值:false。

完整的例子:

spawn('C:/a/b/c.exe', ['-n 100'], {
windowsVerbatimArguments: true
})

spawn('C:/a/b/c.exe', ['-n 100', '-t'])

其他问题

spawn的stdout输出的字符串乱码(���� Ping 127.0.0.1 ���� 32 �ֽڵ�����:)怎么解决?

https://www.npmjs.com/package/iconv-lite ,安装这个库,将其转为GBK编码进行输出即可。

ls.stdout.on('data', (data) => {
    console.log(`stdout: ${iconv.decode(data, 'gbk')}`);
});

如果你想说为什么不使用Buffer.toString进行转换编码呢?那是因为Buffer支持的字符编码有限,不支持GBK字符串编码的转换。
https://nodejs.org/dist/v18.20.4/docs/api/buffer.html

win10上查找可执行文件所属路径

where ping

在Linux上查找可执行文件所属路径

which ping
posted @   星小梦  阅读(298)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
历史上的今天:
2022-08-03 docker 07 多容器应用程序
2022-08-03 Docker 06 持久化到主机本地系统。也就是常说的挂载
2022-08-03 Docker 05 构建镜像发送到中央仓库
2022-08-03 Docker 04 构建并运行基础镜像
点击右上角即可分享
微信分享提示