NodeJS从诞生起发展非常迅速,社区活动非常活跃,目前扩展模块达到1500多个,并且每天都有不同的模块提交。它是构建在JavaScript引擎V8之上的JavaScript环境,它采用基于单线程的异步事件驱动I/O模型,具有非常高的性能,同时能够支持多种平台。日前国外的很多大的软件或互联网公司如Microsoft,ebay,yahoo等都在使用NodeJS,国内的网易,淘宝,新浪等互联网企业也有很多分享和成功的线上案例应用。言归正传,希望下文的内容能给不熟悉或不喜欢nix平台Shell脚本开发或WIN平台下的批处理编写的工程师带来一些帮助,为简单起见,本文采用Nix平台为示例,WIN平台的用户请参考自行修改或与作者联系。

首先,我承认Shell脚本中系统命令再加上sed,awk等瑞士军刀在一起工作已经相当强大,如果你想了解NodeJS的强大之处和如何结合Shell产生强大的工作效率,并且还能具有很好的灵活性,那就让我们继续旅程吧:

示例

先看一段简单的采用Shell 脚本执行一段命令得到其执行时间的脚本diffa.sh:

#!/bin/bash
START=$(date +%s)
# prepare things
du -m /home > /tmp/output
# done  END=$(date +%s)
DIFF=$(( $END - $START ))
echo "化了$DIFF 秒搞定"
chmod +x diff.sh
sh diff.sh

执行上面的脚本后,结果如下:

化了0 秒搞定

用户首次执行一般会耗时几秒,多次执行的结果可能会在0-1秒之间随机显示。因为du的输出重定向,整个脚本的执行时间非常短,并且脚本中采用的是秒数级别的范围,如果需要得到这个脚本的准确执行时间只能用纳秒来进行,并在Shell做除法运算,把脚本修改一下diffb.sh。

START=$(date +%s%N)
du -m /home/ >/tmp/output
END=$(date +%s%N)
DIFF=$(($END - $START))
SUM=`expr $DIFF / 1000000`
echo "化了$SUM MS搞定"

执行一下上面的diffb 脚本就可以得到运行的结果了,需要提醒的是上面的脚本中各表达式的格式都是即定的,如果开发人员不小心多了一个空格或少了一空格,都将导致脚本错误。下面采用NodeJS来试试看,首上下载与安装NodeJS环境,过程非常简单,具体请参考官方网站或直接apt-get 之类的操作。编写如下diffc.js脚本:

#!/usr/bin/env nodevar util = require('util'),spawn = require('child_process').spawn,ls = spawn('du', ['-m', '/home/']);
var start = +new Date();
ls.stdout.on('data', function (data) {//console.log('stdout: ' + data);
});
ls.stderr.on('data', function (data) {console.log('stderr: ' + data);
});
ls.on('exit', function (code) {var end = +new Date();console.log(end - start);
});

注:上面require中引用的都是系统内置模块,spawn的格式为spawn(command, [args], [options]),其他请参阅官方文档。

同样,chmod +x 对脚本赋予执行权限,执行脚本./diff.js,结果如下:

1113

上面示例中显示的时间直接是毫秒级别,代码格式没有严格的限制,流程的控制也会更加灵活,特别是在异常情况下,可以根据用户的需求处理更小的细节。当然,我承认这个示例需求有些诡异,但是做这样的比较,并不是说要二者一决高下,只是换一种前端攻城师喜欢的方法去实现一些系统运维需求。在这里NodeJS脚本本身也是依赖于系统Shell的强大基础之上。

深入一点

以上示例可以看到,在Shell环境中,NodeJS内置模块实现常用的功能是即方便又灵活,Linux Shell环境中比较强大的功能之一就是支持输入输出重定向功能,用符号<和>来表示。0、1和2分别表示标准输入、标准输出和标准错误信息输出,用来指定需要重定向的标准输入或输出,比如 2>error.log表示将错误信息输出到文件err.log中。类似的,NodeJS中可以直接采用超复杂的命令来搞定,一般对于我们这些非系统管理员有一定的难度,下面引入强大点的模块procstreams,它可以实现输出流重定向等功能,首先用户需要执行npm install procstreams安装模块,编写示例如下wc.js:

