随着node的流行,JS已经能够解决大部分问题。这对前端工程师十分友好。
相信不少同窗在开发业务之余,都会写一些小脚本代替手工完成繁琐,重复的工做,从而提升工做效率。
但部分同窗开发的脚本,仅局限于脚本所在路径,经过node xxx 去运行程序,这局限了脚本的使用范围和使用便捷性。css
本文就给你们介绍一个简单且一劳永逸的方法,把本身开发的node脚本部署在全局环境。让脚本能够像Linux命令同样,全局便捷地使用,今后打开新世界的大门。前端
export PATH=/Users/Momo/myShell:$PATH
#!/usr/bin/env node
,'use strict';
。#!/usr/bin/env node
是指本脚本是经过「/usr/bin/env」路径下的node软件运行。至关于文件中什么软件打开。'use strict';
是指使用js的严格语法。chmod 777 脚本文件名
,如示例chmod 777 mop
基本用法:node
// colors不是Node自带模块,须要事先npm install colors安装 const colors = require('colors'); // 引用colors模块,经常使用颜色 black,red,green,yellow,blue,magenta,cyan,white,gray,grey console.log(colors.red('filePath or targetPath can not be empty!')); // 在控制台输出红色的文案
let basePath = process.cwd(); // 其中process是node全局变量,提供当前 Node 进程的信息
基本用法:linux
let elem1 = process.argv[2]; // 携带的参数一 let elem2 = process.argv[3]; // 携带的参数二
基本用法:git
const child_process = require('child_process'); // child_process是node负责子进程的模块 child_process.exec('ls -a', function (error, stdout, stderr) { // 经过child_process下的exec函数执行linux命令 error && console.log('error ' + error); // 执行出错时的错误信息 console.log('Child Process STDOUT: ' + stdout); // stdout是执行linux命令后的执行 结果。在这里即返回执行ls -a命令遍历到的文件信息 });
基本用法:github
require('child_process').exec(`open http://baidu.com`); // 打开百度
shell
// 这是网上找到的,兼容各运行环境的打开页面方法 let cmd = ''; // 运行的指令 if (process.platform == 'wind32') { cmd = 'start "%ProgramFiles%\Internet Explorer\iexplore.exe"'; } else if (process.platform == 'linux') { cmd = 'xdg-open'; } else if (process.platform == 'darwin') { cmd = 'open'; } require('child_process').exec(`${cmd} http://baidu.com`);
介绍:上面介绍到的调用linux方法,本质上只是直接去调用具体的Linux命令。如调用ls,至关于直接找到系统里面ls这个脚本,执行它。
这和咱们日常在终端里面执行有什么区别呢?
在终端里面,咱们调用命令是携带上下文的。即第二条命令会在执行完第一条命令以后的环境下执行,例如npm
cd / ls
这两条命令是先切换到根路径,再打印跟路径下的文件信息。
若是像上面同样,经过gulp
require('child_process').exec(`cd /`); require('child_process').exec(`ls`);
则只是执行了两个相互独立的命令,一个是切换目录,一个是打印文件信息。ls打印的不是切换目录后的文件信息,而是运行脚本时所在的文件信息。
那怎么携带上下文执行linux命令呢?数组
基本用法:
// 注意,这里使用到了colors模块,用于显示不一样颜色的输出。不须要的话,也能够直接console.log()打印。 const subProcess = require('child_process').spawn("bash"); // 使用子程序去运行某个软件,在这里就是运行bash软件。至关于运行一个终端 subProcess.stdout.on('data', function(data) { console.log(colors.green(data)); }); // 监听命令执行后,bash返回的信息 subProcess.on('error', function() { console.log(colors.red('error\n' + arguments)); }); // 消息的错误监听 subProcess.on('close', (code) => { // 关闭bash进程后触发的事件 if (code === 0) { console.log(colors.blue(`执行成功!`)); } else { console.log(colors.blue(`执行失败,错误码为:${code}`)); } }); // 监听进程退出 //向子进程发送命令 subProcess.stdin.write(`cd / \n`); // 切换目录,\n表示回车,执行cd命令 subProcess.stdin.write(`ls -a \n`); // 写入数据 subProcess.stdin.end(); // 结束进程,至关于关闭终端
基本用法:
const copyProcess = require('child_process').spawn("bash"); // 用于复制密码的进程 copyProcess.stdin.write(`echo ${Config.server.password} | pbcopy`); // 将特定文本拷贝到剪切板中 copyProcess.stdin.end(); // 结束进程
上面介绍了一些基本的node功能,虽然看似很简答。但若是善于运用,也能够作出一些提升效率的小工具。
#!/usr/bin/env node 'use strict'; const colors = require('colors'); // 命令行颜色black,red,green,yellow,blue,magenta,cyan,white,gray,grey let helpName = process.argv[2]; // 须要查看的文档名 let helpInfo = { markdown: { '无需列表': '.1 xxx .1 xxx .1 xxx', '有需列表': '- xxx - xxx - xxx', } }; // 自定义帮助文档 // 设置文档name为他自己 let allHelpName = ''; let match = false; // 是否找到匹配项 for (let helpItem in helpInfo) { allHelpName += helpItem + `\n`; if (helpItem === helpName) { match = true; for (let detailItem in helpInfo[helpItem]) { console.log(colors.green(detailItem + ' : ' + helpInfo[helpItem][detailItem])); // 找不到页面相关信息 } return; } } if (!match) { console.log(colors.red('can not find matched helpInfo! the all helpName is')); // 找不到页面相关信息 console.log(colors.red(allHelpName)); // 找不到页面相关信息 }
#!/usr/bin/env node 'use strict'; const proess = require('child_process'); const copyProcess = proess.spawn("bash"); // 用于复制密码的进程,为了不同一个进程拷贝和上传时的冲突 const colors = require('colors'); // 命令行颜色black,red,green,yellow,blue,magenta,cyan,white,gray,grey const dataInfo = require('../config').dataInfo; const introduce = require('../config').shellInfo['mop'].introduce; // 脚本介绍,用在momoShell中介绍 let dataName = process.argv[2]; // 须要打开的页面 let onlyShow = process.argv[3]; // 是否只显示数据,不打开页面 let dataItem = dataInfo[dataName]; // 遍历成功后获取的页面对象 // 输入脚本简介 if (process.argv[2] === '-h') { console.log(colors.green(introduce)); copyProcess.stdin.end(); return; } // 检测数据有效性 if (!dataName) { // 参数为空 console.log(colors.red('dataName can not be empty!')); copyProcess.stdin.end(); return; } else if (!dataItem) { // 找不到页面信息 let allDataName = ''; for (let dataItem in dataInfo) { allDataName += `${dataItem}【${dataInfo[dataItem].info}】\n`; } console.log(colors.red('can not find matched dataInfo! the all dataName is')); // 找不到页面相关信息 console.log(colors.red(allDataName)); // 找不到页面相关信息 copyProcess.stdin.end(); return; } console.log(colors.green(`【name】${dataItem.name}`)); dataItem.account && console.log(colors.green(`【account】${dataItem.account}`)); dataItem.password && console.log(colors.green(`【password】${dataItem.password}`)); dataItem.url && console.log(colors.green(`【url】${dataItem.url}`)); // 将密码拷贝到剪切板中 copyProcess.stdin.write(`echo ${dataItem.password} | pbcopy`); // 写入数据 copyProcess.stdin.end(); !onlyShow && dataItem.url && require('child_process').exec(`open ${dataItem.url}`); // 打开特定页面
#!/usr/bin/env node 'use strict'; const Process = require('child_process').spawn("bash"); // 使用子程序去运行某个软件。在这里就是运行bash软件。并获取其上下文。 const colors = require('colors'); // 命令行颜色black,red,green,yellow,blue,magenta,cyan,white,gray,grey const Config = require('../config'); // 服务器信息 const introduce = Config.shellInfo['mgulp'].introduce; // 脚本介绍,用在momoShell中介绍 const elem = process.argv; // 输入的参数 const basePath = process.cwd(); const action = elem[2]; // 文件名 // 消息监听,监听子进程的输出。并在主进程中打印出来。 function onData(data) { console.log(colors.green(data)); } // 设置消息监听 Process.stdout.on('data', onData); Process.on('error', function() { console.log(colors.red('error\n' + arguments)); }); Process.on('close', (code) => { if (code === 0) { console.log(colors.blue(`执行成功!`)); } else { console.log(colors.blue(`执行成功失败,错误码为:${code}`)); } }); // 监听进程退出 if (action === '-h') { // 输入脚本简介 console.log(colors.green(introduce)); return; } else if (action === '-publish') { // 输入脚本简介 let inputPath = basePath + '/' + (elem[3] || ''); // 文件输入 let outputPath = basePath + '/' + elem[4]; // 文件输出 if (!elem[4]) { outputPath = basePath + `/a-gulp-publish/${elem[3]}`; } Process.stdin.write(`cd /Users/Momo/Desktop/intruction/Node/shell \n`); // 切换pwd Process.stdin.write(`gulp default --${inputPath} --${outputPath} \n`); // 执行gulp,经过「--」来让gulp不解析为gulp任务 Process.stdin.end(); } else if (action === '-watch') { // 输入脚本简介 let watchList = elem[3]; if (!watchList) { // 检测数据有效性 console.log(colors.red('watchList can not be empty!')); } else { watchList = watchList.split(',').map((item) => { // 格式化路径 item = basePath + '/' + item; item.replace(/\/\//g, '/'); // 去除双斜杠 if (item.indexOf('*') === -1) { // 监听全部文件,及旗下文件夹内的文件 item = item + '/*.*,' + item + '/*/*.*'; } return item; }); Process.stdin.write('cd /Users/Momo/Desktop/intruction/Node/shell \n'); // 切换pwd Process.stdin.write('gulp reload --${watchList.join(',')} \n'); // 执行gulp Process.stdin.end(); } } else { // 输入脚本简介 console.log(colors.red('please input action')); Process.stdin.end(); }
#!/usr/bin/env node 'use strict'; const colors = require('colors'); // 命令行颜色black,red,green,yellow,blue,magenta,cyan,white,gray,grey const Config = require('../config'); // 服务器信息 const copyProcess = require('child_process').spawn("bash"); // 用于复制密码的进程,为了不同一个进程拷贝和上传时的冲突 const subProcess = require('child_process').spawn("bash"); // 使用子程序去运行某个软件。在这里就是运行bash软件。并获取其上下文。 const introduce = Config.shellInfo['mupload'].introduce; // 脚本介绍,用在momoShell中介绍 let elem = process.argv; // 输入的参数 let basePath = process.cwd(); let filePath = basePath + '/' + elem[2]; // 文件名 let targetPath = elem[3]; // 目标路径 // 将服务器密码拷贝到剪切板中 copyProcess.stdin.write(`echo ${Config.server.password} | pbcopy`); // 写入数据 copyProcess.stdin.end(); // 输入脚本简介 if (process.argv[2] === '-h') { console.log(colors.green(introduce)); copyProcess.stdin.end(); subProcess.stdin.end(); return; } // 检测数据有效性 if (!filePath || !targetPath) { console.log(colors.red('filePath or targetPath can not be empty!')); subProcess.stdin.end(); return; } // 兼容目标路径 if (targetPath[targetPath.length - 1] === '/') { if (elem[2].indexOf('/') !== -1) { targetPath += elem[2].substr(elem[2].indexOf('/') + 1); } else { targetPath += elem[2]; } } // 消息监听,监听子进程的输出。并在主进程中打印出来。 function onData(data) { console.log(colors.green(data)); } //设置消息监听 subProcess.stdout.on('data', onData); subProcess.on('error', function() { console.log(colors.red('error\n' + arguments)); }); subProcess.on('close', (code) => { if (code === 0) { console.log(colors.blue(`上传成功!`)); console.log(colors.red(`注意,上传文件夹并不会覆盖原文件,请登陆服务器查看文件是否替换成功`)); } else { console.log(colors.blue(`上传失败,错误码为:${code}`)); } }); // 监听进程退出 //向子进程发送命令 subProcess.stdin.write(`scp -C -r -p ${filePath} root@${Config.server.ip}:${targetPath} \n`); // 写入数据 subProcess.stdin.end();
笔者在开发脚本时,遇到两个问题,有兴趣的大神能够指点指点
这是「一键上传文件或文件夹到服务器」遇到的问题,复制剪切板和scp命令会冲突,若是放在同一个bash进程执行会失败,没找到缘由。
这个功能我用linux的shell脚本实现过。可是放在node没能找到实现思路,