详解Node.js 命令行程序开发教程


Posted in Javascript onJune 07, 2017

一种编程语言是否易用,很大程度上,取决于开发命令行程序的能力。

Node.js 作为目前最热门的开发工具之一,怎样使用它开发命令行程序,是 Web 开发者应该掌握的技能。

下面就是我在它的基础上扩展的教程,应该是目前最好的解决方案了。

一、可执行脚本

我们从最简单的讲起。

首先,使用 JavaScript 语言,写一个可执行脚本 hello 。

#!/usr/bin/env node
console.log('hello world');

然后,修改 hello 的权限。

$ chmod 755 hello

现在,hello 就可以执行了。

$ ./hello
hello world

如果想把 hello 前面的路径去除,可以将 hello 的路径加入环境变量 PATH。但是,另一种更好的做法,是在当前目录下新建 package.json ,写入下面的内容。

{
 "name": "hello",
 "bin": {
  "hello": "hello"
 }
}

然后执行 npm link 命令。

$ npm link

现在再执行 hello ,就不用输入路径了。

$ hello
hello world

二、命令行参数的原始写法

命令行参数可以用系统变量 process.argv 获取。

下面是一个脚本 hello 。

#!/usr/bin/env node
console.log('hello ', process.argv[2]);

执行时,直接在脚本文件后面,加上参数即可。

$ ./hello tom
hello tom

上面代码中,实际上执行的是 node ./hello tom ,对应的 process.argv 是 ['node', '/path/to/hello', 'tom'] 。

三、新建进程

脚本可以通过 child_process 模块新建子进程,从而执行 Unix 系统命令。

#!/usr/bin/env node
var name = process.argv[2];
var exec = require('child_process').exec;

var child = exec('echo hello ' + name, function(err, stdout, stderr) {
 if (err) throw err;
 console.log(stdout);
});

用法如下。

$ ./hello tom
hello tom

四、shelljs 模块

shelljs 模块重新包装了 child_process,调用系统命令更加方便。它需要安装后使用。

npm install --save shelljs

然后,改写脚本。

#!/usr/bin/env node
var name = process.argv[2];
var shell = require("shelljs");

shell.exec("echo hello " + name);

上面代码是 shelljs 的本地模式,即通过 exec 方法执行 shell 命令。此外还有全局模式,允许直接在脚本中写 shell 命令。

require('shelljs/global');

if (!which('git')) {
 echo('Sorry, this script requires git');
 exit(1);
}

mkdir('-p', 'out/Release');
cp('-R', 'stuff/*', 'out/Release');

cd('lib');
ls('*.js').forEach(function(file) {
 sed('-i', 'BUILD_VERSION', 'v0.1.2', file);
 sed('-i', /.*REMOVE_THIS_LINE.*\n/, '', file);
 sed('-i', /.*REPLACE_LINE_WITH_MACRO.*\n/, cat('macro.js'), file);
});
cd('..');

if (exec('git commit -am "Auto-commit"').code !== 0) {
 echo('Error: Git commit failed');
 exit(1);
}

五、yargs 模块

shelljs 只解决了如何调用 shell 命令,而 yargs 模块能够解决如何处理命令行参数。它也需要安装。

$ npm install --save yargs

yargs 模块提供 argv 对象,用来读取命令行参数。请看改写后的 hello 。

#!/usr/bin/env node
var argv = require('yargs').argv;

console.log('hello ', argv.name);

使用时,下面两种用法都可以。

$ hello --name=tom
hello tom

$ hello --name tom
hello tom

也就是说,process.argv 的原始返回值如下。

$ node hello --name=tom
[ 'node',
 '/path/to/myscript.js',
 '--name=tom' ]

yargs 可以上面的结果改为一个对象,每个参数项就是一个键值对。

var argv = require('yargs').argv;

// $ node hello --name=tom
// argv = {
//  name: tom
// };

如果将 argv.name 改成 argv.n,就可以使用一个字母的短参数形式了。

$ hello -n tom
hello tom

可以使用 alias 方法,指定 name 是 n 的别名。

#!/usr/bin/env node
var argv = require('yargs')
 .alias('n', 'name')
 .argv;

console.log('hello ', argv.n);

这样一来,短参数和长参数就都可以使用了。

$ hello -n tom
hello tom
$ hello --name tom
hello tom

argv 对象有一个下划线(_)属性,可以获取非连词线开头的参数。

