Nodejs 命令行调用 exec 与 spawn 差异

比如在前端工程项目中 Nodejs 要调用命令行命令如:

yarn electron:build

exec 调用 yarn 命令,为了能使命令行能实时打印输出正在编译的命令

以异步形式调用 exec 使用 stdout.on 方式监听标准输出,并打印

 // 打包 electron
const buildElectron = () => {
return new Promise((resolve, reject)=> {
console.log(`yarn electron:build`)
const buildExec = exec(`yarn electron:build`, (error, stdout, stderr) => {
if (error) {
console.error(`exec error: ${error}`);
reject()
return;
}
resolve()
}); buildExec.stdout.on('data', function(data) {
// 此处会实时打印输出
console.log(data.toString())
});
})
}
// 启动调用
buildElectron();

对于普通的命令行来说这足够了,但当你的命令行输出内容较大时,exec 命令就不行了

此时需要更换 spawn 命令

const command = spawn('yarn', ['command']);

spawn 使用 child_process 模块的方法,但与 exec 不同的是,命令行的参数需要以数组的形式传递进去:

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

const command = spawn('yarn', ['command']);

command.stdout.on('data', (data) => {
console.log(`stdout: ${data}`);
}); command.stderr.on('data', (data) => {
console.error(`stderr: ${data}`);
}); command.on('close', (code) => {
console.log(`child process exited with code ${code}`);
});

然后就在我的 PC 电脑上报错了

spawn yarn enoent

问一下 chatgpt 这是啥错误:

大至意思是 spawn 命令在执行时找不到 yarn 命令, 执行命令时需要带上具体路径

spawn('C:\Program Files\nodejs\yarn', ['command']);

按以上提示后运行以命令

还是报错

继续问 chatgpt

然后答案是,需要用 yarn.cmd 如下:

const { spawn } = require('child_process');
const command = spawn('C:\\Program Files\\nodejs\\yarn.cmd', ['command']);

写死路径,太不科学了,如果其它前端小伙伴接取代码行动的话说不定会报错。。。

最后发现直接用 yarm.cmd 即可,不用完整路径

const { spawn } = require('child_process');
const command = spawn('yarn.cmd', ['command']);

问题又解决了

还有如果你用的是 pnpm , 解决 spawn pnpm ENOENT error 也是一样的处理方法

const { spawn } = require('child_process');
const command = spawn('pnpm.cmd', ['command']);

两者不同

  1. 输入输出处理:

    • spawn: 提供了输入输出的流式接口。它返回了一个 ChildProcess 对象允许你流式读写

    • exec: 整个输出都存到了 buffers 缓冲区,然后传递给回调。它使用起来虽然比较简单,但当命令输出的结果太大时就可能出错。

  2. 指令执行

    • spawn: 使用新的进程启动命令行,允许独立运行。它允许长时间运行或可执行继续交互命令

    • exec: 命令在 shell 中执行,输出结果在缓存区。它使用方便,但输出复杂结果是会有问题或无法在未中断命令的情况下继续进行交互命令

  3. Shell 使用:

    • spawn: 默认不使用 Shell. 参数需要数组方式传递.

    • exec: 使用 Shell. 允许你使用 Shell 的一些特征 pipes, input/output 重定向, 和命令的置换.

  4. 错误处理:

    • spawn: 在 ChildProcess 对象上发送错误事件。可以监听并处理它

    • exec: 错误通过回调内第一个参数传递。可以据此处理


博客园: http://cnblogs.com/willian/

github: https://github.com/willian12345/

