Gahing's blog Gahing's blog
首页
知识体系
  • 前端基础
  • 应用框架
  • 工程能力
  • 应用基础
  • 专业领域
  • 业务场景
  • 前端晋升 (opens new window)
  • Git
  • 网络基础
  • 算法
  • 数据结构
  • 编程范式
  • 编解码
  • Linux
  • AIGC
  • 其他领域

    • 客户端
    • 服务端
    • 产品设计
软素质
  • 面试经验
  • 人生总结
  • 个人简历
  • 知识卡片
  • 灵感记录
  • 实用技巧
  • 知识科普
  • 友情链接
  • 美食推荐 (opens new window)
  • 收藏夹

    • 优质前端信息源 (opens new window)
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

Gahing / francecil

To be best
首页
知识体系
  • 前端基础
  • 应用框架
  • 工程能力
  • 应用基础
  • 专业领域
  • 业务场景
  • 前端晋升 (opens new window)
  • Git
  • 网络基础
  • 算法
  • 数据结构
  • 编程范式
  • 编解码
  • Linux
  • AIGC
  • 其他领域

    • 客户端
    • 服务端
    • 产品设计
软素质
  • 面试经验
  • 人生总结
  • 个人简历
  • 知识卡片
  • 灵感记录
  • 实用技巧
  • 知识科普
  • 友情链接
  • 美食推荐 (opens new window)
  • 收藏夹

    • 优质前端信息源 (opens new window)
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 前端基础

  • 应用框架

  • 工程能力

  • 应用基础

  • 专业领域

    • 服务端

      • Deno

      • Node.js

        • Node.js 版本切换
        • Node子进程执行ping操作并获取统计信息
          • 需求
          • 分析
          • 编码
          • 问题解决
            • node-tree-kill 使用、源码及原理
            • 使用
            • 源码
            • 原理
        • Node 中的当前目录路径
        • node小bug记录
        • 事件驱动理解
        • 小技巧:Chrome 在线调试 Node
        • 深入浅出Node.js
        • log4js配置详解
        • node 模块源码解析

        • nodejs文件下载
      • 服务端框架

    • 跨端技术

    • Web IDE

    • 中后台

    • 动效渲染

    • 可视化

    • 埋点监控

    • 多媒体

    • 桌面技术

    • 游戏互动

    • 编辑器

    • 虚拟化与容器化

    • 设计系统

  • 业务场景

  • 大前端
  • 专业领域
  • 服务端
  • Node.js
gahing
2018-03-09
目录

Node子进程执行ping操作并获取统计信息

# 需求

采用ping -t方式不断进行ping操作,直到收到关闭信号or某个超时时间时结束操作,获取统计信息。

# 分析

在cmd窗口进行ping -t操作,会一直进行ping,直到输入ctrl+C 会输出ping统计信息。

kill('SIGINT') 即模拟 ctrl+C 终止进程

# 编码

这里我自己手动进行统计信息,原因见下面分析。

var exec = require('child_process').exec;
var iconv = require('iconv-lite');
let ping = exec(`ping www.google.com.hk -t`, { encoding: 'binary'}, function (err, stdout, stderr) {
    let send = 0
    let accept = 0
    let lost = 0
    let min = Infinity
    let max = -Infinity
    let avg = 0
    let Min = (a,b)=>a<b?a:b;
    let Max = (a,b)=>a>b?a:b;

    let str = iconv.decode(new Buffer(stdout, 'binary'), 'GBK')
    console.log(str);
    console.log('=========')
    let regAccept = /来自 .*的回复: 字节=(\d+) 时间=(\d+)ms TTL=(\d+)/g
    let regAll = /\n/g
    send = str.match(regAll).length - 2
    send=send<0?0:send
    let res
    while (res = regAccept.exec(str)) {
        accept++
        let tim = Number(res[2])
        min=Min(tim,min)
        max=Max(tim,max)
        avg= (avg*(accept-1)+tim)/accept
        console.log(res[1], tim, res[3],avg)
    }
    console.log('=========')
    console.log(`发送:${send};接收:${accept};丢失:${send-accept};${(1-(accept/send))*100}%丢失`)
    console.log(`最短:${min}ms;最长:${max}ms;平均:${avg}ms`)
});
ping.on('close', (code) => { console.log('close by', code) })
setTimeout(function () {
    ping.kill('SIGINT')
}, 5 * 1000);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

想通过ping.kill('SIGINT')去关闭exec子进程。

测试结果是:输出了 close by null 后,程序依然再运行,并且没有输出统计信息。

# 问题解决

思路1:在setTimeout中增加process.kill(ping.pid,'SIGINT');process.exit(0)

测试结果:程序会退出,但是没有输出close by也没有输出统计信息。并且任务管理器中ping进程仍然存在。

思路2:换个思路,给exec的options增加timeout参数,取消setTimeout。

测试结果:达到timeout时间后,会执行回调函数,可以输出统计信息(cmd ping操作最后的统计信息在这边是没有的,这边我自己进行了统计)。

但是!!ping进程并没有关闭。当ping进程大量存在的时候,ping的速度会越来越慢。

看到网上有篇文章child_process模块怎么真正的杀死子进程 (opens new window)有一样的问题。

最后他是采用 node-tree-kill (opens new window) 库解决。

# node-tree-kill 使用、源码及原理

# 使用

npm i tree-kill 安装

var kill = require('tree-kill');
setTimeout(function () {
    kill(ping.pid) //把最初代码这边做下替换
}, 5 * 1000);
1
2
3
4

# 源码

module.exports = function (pid, signal, callback) {
    var tree = {};
    var pidsToProcess = {};
    tree[pid] = [];
    pidsToProcess[pid] = 1;
    
    if (typeof signal === 'function' && callback === undefined) {
      callback = signal;
      signal = undefined;
    }

    switch (process.platform) {
    case 'win32':
        // /T终止指定的进程和由它启用的子进程
        // /F指定强制终止进程 /pid指定进程pid号
        exec('taskkill /pid ' + pid + ' /T /F', callback);
        break;
    case 'darwin':
        buildProcessTree(pid, tree, pidsToProcess, function (parentPid) {
          return spawn('pgrep', ['-P', parentPid]);
        }, function () {
            killAll(tree, signal, callback);
        });
        break;
    // case 'sunos':
    //     buildProcessTreeSunOS(pid, tree, pidsToProcess, function () {
    //         killAll(tree, signal, callback);
    //     });
    //     break;
    default: // Linux
        buildProcessTree(pid, tree, pidsToProcess, function (parentPid) {
          return spawn('ps', ['-o', 'pid', '--no-headers', '--ppid', parentPid]);
        }, function () {
            killAll(tree, signal, callback);
        });
        break;
    }
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

# 原理

很简单。就是调用了系统指令强行关闭进程,而不是原来程序中去做关闭。做了不同平台的兼容。

编辑 (opens new window)
上次更新: 2024/09/01, 23:56:56
Node.js 版本切换
Node 中的当前目录路径

← Node.js 版本切换 Node 中的当前目录路径→

最近更新
01
浅谈代码质量与量化指标
08-27
02
快速理解 JS 装饰器
08-26
03
Vue 项目中的 data-v-xxx 是怎么生成的
09-19
更多文章>
Theme by Vdoing | Copyright © 2016-2024 Gahing | 闽ICP备19024221号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式