// 使用javascript语言编写一个可执行脚本javascript
#! /usr/bin/env node console.log('hello')
是Unix和Linux脚本语言的第一行,目的就是指出,你想要你的这个文件中的代码用什么可执行程序去运行它html
!/usr/bin/node是告诉操做系统执行这个脚本的时候,调用/usr/bin下的node解释器;
!/usr/bin/env node这种用法是为了防止操做系统用户没有将node装在默认的/usr/bin路径里。当系统看到这一行的时候,首先会到env设置里查找node的安装路径,再调用对应路径下的解释器程序完成操做。java
!/usr/bin/node至关于写死了node路径;
!/usr/bin/env node会去环境设置寻找node目录,推荐这种写法node
在命令行中输入 hello
报错 zsh: command not found: hello
修改权限 chmod 755 helloshell
/*
chmod是Linux下设置文件权限的命令,后面的数字表示不一样用户或用户组的权限。npm
通常是三个数字:json
第一个数字表示文件全部者的权限数组
第二个数字表示与文件全部者同属一个用户组的其余用户的权限缓存
第三个数字表示其它用户组的权限。安全
权限分为三种:读(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 去掉前面的./ 则有两种方案
{ name: 'hello', "bin": { "hello": "hello" } }
而后 npm link
再执行hello 就不用输入路径了
### 2.命令行参数的原始写法
命令行参数能够用系统的process.argv获取
#!/usr/bin/env node console.log('hello ',process.argv[2]); console.log(process.argv); // [ '/usr/local/bin/node', '/usr/local/bin/hello', 'liu' ] // process.argv 这个是一个数组,第一个参数是当前可执行程序的本机路径 第二个参数是当前文本的路径 第三个参数及之后的参数都是命令行参数
在命令行中输入 hello liu 输出 hello liu
脚本能够经过child_process模块新建子进程,从而执行Linux 命令
#!/usr/bin/env node let 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.js let 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.1 安装
npm install yargs --save
4.2 读取命令行参数
yargs模块提供了argv对象来读取命令行参数
#! /usr/bin/env node let argv = require('yargs').argv console.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 node let argv = require('yargs').argv console.log('yargs'+ argv._) // yargs liu shiyu // [ 'liu', 'shiyu' ]
4.5 命令行参数的配置
demand 是否必选 default 默认值 describe 提示 ``` #!/usr/bin/env node let 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', }).argv console.log('hello ' + argv.n) // yargs --n=liushiyu // yargs --name=liushiyu // hello liushiyu ``` 有时候,某些参数不须要,只起到开关的做用,能够用boolean指定这些参数返回布尔值
#!/usr/bin/env node let argv = require('yargs') .boolean(['private']) .argv console.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') .argv console.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 liu copyright 2018