博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Node.js 命令行程序开发教程
阅读量:5235 次
发布时间:2019-06-14

本文共 5244 字,大约阅读时间需要 17 分钟。

1. 可执行脚本

// 使用javascript语言编写一个可执行脚本

#! /usr/bin/env nodeconsole.log('hello')
!/usr/bin/node 和 #! /usr/bin/env node 意思及区别

是Unix和Linux脚本语言的第一行,目的就是指出,你想要你的这个文件中的代码用什么可执行程序去运行它

!/usr/bin/node是告诉操作系统执行这个脚本的时候,调用/usr/bin下的node解释器;

!/usr/bin/env node这种用法是为了防止操作系统用户没有将node装在默认的/usr/bin路径里。当系统看到这一行的时候,首先会到env设置里查找node的安装路径,再调用对应路径下的解释器程序完成操作。

!/usr/bin/node相当于写死了node路径;

!/usr/bin/env node会去环境设置寻找node目录,推荐这种写法

在命令行中输入 hello

报错 zsh: command not found: hello
修改权限 chmod 755 hello

chmod 755

/*

chmod是Linux下设置文件权限的命令,后面的数字表示不同用户或用户组的权限。

一般是三个数字:

第一个数字表示文件所有者的权限

第二个数字表示与文件所有者同属一个用户组的其他用户的权限

第三个数字表示其它用户组的权限。

权限分为三种:读(r=4),写(w=2),执行(x=1)。综合起来还有可读可执行(rx=5=4+1)、可读可写(rw=6=4+2)、可读可写可执行(rwx=7=4+2+1)。

所以,chmod 755 设置用户的权限为:

1.文件所有者可读可写可执行

2.与文件所有者同属一个用户组的其他用户可读可执行

3.其它用户组可读可执行

*/

在命令行中输入 ./hello

控制台打印出hello

如果想直接执行 hello 去掉前面的./ 则有两种方案

  1. 把当前hello文件的路径放入到环境变量中
  2. 更好的做法是在当前目录下创建一个package.json
{    name: 'hello',    "bin": {        "hello": "hello"    }}

然后 npm link

再执行hello 就不用输入路径了

### 2.命令行参数的原始写法

命令行参数可以用系统的process.argv获取

#!/usr/bin/env nodeconsole.log('hello ',process.argv[2]);console.log(process.argv);// [ '/usr/local/bin/node', '/usr/local/bin/hello', 'liu' ]// process.argv 这个是一个数组,第一个参数是当前可执行程序的本机路径  第二个参数是当前文本的路径  第三个参数及以后的参数都是命令行参数

在命令行中输入 hello liu 输出 hello liu

3. 新建进程

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

#!/usr/bin/env nodelet name = process.argv[2];let {exec} = require('child_process');let child  = exec('echo hello '+name,(err,stdout,stderr)=>{    if(err) throw err;    console.info(stdout);});// child_process模块用于新建子进程。子进程的运行结果储存在系统缓存之中(最大200KB),等到子进程运行结束以后,主进程再用回调函数读取子进程的运行结果。// exec方法最多可以接受两个参数,第一个参数是所要执行的shell命令,第二个参数是回调函数,该函数接受三个参数,分别是发生的错误、标准输出的显示结果、标准错误的显示结果。// 由于标准输出和辨准错误都是流对象,可以监听data事件,因此上面的代码可以写成下面的样子let child = exec('echo hello ' + name);child.stdout.on('data', function(data){    console.log('stdout:'+data)})child.stderr.on('data', function(data){    console.log('stderr:'+data)})child.on('close', function(code){    console.log('closing code:'+code)})// 上面的代码还表明,子进程本身有close事件,可以设置回调函数。// 上面的代码还有一个好处。监听data事件以后,可以实时输出结果,否则只有等到子进程结束,才会输出结果。所以,如果子进程运行时间较长,或者是持续运行,第二种写法更好。

exec()方法存在的问题?

exec方法会直接调用bash(bin/sh程序)即shell脚本来解析命令,所以如果有用户输入的参数,exec方法是不安全的

let exec = require('child_process').exec;// exec('node -v', function (error, stdout, stderr) {//     if (error !== null) {//         console.log('exec error' + error)//     }//     console.log('stdout:' + stdout); // stdout:v8.9.3//     console.log('stderr:' + stderr); // stderr:// })// node child.jslet path = ";user input";exec('ls -l' + path, function (err, stdout, stderr) {    console.log('输出',stdout)})// 上面代码表示,在bash环境下,ls -l; user input会直接运行。如果用户输入恶意代码,将会带来安全风险。因此,在有用户输入的情况下,最好不使用exec方法,而是使用execFile方法。

