preface
Node.js is cross-platform, which means it runs on Windows, OSX, and Linux platforms. Many Node.js developers develop on OSX and then deploy their code to Linux servers. Because OSX and Linux are both based on Unix, they have a lot in common. Windows is also the official node.js platform, so as long as you code the right way, you can run on all platforms without any stress.
Node.js child_process module has a spawn function, which can be used to call system commands. On Linux, macOS, etc., we can execute the following code to call the common NPM command.
const spawn = require('child_process').spawn;
spawn('npm', {
stdio: 'inherit'
});
Copy the code
However, an error is reported when the same statement is executed on 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
Copy the code
Because on Windows, when we execute NPM, we actually execute the npm. CMD batch, whereas on Windows, the.cmd,.bat batch cannot be run without the cmd.exe interpreter.
Therefore, we need to explicitly call CMD
spawn('cmd'['/c'.'npm'] and {stdio: 'inherit'
});
Copy the code
Or implicitly call CMD by setting the shell option to true when calling the spawn function
spawn('npm', {
stdio: 'inherit'.shell: true
});
Copy the code
In addition, commands can be executed normally on Linux, macOS, and other systems without setting shell options. Setting the shell to true does not interfere with command execution, but creates an unnecessary extra shell process that affects performance.
So if you want to write a cross-platform spawn command without incurring extra overhead, you can do so
const process = require('process');
const { spawn } = require('child_process');
spawn('npm', {
stdio: 'inherit'.// Use shell only when the current operating environment is Windows
shell: process.platform === 'win32'
});
Copy the code
Cross-spawn third party module
Cross-platform writing of the spawn function is handled at the time of writing your own code, but there are also third-party modules that encapsulate the details, such as cross-spawn.
Using this module, you can automatically generate a shell to execute the given command based on the current running platform when calling the spawn function. It is easier to escape characters in commands and arguments.
#! /usr/bin/env node
const spawn = require('cross-spawn');
const { resolve } = require('path');
const { existsSync } = require('fs');
const version = process.env.CLI_BIN || '1.0.0';
const CLI_BIN = resolve(__dirname, process.platform, version, 'cli-bin');
if(! existsSync(CLI_BIN)) {console.log(`${version}Version does not exist);
process.exit(1);
}
spawn(CLI_BIN, process.argv.slice(2), { stdio: 'inherit' });
Copy the code