#!/usr/bin/env node
var argv = require('yargs').argv;

console.log('hello ', argv.n);
console.log(argv._);

用法如下。

$ hello A -n tom B C
hello tom
[ 'A', 'B', 'C' ]

六、命令行参数的配置

yargs 模块还提供3个方法,用来配置命令行参数。

  1. demand:是否必选
  2. default:默认值
  3. describe:提示
#!/usr/bin/env node
var argv = require('yargs')
 .demand(['n'])
 .default({n: 'tom'})
 .describe({n: 'your name'})
 .argv;

console.log('hello ', argv.n);

上面代码指定 n 参数不可省略,默认值为 tom,并给出一行提示。

options 方法允许将所有这些配置写进一个对象。

#!/usr/bin/env node
var argv = require('yargs')
 .option('n', {
  alias : 'name',
  demand: true,
  default: 'tom',
  describe: 'your name',
  type: 'string'
 })
 .argv;

console.log('hello ', argv.n);

有时,某些参数不需要值,只起到一个开关作用,这时可以用 boolean 方法指定这些参数返回布尔值。

#!/usr/bin/env node
var argv = require('yargs')
 .boolean(['n'])
 .argv;

console.log('hello ', argv.n);

上面代码中,参数 n 总是返回一个布尔值,用法如下。

$ hello
hello false
$ hello -n
hello true
$ hello -n tom
hello true

boolean 方法也可以作为属性,写入 option 对象。

#!/usr/bin/env node
var argv = require('yargs')
 .option('n', {
  boolean: true
 })
 .argv;

console.log('hello ', argv.n);

七、帮助信息

yargs 模块提供以下方法,生成帮助信息。

  1. usage:用法格式
  2. example:提供例子
  3. help:显示帮助信息
  4. epilog:出现在帮助信息的结尾
#!/usr/bin/env node
var argv = require('yargs')
 .option('f', {
  alias : 'name',
  demand: true,
  default: 'tom',
  describe: 'your name',
  type: 'string'
 })
 .usage('Usage: hello [options]')
 .example('hello -n tom', 'say hello to Tom')
 .help('h')
 .alias('h', 'help')
 .epilog('copyright 2015')
 .argv;

console.log('hello ', argv.n);

执行结果如下。

$ hello -h

Usage: hello [options]

Options:
 -f, --name your name [string] [required] [default: "tom"]
 -h, --help Show help [boolean]

Examples:
 hello -n tom say hello to Tom

copyright 2015

八、子命令

yargs 模块还允许通过 command 方法,设置 Git 风格的子命令。

#!/usr/bin/env node
var argv = require('yargs')
 .command("morning", "good morning", function (yargs) {
  console.log("Good Morning");
 })
 .command("evening", "good evening", function (yargs) {
  console.log("Good Evening");
 })
 .argv;

console.log('hello ', argv.n);

用法如下。

$ hello morning -n tom
Good Morning
hello tom

可以将这个功能与 shellojs 模块结合起来。

#!/usr/bin/env node
require('shelljs/global');
var argv = require('yargs')
 .command("morning", "good morning", function (yargs) {
  echo("Good Morning");
 })
 .command("evening", "good evening", function (yargs) {
  echo("Good Evening");
 })
 .argv;

console.log('hello ', argv.n);

每个子命令往往有自己的参数,这时就需要在回调函数中单独指定。回调函数中,要先用 reset 方法重置 yargs 对象。

#!/usr/bin/env node
require('shelljs/global');
var argv = require('yargs')
 .command("morning", "good morning", function (yargs) { 
  echo("Good Morning");
  var argv = yargs.reset()
   .option("m", {
    alias: "message",
    description: "provide any sentence"
   })
   .help("h")
   .alias("h", "help")
   .argv;

  echo(argv.m);
 })
 .argv;

用法如下。

$ hello morning -m "Are you hungry?"
Good Morning
Are you hungry?

九、其他事项

(1)返回值

根据 Unix 传统,程序执行成功返回 0,否则返回 1 。

if (err) {
 process.exit(1);
} else {
 process.exit(0);
}

(2)重定向

Unix 允许程序之间使用管道重定向数据。

$ ps aux | grep 'node'

脚本可以通过监听标准输入的data 事件,获取重定向的数据。

process.stdin.resume();
process.stdin.setEncoding('utf8');
process.stdin.on('data', function(data) {
 process.stdout.write(data);
});

下面是用法。

