Appearance
介绍
nodejs 提供创建操作子进程的能力,通过spawn exec fork execFile四个api。后面三个均是spawn的衍生。
shell
shell是一个快捷启动进程的壳子,当我们在shell中敲命令(外部命令)时,实际是通过shell作为父进程创建了一个子进程比如 node xxx.js。所以当我们关闭shell窗口时,对应的命令也会kill。没登录一次shell窗口就会产生一个shell进程。具体是哪个shell使用用户自行配置的。
有时候我们写shell脚本会指定该脚本由哪个shell执行,流程是先打开对应的进程,对应的进程对脚本内容进行处理。
child_process
nodejs本身在执行时也是一个进程,如果是被shell直接调用,则是shell的衍生进程。当nodejs通过child_process 创建子进程时,如果有些子进程还需要通过shell来启动,所以还能指定是否启动shell。 主进程关闭后子进程也会关闭。进程需要关注的是以下几个点
- stdout,stdin,stderr 表示进程输入,输出和错误。由于当前的默认情况子进程的stdout,stdin,stderr是pipe,意思是通过管道向外发射。也可以设置为和父进程共享,借助父进程来输入输出
- 还有一种IPC子进程,父子进程通过IPC通信,nodejs中是on('message')和send。通过fork创建或者执行std是IPC。 IPC只能用都是node进程的情况下
js
import child_process from 'child_process'
export const shelljs = () => {
const child = child_process.spawn('ls', {
shell: true
}, (err, stdin, stdout) => {
})
}进程追加
很多情况子进程都是启动后执行完毕就会自动关闭,每次执行上下文不共享。但是也可以启动一个常驻的进程,比如直接启动一个shell。
js
import { spawn, spawnSync } from "child_process";
const mergeShellOptions = (...options) => {
return Object.assign({}, ...options);
};
const getGlobalShell = ((shell) => (option, config) => {
shell = shell || Shell.createShell(option, config);
return shell;
})();
const getDefaultOption = () => ({
shell: true,
stdio: ["pipe", "inherit", "inherit"],
timeout: 1000 * 60 * 5,
});
const getBash = () => {
if (process.platform === "win32") {
return { cmd: "cmd", arg: "/C" };
} else {
return { cmd: "sh", arg: "-c" };
}
};
class Shell {
static defaultOption = getDefaultOption();
static createShell(option, config) {
return new Shell(option, config);
}
static exec(cwd, option, config) {
const shell = getGlobalShell(option, config);
shell.exec(cwd);
}
/**
* shell示例的选项
*/
shellOption;
shell;
constructor(option, config) {
this.shellOption = mergeShellOptions(Shell.defaultOption, option);
this.shell = spawn(getBash().cmd, this.shellOption);
}
exec(cwd) {
console.log(cwd);
this.shell.stdin.write(cwd + "\n");
}
close() {
this.shell.kill();
}
}
export default Shell;