Nodejs 命令行调用 exec 与 spawn 差异--- 解决 spawn yarn ENOENT error的更多相关文章

  1. nodejs命令行执行时带参数

    nodejs命令行执行时带参数 转 https://www.jianshu.com/p/474e6d76f867   今天项目里突然想在初始化时跑一些数据,于是想起以前在python时可以在命令行里带 ...

  2. Symfony2 通过命令行调用控制器

    由于系统需求,需要写一个无限循环的控制器,那么既然有一个无限循环的控制器,那么就需要有一个开关,不可能直接通过route来开启吧.当然要使用高级一点的方法啊. 那就是使用控制台通过命令行(comman ...

  3. Maven-11: 从命令行调用插件

    mvn -h显示mvn命令帮助: usage: mvn [options] [<goal(s)>] [<phase(s)>] Options: -am,--also-make ...

  4. 命令行调用dubbo远程服务

    命令行调用dubbo远程服务 telnet远程连接到dubbo telnet 127.0.0.1 20880 查看提供服务的接口 dubbo>ls com.test.service.TestIn ...

  5. Java项目导出为jar包+导出第三方jar包+使用命令行调用+传参

    Java项目导出为jar包+导出第三方jar包+使用命令行调用+传参 一.打包 情况1:不需要向程序传参数,并且程序没有使用第三方jar包 Eclipse上导出jar: 然后选择一个java文件作为入 ...

  6. VB6 实现命令行调用时附着到原控制台

    Public Declare Function AttachConsole Lib "kernel32.dll" (ByVal ProcessID As Integer) As B ...

  7. blockdev - 从命令行调用区块设备控制程序

    总览(SYNOPSIS) blockdev [options] commands devices 描述(DESCRIPTION) blockdev 工具允许从命令行调用区块设备控制程序. 选项(OPT ...

  8. Shodan搜索引擎详解及Python命令行调用

    shodan常用信息搜索命令 shodan配置命令 shodan init T1N3uP0Lyeq5w0wxxxxxxxxxxxxxxx //API设置 shodan信息收集 shodan myip ...

  9. 关于windows环境下cordova命令行无法启动adb.exe的解决办法

    使用phonegap开发手机APP,常常需要更改代码之后进行调试,使用安卓模拟器每次启动非常缓慢,而且不能保证最终在真机上的效果.所以一般都采用真机进行调试. 搭建真机的调试环境这里就不再赘述了,网上 ...

  10. WebService远程调用(命令行调用)

    远程调用webservice 方法, 通过wsdl命令,生成webservice 对应asmx 文件的对应类(cs文件),然后将此cs文件引用到当前项目中,项目其他地方需要调用webservice方法 ...

随机推荐

  1. VB6的WindowsXP控件引擎 - 开源研究系列文章

    这几天翻了一下原来VB6的代码,将一些有用的代码进行了整理,然后将这些代码记录下来,开源出来,让需要的朋友能够进行代码复用. 这次介绍的是一个VB6的WindowXP的控件引擎代码,主要是在程序启动的 ...

  2. DDR5能给PC带来怎样提升?我们用12款软件进行了对比测试

    结论前置:我们使用了12款专业测试软件,分别对DDR5与DDR4内存,在相同平台下进行了测试体验:酷睿i9-12900K搭配DDR4与DDR5,总体差距并不是很大:在y-cruncher测试中,DDR ...

  3. 每日一道Java面试题:说一说Java中的泛型?

    写在开头 今天的每日一道Java面试题聊的是Java中的泛型,泛型在面试的时候偶尔会被提及,频率不是特别高,但在日后的开发工作中,却是是个高频词汇,因此,我们有必要去认真的学习它. 泛型的定义 什么是 ...

  4. Leetcode刷题第二天-贪心

    655:非递减数列 链接:665. 非递减数列 - 力扣(LeetCode) 直接找最大最小值进行替换不行,[1,5,4,6,7,8,9]最大最小值所处位置可能是非递减数列 如果nums[i]> ...

  5. navicat破解(15以前的版本)

    navicat破解各种不成功,很耽误事.所以,再次整理一个相对省事有效的办法.内容如下: 一:下载此激活工具 二:按下图生成激活码 1. 2. 点击手动激活 3. 将请求码按图粘贴,按图点击操作便可激 ...

  6. MySQL-CDC原理与实践

    MySQL CDC (Change Data Capture),中文名为MySQL变化数据捕获,是一种截取MySQL主从复制流中binlog的技术,从而实时捕获数据库中的增.删.改操作.在大数据.实时 ...

  7. 【Unity3D】场景切换、全屏_恢复切换、退出游戏、截屏

    1 前言 ​ 1)场景切换 ​ 场景切换可以使用 SceneManager 的 LoadScene 和 LoadSceneAsync 方法,如下: public static void LoadSce ...

  8. Java并发编程实例--2.获取和设置线程信息

    常用线程属性 ID: 每个线程的唯一标识: Name: 线程名称: Priority: 线程优先级,从1-10,数字越大优先级越高:不推荐改变线程优先级: Status: 线程状态,包含6种状态:ne ...

  9. Android使用SurfaceView实现签名板

    SurfaceView使用 首先创建一个SurfaceViewSign类,继承SurfaceView类,继承 SurfaceHolder.Callback和Runnable接口,代码如下: impor ...

  10. RunnerGo低代码测试体验

    RunnerGo是基于go语言自研的一款企业级全栈式测试平台,采用Apache-2.0 license开源协议,涵盖接口测试.性能测试.UI测试和项目管理等功能,并独创"拖拉拽"的 ...