child_process spawn 模块详解
child_process.spawn()方法使用给定的 command 衍生新的进程,并传入 args 中的命令行参数。
函数签名
interface SpawnOptions {
cwd: string
env: Object
argv0: string[]
stdio: string[] | string
detached: boolean
uid: number
gid: number
serialization: string
shell: boolean
windowsVerbatimArguments: boolean
windowsHide: boolean
}
function spawn(command: string, options: SpawnOptions): ChildProcess
function spawn(
command: string,
args: ReadonlyArray<string>,
options: SpawnOptions
): ChildProcess参数详解
Command
spawn 模块会创建一个子进程,并在这个进程中调用传入的系统命令。
这里的系统命令 command 就是指你可以在终端中输入的命令,比如 npm、node、bash、ls、pwd、mongod 等等等等,你可以在终端中输入,就可以在这里传入
比如我们可以这样调用 ls 命令
const { spawn } = require("child_process")
spawn("ls")Args
如果需要给命令传递参数,可以传入 args 属性,此属性默认为空数组
spawn("ls", ["-a"])Options
常用这两个:shell stdio
-
shell: boolean | string = false
- 如果为 true,则在 shell 中运行 command。
- 在 Unix 上使用 '/bin/sh',在 Windows 上使用 process.env.ComSpec。
- 可以将不同的 shell 指定为字符串。参见 shell 的要求和默认的 Windows shell
-
stdio: string[] | string = 'pipe'
-
默认情况下,子进程的输入输出流都会在子进程中处理,我们可以将其设置为
inherit,来把子进程的输入输出放到副进程中处理。详见 options_stdio -
举个例子
// index.js 文件 require('child_process').spawn('ls') node index.js // 如果我们直接这样执行代码,那么在终端中我们是看不到任何输出的 // 这是因为输出信息都传递给了子进程,而子进程并没有打印处理 // 我们加上下面的代码进行打印 require('child_process').spawn('ls').stdout.on('data', console.log) // 此时再执行就可以在终端中看到输出的信息了 // 而如果我们将 stdio 设置为 inherit,则会将输入输出交由父进程处理,子进程不需要监听事件也可以在终端中看到输出的信息了
-
-
cwd: string
- 设置子进程的工作目录,默认值:当前目录
-
env: object
- 环境变量的键值对。默认值: process.env
-
argv0: string
- 可以通过设置这个参数重写
command参数的值,如果没有传入,则会被设置为传入的command值
- 可以通过设置这个参数重写
-
detached: boolean
- 使子进程独立于其父进程运行, 具体行为取决于平台。详见 options_detached
= uid: number - 设置进程的用户标识
= gid: number - 设置进程的群组标识
- 使子进程独立于其父进程运行, 具体行为取决于平台。详见 options_detached
-
serialization: string = json
- 指定用于在进程之间发送消息的序列化类型。可能的值为 'json' 和 'advanced'。
-
windowsVerbatimArguments: boolean
- 在 Windows 上不为参数加上引号或转义。
- 在 Unix 上会被忽略。
- 如果指定了 shell 并且是 CMD,则自动设为 true。默认值: false。
-
windowsHide: boolean
- 隐藏子进程的控制台窗口(在 Windows 系统上通常会创建)。默认值: false。
跨平台
在 unix 系统中,我们可以这样使用 spawn('npm'),这场可以正常运行的。但在 windows 系统中则会报错,这是因为在 windows 中我们实际执行的是 npm.cmd 批处理,而在 windows 上,.cmd .bat 批处理需要使用 cmd.exe 来运行。
所以我们需要显示的调用 cmd:spawn('cmd', ['/c', 'npm']),或者我们可以设置 shell 参数来隐式调用 cmd spawn('npm', {shell: true})
虽然在 unix 中,我们设置 shell 为 true 也不妨碍命令的执行,但是这样就会额外产生一个不必要的 shell 进程。
所以我们可以这么来写,如果系统是 windows 则打开 shell
spawn("npm", {
shell: process.platform === "win32",
})执行 Shell 命令
从上面的文章我们可以了解到, 默认情况下,spawn 并不会创建一个 shell 来执行我们传入的命令。
这个行为使得它比 exec 函数效率更高,但是有时我们又确实需要执行 shell 命令,那这个时候我们怎么使用 spawn 来执行呢?要知道 exec 函数会缓存输出结果一次性返回给我们,而 spawn 则是使用流的形式。如果我们的命令数据数据规模较小,那使用 exec 的确是个不错的选择,但在大多数情况下,使用 spawn 将会是更合理、更安全的方式
那么如果使用 spawn 来执行 shell 命令呢?
- 最简单的,就是设置 shell 参数
// 设置为true
spawn("npm run dev", { shell: true })
// 指定终端
spawn("npm run dev", { shell: "bash" })- 也可以运行指定终端来执行命令
// 直接传入shell命令
spawn("bash", ["npm", "run", "dev"])
// 通过stdin.write写入命令
const bash = spawn("bash")
bash.stdin.write("npm run dev")
bash.stdin.end()