#!/usr/bin/env nodevar p = require('procstreams');
p('cat app.log').pipe('wc -l').data(function (stdout, stderr) {console.log(stdout);
});

wc.js脚本代码是借助于Shell命令实现统计app.log的行数,相当于Shell环境中的cat app.log | wc -l功能,输出的结果可以再根据需要再进行灵活处理,另外它还支持then、and和or等操作,类似Shell脚本中的;、&& 和||操作。在实现复杂或交互的功能时,甚至可以完全采用交互的方式进行操作输入。

另外,用户执行脚本的时候还需要处理复杂一些的参数对应,node-optimist 及 isaacs's nopt 之类的模块可以非常简单的帮助攻城师实现这样的功能,如实现根据用户的输入的参数执行需要的系统命令,并可以做相关的逻辑处理的opt.js:

#!/usr/bin/env nodevar util = require('util'),spawn = require('child_process').spawn;
var argv = require('optimist').argv;
var cmd = argv.cmd;
var args = argv.args
var option = argv.opt
var ls = spawn(cmd, [args, option]);
ls.stdout.on('data', function (data) {if (!data || !! data) console.log(' i believe it');
});
ls.stderr.on('data', function (data) {console.log('It\'s a miracle!');
});
ls.on('exit', function (code) {console.log('it.justHappened();');
});

用户使用如下对应格式执行代码:./opt.js --cmd=ls --args=/m --opt=/home,然后只需要在代码相关处添加对应的逻辑代码,把注意力放在业务层,采用js的流程控制实现业务逻辑的分离。

实际应用

在企业线上或系统运维中,常需要对一些进程进行监控和报警,以便通知相关系统管理人员,如下Shell脚本 agenta.sh实现了对tomcat6进程监控,如果不存在自动重启。

#!/bin/sh
pid=`ps aux| grep "tomcat6" | grep -v grep | sed -n  '1P' | awk '{print $2}'`
if [ -z $pid ]; thenecho "begin restart,please waiting..."sudo /etc/init.d/tomcat6 restartexit 1
elseecho -e "exist ,don't need restart"
fi

脚本编写人员在经过一番努力与折腾后,完成了代码编写与调试工作,然后需要通过系统的crontab功能添加如0-59/2 * * * * sh agent.sh的定时任务,如果系统管理员把crontab的权限给禁用了,那就需要得到系统管理员的帮助了。下面使用Nodejs来实现同样的功能,先假设读者对grep、sed和awk等常用命令的使用有大概了解,代码如下agentb.js:

var p = require('procstreams');
var exec = require('child_process').exec;
setInterval(function () {exec("ps aux| grep 'tomcat6' | grep -v grep | sed -n  '1P' | awk '{print $2}'", function (err, output) {if (err) throw err;if (output.length > 0) console.log('exist,don\'t need restart');else exec('sudo /etc/init.d/tomcat6 restart', function (err2, out2) {});})
}, 1000 * 60 * 2);

示例代码中setInterval的函数的作用通过设置一个回调函数和间隔执行时间来实现定时监控。运行代码后,同样可以实现进程监控的功能,也许你会说上面的Shell命令还是很多的。因为你觉得直接使用Shell脚本会更简单,可是如果你经历过为空格或配置之类的调试过程,或者需求更加复杂时,采用NodeJS会让你觉得非常轻松。更重要的是,编写脚本后,在执行脚本时你可以直接通过chrome debug 工具设置断点与单步调试,或者在chrome 浏览器上进行图形化调试等操作,具体请参考node-inspector。现在,agentb.js代码中的Shell命令还是太长了太复杂,调试起来也不太方便,使用procstreams做一下简化,实现代码agentc.js如下:

var p = require('procstreams');
setInterval(function () {p("ps aux").pipe('grep tomcat6').pipe('grep -v grep').pipe('sed -n 1P').pipe("awk $2").data(function (stdout, stderr) {if (stderr) throw stderr;if (stdout.length > 0) {console.log('exist,don\'t need restart');} else {console.log('restart,waiting...');p('sudo /etc/init.d/tomcat6 restart', function (stdout, stderror) {console.log(stdout);});}});
}, 1000 * 60 * 2);

