Skip to content

介绍

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。 主进程关闭后子进程也会关闭。进程需要关注的是以下几个点

  1. stdout,stdin,stderr 表示进程输入,输出和错误。由于当前的默认情况子进程的stdout,stdin,stderr是pipe,意思是通过管道向外发射。也可以设置为和父进程共享,借助父进程来输入输出
  2. 还有一种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;