专栏首页YuanXinNodeJS模块研究 - child_process

NodeJS模块研究 - child_process

掌握 nodejs 的 child_process 模块能够极大提高 nodejs 的开发能力,例如主从进程来优化 CPU 计算的问题,多进程开发等等。本文从以下几个方面介绍 child_process 模块的使用:

  • 创建子进程
  • 父子进程通信
  • 独立子进程
  • 进程管道

创建子进程

nodejs 的 child_process 模块创建子进程的方法:spawn, fork, exec, execFile。它们的关系如下:

  • fork, exec, execFile 都是通过 spawn 来实现的。
  • exec 默认会创建 shell。execFile 默认不会创建 shell,意味着不能使用 I/O 重定向、file glob,但效率更高。
  • spawn、exec、execFile 都有同步版本,可能会造成进程阻塞。

child_process.spawn()的使用:

const { spawn } = require("child_process");
// 返回ChildProcess对象,默认情况下其上的stdio不为null
const ls = spawn("ls", ["-lh"]);

ls.stdout.on("data", data => {
    console.log(`stdout: ${data}`);
});

ls.stderr.on("data", data => {
    console.error(`stderr: ${data}`);
});

ls.on("close", code => {
    console.log(`子进程退出,退出码 ${code}`);
});

child_process.exec()的使用:

const { exec } = require("child_process");
// 通过回调函数来操作stdio
exec("ls -lh", (err, stdout, stderr) => {
    if (err) {
        console.error(`执行的错误: ${err}`);
        return;
    }
    console.log(`stdout: ${stdout}`);
    console.error(`stderr: ${stderr}`);
});

父子进程通信

fork()返回的 ChildProcess 对象,监听其上的 message 事件,来接受子进程消息;调用 send 方法,来实现 IPC。

parent.js 代码如下:

const { fork } = require("child_process");
const cp = fork("./sub.js");
cp.on("message", msg => {
    console.log("父进程收到消息:", msg);
});
cp.send("我是父进程");

sub.js 代码如下:

process.on("message", m => {
    console.log("子进程收到消息:", m);
});

process.send("我是子进程");

运行后结果:

父进程收到消息: 我是子进程
子进程收到消息: 我是父进程

独立子进程

在正常情况下,父进程一定会等待子进程退出后,才退出。如果想让父进程先退出,不受到子进程的影响,那么应该:

  • 调用 ChildProcess 对象上的unref()
  • options.detached 设置为 true
  • 子进程的 stdio 不能是连接到父进程

main.js 代码如下:

const { spawn } = require("child_process");
const subprocess = spawn(process.argv0, ["sub.js"], {
    detached: true,
    stdio: "ignore"
});

subprocess.unref();

sub.js 代码如下:

setInterval(() => {}, 1000);

进程管道

options.stdio 选项用于配置在父进程和子进程之间建立的管道。 默认情况下,子进程的 stdin、 stdout 和 stderr 会被重定向到 ChildProcess 对象上相应的 subprocess.stdin、subprocess.stdout 和 subprocess.stderr 流。 这意味着可以通过监听其上的 data事件,在父进程中获取子进程的 I/O 。

可以用来实现“重定向”:

const fs = require("fs");
const child_process = require("child_process");

const subprocess = child_process.spawn("ls", {
    stdio: [
        0, // 使用父进程的 stdin 用于子进程。
        "pipe", // 把子进程的 stdout 通过管道传到父进程 。
        fs.openSync("err.out", "w") // 把子进程的 stderr 定向到一个文件。
    ]
});

也可以用来实现”管道运算符”:

const { spawn } = require("child_process");

const ps = spawn("ps", ["ax"]);
const grep = spawn("grep", ["ssh"]);

ps.stdout.on("data", data => {
    grep.stdin.write(data);
});

ps.stderr.on("data", err => {
    console.error(`ps stderr: ${err}`);
});

ps.on("close", code => {
    if (code !== 0) {
        console.log(`ps 进程退出,退出码 ${code}`);
    }
    grep.stdin.end();
});

grep.stdout.on("data", data => {
    console.log(data.toString());
});

grep.stderr.on("data", data => {
    console.error(`grep stderr: ${data}`);
});

grep.on("close", code => {
    if (code !== 0) {
        console.log(`grep 进程退出,退出码 ${code}`);
    }
});

参考链接

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • ES6重难点整理

    ES6 新增了let和const,它们声明的变量,都处于“块级作用域”。并且不存在“变量提升”,不允许重复声明。

    心谭博客
  • NodeJS模块研究 - process

    process 模块是 nodejs 提供给开发者用来和当前进程交互的工具,它的提供了很多实用的 API。从文档出发,管中窥豹,进一步认识和学习 process...

    心谭博客
  • 设计模式 - 桥接模式 - JavaScript

    例如,对外提供暴露一个afterFinish函数, 如果用户有传入此函数, 那么就会在某一段代码逻辑中调用。

    心谭博客
  • Git的深入理解与GitHub托管服务的使用

    许多人习惯用复制整个项目目录的方式来保存不同的版本,或许还会改名加上备份时间进行区别。这么做的唯一好处就是简单,坏处也不少:有时候会混淆所在的工作目录,一旦弄错...

    大江小浪
  • ICLR2020首次虚拟会议圆满结束:全部内容免费开放,还有精美笔记送!

    ICLR 2020总主席、康奈尔大学技术学院的Alexander (Sasha) Rush透露,「今年没有最佳论文」。

    新智元
  • VP9到HEVC转码的帧间加速算法

    背景介绍 互联网多媒体技术的普及使数字视频得到了广泛的应用,更大分辨率、更高清晰度的视频逐渐进入人们的生活。传统视频编码标准如ITU(国际电信联盟)和ISO/I...

    用户1324186
  • 一个不错的 memcached web ui

    项目地址: https://github.com/youngsterxyf/memcached-ui

    二狗不要跑
  • Ubuntu14.04下使用fcitx安装搜狗及双拼输入法

    之前Ubuntu打不开了,重新装了一遍,顺便把一些东西直接记录下来,省得日后再四处爪哇。。。

    汐楓
  • Jenkins Pipeline script语法自动化测试模板及效果

    Jenkins 流水线 (或简单的带有大写"P"的"Pipeline") 是一套插件,它支持实现和集成 continuous delivery pipeline...

    苦叶子
  • 5.源码分析---SOFARPC调用服务

    我们这一次来接着上一篇文章《4. 源码分析---SOFARPC服务端暴露》讲一下服务暴露之后被客户端调用之后服务端是怎么返回数据的。

    luozhiyun

扫码关注云+社区

领取腾讯云代金券