agentc代码中通过pipe操作可以实现对每个步骤的输入进行详细的跟踪与调试,但是脚本中还是需要对系统的很多内置命令有大概的了解,需要对操作系统的相关功能或语法格式比较熟悉,使用起来还是有点不习惯。攻城师都喜欢编程时能控制住自己把握的,或者在使用简单的命令的情况下,就能实现需要的功能,再次简化代码后得到agentd.js

var p = require('procstreams');
var serviceName = 'tomcat6';
var interval = 1000 * 60 * 2;
setInterval(function () {p("ps aux").pipe('grep ' + serviceName).data(function (stdout, stderr) {if ( !! stdout && stdout.indexOf(serviceName) == 0) {console.log('exist,don\'t need restart');} else {console.log('restart,waiting...');p('sudo /etc/init.d/tomcat6 restart', function (stdout, stderror) {});}});
}, interval);

在经过这次修改之后,对系统命令的掌握程度要求明显更低了,题外话,用户对系统命令了解的越详细越好,但如果使用简单即美的指导去实现同样的需求,何乐而不为。代码中serviceName 和interval 参数可以通过node-optimist模块动态给定,这样就可以实现一份代码监控多个进程,并且不需要系统管理员的帮助去添加定时任务的操作。当然,希望这样操作不会影响系统功能或在权限范围内。

总结

尽管Linux的Shell环境编程非常的强大,但是编写或调试Shell脚本时常令人抓狂不已,也没有很好的图形化调试工具。当然脚本较复杂时,尤其在需求跨平台时,脚本改动比常较大,日前,开发人员需要根据平台的不同,准备多套脚本代码,如tomcat,apache等,如果采用简单Shell和NodeJS结合编程,或许只需要把平台相关的命令提取出来,只需较少改动就能实现跨平台,可以大大提高工作效率与减少浪费攻城师的时间。个人认为,采用二者结合的方式具有以下优点:

  1. 采用v8引擎,轻量级模块,较好跨平台性,较底层的系统操作,在系统监控运维等方面具有明显优势,
  2. 采用事件驱动非阻塞IO模型,无线程上下文切换和锁操作,, 可利用多核CPU计算,性能较高,
  3. 开放源代码,社区活跃,模块丰富,底层的扩展实现也较方便。

随着NodeJS不断发展和成熟,国内外厂商越来越多的成功案例与分享,在企业级和互联网系统应用开发和维护中具有更广阔的前景。

转载于:https://www.cnblogs.com/youdoce/archive/2012/02/19/2358018.html