execSync()

execSync是exec的同步执行版本。

它可以接受两个参数,第一个参数是所要执行的命令,第二个参数用来配置执行环境。

execFile()

execFile方法直接执行特定的程序,参数作为数组传入,不会被bash解释,因此具有较高的安全性。

var child_process = require('child_process');var path = ".";child_process.execFile('/bin/ls', ['-l', path], function (err, result) {    console.log(result)});

上面代码中,假定path来自用户输入,如果其中包含了分号或反引号,ls程序不理解它们的含义,因此也就得不到运行结果,安全性就得到了提高。

4. yarys 模块用于处理命令行参数

4.1 安装

npm install yargs --save

4.2 读取命令行参数

yargs模块提供了argv对象来读取命令行参数

#! /usr/bin/env nodelet argv = require('yargs').argvconsole.log('yargs'+ argv['_'][0] + argv['_'][1])console.log(argv)// ./yargs liu shiyu// { _: [ 'liu', 'shiyu' ],     help: false,     version: false,     '$0': 'yargs'   }  // 从这个例子我们发现 命令行所传的参数 全部放在argv['_'] 的数组中  console.log('yargs'+ argv.name)  // yargs --name=liu  // yargsliu

4.3 可以指定别名

let argv require('yargs').alias('n','name').argv// yargs --n liu// yargsliu{ _: [],  help: false,  version: false,  n: 'liu',  name: 'liu',  '$0': 'yargs' }

4.4 下划线属性

argv对象有一个下划线属性,是一个数组,里面存放的是非连词线开头的参数

#! /usr/bin/env nodelet argv = require('yargs').argvconsole.log('yargs'+ argv._)// yargs liu shiyu// [ 'liu', 'shiyu' ]

4.5 命令行参数的配置

demand 是否必选default 默认值describe 提示```#!/usr/bin/env nodelet argv = require('yargs')  .demand(['n'])  .default({n:'liu'})  .describe({n:"你的名字"})  .argv; console.log('hello ',argv.n); // yargs // hello liu 不传的话取默认值```options 方法允许将所有的配置写入配置对象```let yargs = require('yargs');let argv = yargs.option('n',{    alias: 'name',    demand: true,    describe: '请输入你的名字',    type: 'string',}).argvconsole.log('hello ' + argv.n)// yargs --n=liushiyu// yargs --name=liushiyu// hello liushiyu```有时候,某些参数不需要,只起到开关的作用,可以用boolean指定这些参数返回布尔值
#!/usr/bin/env nodelet argv = require('yargs')    .boolean(['private'])    .argvconsole.log('hello',argv.n);

4.6 帮助信息

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

usage 用法格式

example 提供例子
help 显示帮助信息
epilog 出现在帮助信息的结尾

let yargs = require('yargs');let argv = yargs.option('n',{    alias: 'name',    demand: true,    describe: '请输入你的名字',    type: 'string',}).usage('Usage: yargs [options]')    .example('yargs -n liu','say hello to liu')    .help('h')    .alias('h','help')    .epilog('copyright 2018')    .argvconsole.log('hello ' + argv.n)// Usage: yargs [options]Options:  --version   Show version number                                      [boolean]  -n, --name  请输入你的名字                                 [string] [required]  -h, --help  Show help                                                [boolean]Examples:  yargs -n liu  say hello to liucopyright 2018

转载于:https://www.cnblogs.com/qinmengjiao123-123/p/8520807.html

你可能感兴趣的文章
iOS: 数据持久化方案
查看>>
Neo4j学习笔记
查看>>
【C#】【Thread】Monitor和Lock
查看>>
UVALive - 3635 - Pie(二分)
查看>>
jQuery的中文乱码问题[转]
查看>>
bzoj 2005 & 洛谷 P1447 [ Noi 2010 ] 能量采集 —— 容斥 / 莫比乌斯反演
查看>>
P1631 序列合并
查看>>
Luogu_4886 快递员
查看>>
内存优化文章链接
查看>>
ext4.0 代理 的使用
查看>>
数据检查约束类型和语法
查看>>
AngularJS实战之路由ui-view
查看>>
使用jQuery+huandlebars防止编码注入攻击
查看>>
C#的托管与非托管大难点
查看>>
[转]HTTPS简谈
查看>>
(图片)jsp上传图片,进行缩放处理
查看>>
集合类List,set,Map 的遍历方法,用法和区别
查看>>
HDU-2577-How to Type
查看>>
java日志框架之logback——布局详细说明书地址
查看>>
Java Selenium (十二) 操作弹出窗口 & 智能等待页面加载完成 & 处理 Iframe 中的元素...
查看>>