Node.js 编写跨平台 spawn 语句

2019-01-29 14:50:51

前言

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 ENOENTat 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 时,才使用 shellshell: 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'});

参考文档

  • 2020-02-16 16:17:15

    CocoaPods安装和使用教程

    当你开发iOS应用时,会经常使用到很多第三方开源类库,比如JSONKit,AFNetWorking等等。可能某个类库又用到其他类库,所以要使用它,必须得另外下载其他类库,而其他类库又用到其他类库,“子子孙孙无穷尽也”,这也许是比较特殊的情况。总之小编的意思就是,手动一个个去下载所需类库十分麻烦。另外一种常见情况是,你项目中用到的类库有更新,你必须得重新下载新版本,重新加入到项目中,十分麻烦。如果能有什么工具能解决这些恼人的问题,那将“善莫大焉”。所以,你需要 CocoaPods。

  • 2020-02-16 17:13:34

    iOS优秀Objective-C开源库集锦

    自己从事iOS开发工作接近两年左右的时间了,在自己工作之余,收集整理了一些优秀的三方开源框架,自己整理的这些三方开源库涵盖了iOS开发面很多方面的知识。非常感谢这些开源库的作者们,正是因为这些库,提高了我们的开发效率,同样也是我们学习进步的源泉。现将这个整理工程文件分享出来,希望能给需要的朋友一些帮助,同时也自己也做下收集记录。

  • 2020-02-19 23:04:52

    理解Laravel中的pipeline

    pipeline在laravel的启动过程中出现次数很多,要了解laravel的启动过程和生命周期,理解pipeline就是其中的一个关键点。网上对pipeline的讲解很少,所以我自己写一写吧。

  • 2020-02-19 23:08:56

    Laravel 用户认证 Auth(精华)

    很多应用是需要登陆后才能操作,Laravel 提供了一个 auth 工具来实现用户的认证功能。并且有一个 config/auth.php 来配置 auth 工具。大概看一下 auth 工具的常用方法