当Shell遇上了NodeJS相关推荐

  1. [当人工智能遇上安全] 6.基于机器学习的入侵检测和攻击识别——以KDD CUP99数据集为例

    您或许知道,作者后续分享网络安全的文章会越来越少.但如果您想学习人工智能和安全结合的应用,您就有福利了,作者将重新打造一个<当人工智能遇上安全>系列博客,详细介绍人工智能与安全相关的论文. ...

  2. 【ArcGIS遇上Python】从入门到精通系列之第一章:ArcGIS Python简介

    文章目录 1. Python简介 2. Python的特点 3. ArcGIS的脚本语言 4. ArcGIS中的Python脚本编辑器 1. Python简介 Python是一种跨平台的计算机程序设计 ...

  3. 当SWOOLE遇上PROTOCOL

    前言 上回我们简单介绍了一下TCP Server的工作方式以及如何用Swoole实现一个简单的TCP Server,这次我们来聊聊信息流动中,非常重要基石之一--协议(PROTOCOL). 协议,通信 ...

  4. [当人工智能遇上安全] 5.基于机器学习算法的主机恶意代码识别研究

    您或许知道,作者后续分享网络安全的文章会越来越少.但如果您想学习人工智能和安全结合的应用,您就有福利了,作者将重新打造一个<当人工智能遇上安全>系列博客,详细介绍人工智能与安全相关的论文. ...

  5. 当摸鱼的老油条遇上了内卷的小年轻...真的是被卷怕了....

    软件测试岗当摸鱼的老油条遇上了内卷的小年轻,这是一个有趣的故事.老油条在公司里已经干了好几年,对软件测试的各种技巧和方法都非常熟悉,但也由于他的经验丰富,经常会被视为不求新进展而"发呆&qu ...

  6. 推荐系统遇上深度学习,9篇阿里推荐论文汇总!

    作者 | 石晓文 转载自小小挖掘机(ID: wAIsjwj) 业界常用的推荐系统主要分为两个阶段,召回阶段和精排阶段,当然有时候在最后还会接一些打散或者探索的规则,这点咱们就不考虑了. 前面九篇文章中 ...

  7. 华为平板电脑_当5G遇上平板电脑,华为MatePad Pro 5G带来了什么?

    5G已经来临,科技产品向5G升级已是大势所趋,这更是检验实力的探索之路. 2月24日,华为在巴塞罗那在线发布了一系列新品,其中,华为面向全球推出的5G高端旗舰平板,同时也是全球首款公开发布的5G平板华 ...

  8. 404未找到是什么意思_为什么老遇上404 not found?你懂的

    文章转载自公众号:一只学霸(bajie203) 昨天晚上 大毛火急火燎地打开了电脑 戴上了耳机 不到两分钟 -- 我们往前一凑 登等 果然是大家最害怕的一幕出现了 学霸在网上冲浪多年 留下的都是美好的 ...

  9. Linux环境Shell脚本上传下载阿里云OSS文件

    为什么80%的码农都做不了架构师?>>>    Linux环境Shell脚本上传下载阿里云OSS文件 背景 工作中由于我们项目生成的日志文件比较重要,而本地磁盘空间有限存储不了多久, ...

最新文章

  1. Spring配置文件applicationContext.xml的两种拆分方式
  2. leetcode1053. 交换一次的先前排列(贪心算法)
  3. C++编写简单的俄罗斯方块游戏
  4. vue 插件 滑块验证_vue滑块验证,原理,demo
  5. html固定悬浮窗效果,js 固定悬浮效果实现思路代码
  6. X86-64和ARM64用户栈的结构 (1) ---背景介绍
  7. html标签blockquote,HTML中的blockquote标签怎么用
  8. android格式化sd卡软件,如何在各种设备中把SD卡格式化?附误格式化数据恢复方法!...
  9. (附源码)springboot音乐播放小程序 毕业设计 031306
  10. RFT(Rational Functional Test)是IBM开发的一套自动化测试工具,可以测试web, GUI和console。
  11. android模拟电源按键
  12. Developing DataBase Applications Using MySQL Connector/C++ 中文文本
  13. ubuntu虚拟机中的vscode:扩展失败XHR Failed
  14. Zhong__Jenkins安装和使用
  15. Python项目实战之欢迎来到美多商城!学习目录导航
  16. 显示器预算有限,是买1080P 144HZ还是买2K 60HZ?
  17. Django框架的电商商城的设计与实现python语言
  18. 神马笔记 版本2.11.0——歌词笔记
  19. 0-1000Hz频率转4-20mA隔离变送器贝福IBF
  20. initramfs unpacking failed: Decoding failed 无法安装ubuntu 联想台式机

热门文章

  1. LeetCode(118)——杨辉三角(JavaScript)
  2. 计算机网络学习笔记(10. 速率、带宽、延迟)
  3. Linux---高级IO
  4. 【考研英语5500词】 —思维导图,建议收藏(四六级党也可入手)!!!
  5. 前端如何实现网络速度测试功能_如何通过fiddler的断点功能,来实现不同场景的测试...
  6. python和易语言爬虫速度_如何优化 Python 爬虫的速度?
  7. 我爱人71年3月出生,档案招工表填成74年了,如何办理退休?
  8. 吃冻梨对人会有什么好处?
  9. 毕业三年,攒了多少钱?
  10. 【go】metrics基本使用