昨天在跟同事讨论 node 中执行 shell 命令,或者 node 命令时,控制台没有输出想要的信息,所以研究下为什么。
前提
Node 是单进程单线程。
ChildProcess 类
child_process.spawn(command[, args][, options]])
会衍生出一个子进程,这个子进程实际上就是 ChildProcess
的实例。对,不是 new
出来的,而是使用 child_process.spawn()
、child_process.exec()
、child_process.execFile()
或 child_process.fork()
方法来创建 ChildProcess
的实例。 这个实例提供有关当前子进程的信息并对其进行控制。
const { spawn } = require('child_process');
const subprocess = spawn('some_command');
ChildProcess
的实例上具体有什么属性和方法,这里不做详细的描述,具体可以参考文档。
通信
父 Node.js 进程和衍生的子进程之间会建立管道。
默认情况下,子进程的标准输入、标准输出和标准错误被重定向到 ChildProcess
对象上相应的 subprocess.stdin
、subprocess.stdout
和 subprocess.stderr
流。 这相当于将 options.stdio
设置为等于 ['pipe', 'pipe', 'pipe']
。
这样父 Node.js 进程会通过以下方式获取子进程的消息,并在控制台 console.log
内容。
const child_process = require("child_process");
const subprocess = child_process.spawn("ls", ["-a"], {
stdio: "pipe",
});
subprocess.stdout.on("data", (data) => {
console.log(data.toString());
});
但是,当 options.stdio
设置为 'ignore'
,表示Node.js 忽略子进程中的文件。subprocess.stdout
就会是 null 。
当 options.stdio
设置为'inherit'
,subprocess.stdout
也会是 null 。
stdio 选项
从上面可以看到,这个选项是用于配制在父进程和子进程之间建立的管道。也就是说可以影响到 shell 命令,或者 node 命令 在控制台上的输出。
当类型为字符串时:
options.stdio |
含义 |
---|---|
'pipe' |
在子进程和父进程之间创建管道。 管道的父端作为 subprocess.stdio[fd\] 的 child_process 对象的属性暴露给父进程。也可以在父进程中通过subprocess.stdout.on("data", () => {})获取。 |
'overlapped' |
与 'pipe' 相同。 |
'ignore' |
父进程通过管道得到的是 null 。 |
'inherit' |
子进程将使用父进程的标准输入输出。 |
结论
以上我们清楚的了解到,当使用 child_process.spawn(command[, args][, options]])
执行命令时,一般将 options.stdio
设置为 'inherit'
,这样才能在控制台中正确显示信息。