$ echo 'foo' | ./hello
hello foo

(3)系统信号

操作系统可以向执行中的进程发送信号,process 对象能够监听信号事件。

process.on('SIGINT', function () {
 console.log('Got a SIGINT');
 process.exit(0);
});

发送信号的方法如下。

$ kill -s SIGINT [process_id]

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
setAttribute 与 class冲突解决
Feb 17 Javascript
JQuery 获取和设置Select选项的代码
Feb 07 Javascript
AlertBox 弹出层信息提示框效果实现步骤
Oct 11 Javascript
js函数的引用, 关于内存的开销
Sep 17 Javascript
页面js遇到乱码问题的解决方法是和无法转码的情况
Apr 30 Javascript
jquery实现textarea输入框限制字数的方法
Jan 15 Javascript
实例详解jQuery结合GridView控件的使用方法
Jan 04 Javascript
location.hash保存页面状态的技巧
Apr 28 Javascript
js实现右键自定义菜单
Dec 03 Javascript
vue-router配合ElementUI实现导航的实例
Feb 11 Javascript
Vue Render函数创建DOM节点代码实例
Jul 08 Javascript
gojs实现蚂蚁线动画效果
Feb 18 Javascript
详解vee-validate的使用个人小结
Jun 07 #Javascript
微信小程序多张图片上传功能
Jun 07 #Javascript
Vue.js对象转换实例
Jun 07 #Javascript
深入理解Angular4中的依赖注入
Jun 07 #Javascript
Vue中保存用户登录状态实例代码
Jun 07 #Javascript
jquery dataTable 后台加载数据并分页实例代码
Jun 07 #jQuery
jQuery用户头像裁剪插件cropbox.js使用详解
Jun 07 #jQuery
You might like
【动漫杂谈】关于《请在T台上微笑》
2020/03/03 日漫
Windows2003 下 MySQL 数据库每天自动备份
2006/12/21 PHP
用Zend Encode编写开发PHP程序
2010/02/21 PHP
PHP的范围解析操作符(::)的含义分析说明
2011/07/03 PHP
PHP实现的多维数组去重操作示例
2018/07/21 PHP
jquery Mobile入门—多页面切换示例学习
2013/01/08 Javascript
js replace替换所有匹配的字符串
2014/02/13 Javascript
通过Jquery的Ajax方法读取将table转换为Json
2014/05/31 Javascript
node.js中的fs.ftruncate方法使用说明
2014/12/15 Javascript
jQuery中removeAttr()方法用法实例
2015/01/05 Javascript
jQuery实现垂直半透明手风琴特效代码分享
2015/08/21 Javascript
jQuery实时显示鼠标指针位置和键盘ASCII码
2016/03/28 Javascript
基于BootStrap Metronic开发框架经验小结【一】框架总览及菜单模块的处理
2016/05/12 Javascript
解决微信浏览器Javascript无法使用window.location.reload()刷新页面
2016/06/21 Javascript
微信小程序图表插件(wx-charts)实例代码
2017/01/17 Javascript
jQuery实现的简单悬浮层功能完整实例
2017/01/23 Javascript
angular ng-repeat数组中的数组实例
2017/02/18 Javascript
Vue 自定义标签的src属性不能使用相对路径的解决
2019/09/17 Javascript
nodejs+express最简易的连接数据库的方法
2020/12/23 NodeJs
原生js拖拽功能制作滑动条实例代码
2021/02/05 Javascript
python logging 日志轮转文件不删除问题的解决方法
2016/08/02 Python
Python冲顶大会 快来答题!
2018/01/17 Python
python操作excel的方法
2018/08/16 Python
Python os.rename() 重命名目录和文件的示例
2018/10/25 Python
python找出完数的方法
2018/11/12 Python
解决pycharm工程启动卡住没反应的问题
2019/01/19 Python
linux下python中文乱码解决方案详解
2019/08/28 Python
python使用celery实现异步任务执行的例子
2019/08/28 Python
ubuntu16.04升级Python3.5到Python3.7的方法步骤
2020/08/20 Python
生产部统计员岗位职责
2014/01/05 职场文书
愚人节活动策划方案
2014/03/11 职场文书
学生评语大全
2014/04/18 职场文书
爱祖国演讲稿
2014/05/04 职场文书
党员个人查摆剖析材料
2014/10/16 职场文书
学生自我评语
2015/01/04 职场文书
办公经费申请报告
2015/05/15 职场文书