nodejs中spawn和exec开启子进程的区别以及正常启动exe二进制文件不起作用的原因

533 阅读2分钟

文章分为两部分,第一部分为nodejs中child_process中spawn和exec子进程的区别以及联系第二部分为启动exe文件可能出现的问题以及解决方案

spawn 和 exec的区别

spawn的使用和说明

先在nodejs导入spawn和exec

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

启动spawn在node18版本中明确表示了spawn的启动需要三个参数:command,arg,option例如:

const childProcess = spawn('开启子进程的路径', [], {cwd: '子进程工作目录'});

child_procees中有6个事件通过on触发:close、disconnect、error、exit、message、spawn 比较基础的close error exit 在以下进行说明

1.errors事件 说明:在子进程本身这个进程启动不起来所报的错误

childProcess.on('error',err=>{
      console.log(err.message)
})

2.close事件:子进程关闭事件

childProcess.on('close', (code,signal) => {
    console.log(`子进程关闭,退出码 ${code},信号为:${signal}`);
    }

3.exit事件:子进程退出事件

childProcess.on('close', (code) => {
    console.log(`子进程退出,退出码 ${code}`);
    }

close和exit的区别: 'close' 事件在进程结束并且子进程的 stdio 流关闭后触发。 这与 ['exit'] 事件不同,因为多个进程可能共享相同的 stdio 流。 'close' 事件将始终在 ['exit'] 已经触发后触发,或者如果子项未能生成则为 ['error']

总结一点:当进程很多的时候,S进程退出了A进程的事情['exit'] ,但是S进程还可以参与B进程所做的事情,此时 S可以退出,但没必要关闭,所以['exit']比['close']先执行

child_process常用的方法: stdoutstderr

stdout

childprocess.stdout.on('data', (buffer) => {
      const data =buffer.tostring()
      console.log(`数据:${data}`)
}); 

stderr

childprocess.stderr.on('data', (data) => {
      console.log(`输出错误:${data}`)
}); 

exec使用和说明

说明:exec的使用只需要三个参数:command、option、callback

const {exec} = require('child_process');
exec(`where nodejs`,[],(error, stdout, stderr)=>{
  if (error) {
    console.error(`exec error: ${error}`);
    return;
  }
  console.log(`stdout: ${stdout}`);
  console.error(`stderr: ${stderr}`);
})

同时exec的方法和事件和spwan相同,因此不再赘述

exec 和spawn区别

exec和spawn最大的区别在于输出流的捕获:exec虽然用起来比spawn方便,但是在官方文档中规定了exec在捕获输出流规定了默认的最大buffer是1MB,而spawn没有规定,因此在捕获输出流时spawn更好。其次作者再看其他文章时都说是200KB,作者也不太明白,希望各位读者留言指正。

spawn和exec启动二进制文件启动不起来可能的原因

1.有的exe文件需要在指定的工作目录下才能启动,因此需要在childprocess中option将cwd设置子进程所需要的工作目录

const {exec} = require('child_process');
exec(`where nodejs`,[cwd:"子进程工作目录"],(error, stdout, stderr)=>{
  if (error) {
    console.error(`exec error: ${error}`);
    return;
  }
  console.log(`stdout: ${stdout}`);
  console.error(`stderr: ${stderr}`);
})
const childProcess = spawn('开启子进程的路径', [cwd:"子进程工作目录"], {cwd: '子进程工作目录'});

2.有的exe文件自己可以在控制台打开,或者双击可以打开,但是子进程打不开,可能是idea没有管理员权限,关闭idea重新用管理员权限打开即可。

3.打包之后子进程依旧启动不起来 只需要在打包的时候,在package.json的build中设置权限为系统管理员即可:

"requestedExecutionLevel": "requireAdministrator",