利用Node.js编写跨平台的spawn语句详解


Posted in Javascript onFebruary 12, 2017

前言

Node.js 是跨平台的,也就是说它能运行在 Windows、OSX 和 Linux 平台上。很多 Node.js 开发者都是在 OSX 上做开发的,然后再将代码部署到 Linux 服务器上。由于 OSX 和 Linux 都是基于 Unix 的,因此两者共性很多。Windows 也是 Node.js 官方支持的平台,只要你通过正确的方式写代码,就能在各个平台上毫无压力的跑起来。

Node.js 的子进程 (child_process) 模块下有一 spawn 函数,可以用于调用系统上的命令,如在 Linux, macOS 等系统上,我们可以执行

const spawn = require('child_process').spawn;

spawn('npm', {
 stdio: 'inherit'
});

来调用 npm 命令。

然而,同样的语句在 Windows 上执行则会报错。

Error: spawn npm ENOENT
 at exports._errnoException (util.js:855:11)
 at Process.ChildProcess._handle.onexit (internal/child_process.js:178:32)
 at onErrorNT (internal/child_process.js:344:16)
 at nextTickCallbackWith2Args (node.js:455:9)
 at process._tickCallback (node.js:369:17)
 at Function.Module.runMain (module.js:432:11)
 at startup (node.js:141:18)
 at node.js:980:3

因为在 Windows 上,当我们执行 npm 时,我们实际执行的是 npm.cmd 批处理,而在 Windows 上, .cmd,  .bat 批处理是无法脱离 cmd.exe 这一解释器而单独运行的。

因此,我们需要显式地调用 cmd

spawn('cmd', ['/c', 'npm'], {
 stdio: 'inherit'
});

或者使用在调用 spawn 函数时,设置 shell 选项为 true 以隐式地调用 cmd (该选项添加自 Node.js v6 版本)

spawn('npm', {
 stdio: 'inherit',
 shell: true
});

另外,虽然在 Linux, macOS 等系统上不需要设置 shell 选项,命令也能够正常执行;设置 shell true 也不会妨碍命令的执行,只是会额外的产生一个本不必要的 shell 进程,影响性能。

因此,如果想要编写跨平台的 spawn 命令,而又不想增加额外的开销的话,可以这样写

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

spawn('npm', {
 stdio: 'inherit',
 // 仅在当前运行环境为 Windows 时,才使用 shell
 shell: process.platform === 'win32'
});

第三方模块 cross-spawn

关于 spawn 函数的跨平台写法,除了自己编写代码的时候做处理,也有第三方模块封装好了相关细节,如 cross-spawn。

使用该模块,可以在调用 spawn 函数时,自动根据当前的运行平台,来决定是否生成一个 shell 来执行所给的命令。

而且,还能够

  • 支持低于 v6 的 Node.js 版本 (使用 shell 选项需要至少 Node.js v6);
  • 跨平台地支持 shebang;
  • 对命令和参数中的字符进行转义更为方便。

安装

npm install cross-spawn

用法

const spawn = require('cross-spawn');

spawn('npm', {
 stdio: 'inherit'
});

参考文档

在 Windows 上衍生 .bat 和 .cmd 文件

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流。

Javascript 相关文章推荐
JSON 和 JavaScript eval使用说明
Jun 13 Javascript
JavaScript创建对象的写法
Aug 29 Javascript
Jquery弹出层插件ThickBox的使用方法
Dec 09 Javascript
JS实现的多张图片轮流播放幻灯片效果
Jul 22 Javascript
jQuery实现弹出带遮罩层的居中浮动窗口效果
Sep 12 Javascript
jQuery实现select模糊查询(反射机制)
Jan 14 Javascript
React快速入门教程
Jan 17 Javascript
bootstrap table 多选框分页保留示例代码
Mar 08 Javascript
详解如何构建一个Angular6的第三方npm包
Sep 07 Javascript
详解用js代码触发dom事件的实现方案
Jun 10 Javascript
解决Vue @submit 提交后不刷新页面问题
Jul 18 Javascript
JS中循环遍历数组的四种方式总结
Jan 23 Javascript
超全面的vue.js使用总结
Feb 12 #Javascript
Vue-Router实现页面正在加载特效方法示例
Feb 12 #Javascript
jquery使用EasyUI Tree异步加载JSON数据(生成树)
Feb 11 #Javascript
详解Jquery EasyUI tree 的异步加载(遍历指定文件夹,根据文件夹内的文件生成tree)
Feb 11 #Javascript
JavaScript实现瀑布流以及加载效果
Feb 11 #Javascript
JavaScript表单验证的两种实现方法
Feb 11 #Javascript
jQuery实现复制到粘贴板功能
Feb 11 #Javascript
You might like
xml在joomla表单中的应用详解分享
2012/07/19 PHP
IE中直接运行显示当前网页中的图片 推荐
2006/08/31 Javascript
JS+ACTIVEX实现网页选择本地目录路径对话框
2013/03/18 Javascript
Jquery AJAX POST与GET之间的区别
2013/11/14 Javascript
JS+JSP checkBox 全选具体实现
2014/01/02 Javascript
php is_numberic函数造成的SQL注入漏洞
2014/03/10 Javascript
纯JS代码实现一键分享功能
2016/04/20 Javascript
Augularjs-起步详解
2016/07/08 Javascript
Angular ng-class详解及实例代码
2016/09/19 Javascript
基于原生js淡入淡出函数封装(兼容IE)
2016/10/20 Javascript
vue实现简单实时汇率计算功能
2017/01/15 Javascript
js的三种继承方式详解
2017/01/21 Javascript
Angular数据绑定机制原理
2018/04/17 Javascript
详解如何解决Vue和vue-template-compiler版本之间的问题
2018/09/17 Javascript
vue-cli3.0 环境变量与模式配置方法
2018/11/08 Javascript
让IDE识别webpack的别名alias的实现方法
2020/05/06 Javascript
weui上传多图片,压缩,base64编码的示例代码
2020/06/22 Javascript
[01:35]2018年度CS GO最佳战队-完美盛典
2018/12/17 DOTA
Python中使用SAX解析xml实例
2014/11/21 Python
Django内容增加富文本功能的实例
2017/10/17 Python
Python搜索引擎实现原理和方法
2017/11/27 Python
matplotlib设置legend图例代码示例
2017/12/19 Python
对numpy 数组和矩阵的乘法的进一步理解
2018/04/04 Python
pandas 转换成行列表进行读取与Nan处理的方法
2018/10/30 Python
对python文件读写的缓冲行为详解
2019/02/13 Python
python如何实现视频转代码视频
2019/06/17 Python
使用PyTorch实现MNIST手写体识别代码
2020/01/18 Python
如何利用Python动态模拟太阳系运转
2020/09/04 Python
Python+Selenium随机生成手机验证码并检查页面上是否弹出重复手机号码提示框
2020/09/21 Python
化学教学随笔感言
2014/02/19 职场文书
空中乘务员岗位职责
2014/03/08 职场文书
歌唱比赛主持词
2014/03/18 职场文书
电钳工人个人求职信
2014/05/10 职场文书
小区环境卫生倡议书
2015/04/29 职场文书
军训结束新闻稿
2015/07/17 职场文书
SpringCloud的JPA连接PostgreSql的教程
2021/06/26 Java/Android