博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
如何设置node全局脚本
阅读量:7024 次
发布时间:2019-06-28

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

前语

随着node的流行,JS已经可以解决大部分问题。这对前端工程师十分友好。

相信很多同学在开发业务之余,都会写一些小脚本代替手工完成繁琐,重复的工作,从而提高工作效率。
但部分同学开发的脚本,仅局限于脚本所在路径,通过node xxx 去运行程序,这局限了脚本的使用范围和使用便捷性。

本文就给大家介绍一个简单且一劳永逸的方法,把自己开发的node脚本部署在全局环境。让脚本可以像Linux命令一样,全局便捷地使用,从此打开新世界的大门。

文件夹

全局脚本设置的本质思路

其实原理很简单:将Linux的全局命令搜索路径,加上脚本所在文件夹的路径。

文件夹

具体设置过程

找到终端配置文件

  • 终端配置文件默认路径为「/User/用户名」,笔者的mac用户名为Momo,故以下示例中用户名均为「Momo」。
  • 原配终端为bash,对应配置文件为「.bash.rc」。装了zsh终端的同学,对应修改「.zsh.rc」。
  • 解析:.rc文件为终端的配置文件,在重启终端,或者新开终端tab都会读取该文件。

文件夹

修改Linux的全局命令搜索路径

  • 打开文件,加上脚本所在文件夹。笔者的脚本均放在了myShell(其实应该叫myScript)文件夹中,所以加上一句export PATH=/Users/Momo/myShell:$PATH
  • 解析:在Linux中,全局命令搜索路径就是通过PATH变量保存起来的。「:」是字符串链接符的意思。类似于js中,var str = '1' + '2';中的「+」
    文件夹

修改js脚本文件

  • 在头部加上#!/usr/bin/env node'use strict';
  • 解析:#!/usr/bin/env node是指本脚本是通过「/usr/bin/env」路径下的node软件运行。相当于文件中什么软件打开。'use strict';是指使用js的严格语法。
  • 注意这两句一定要放置为js文件顶部,否则系统将不知道用什么软件执行。运行失败
    文件夹

修改js脚本文件权限

  • 终端运行chmod 777 脚本文件名,如示例chmod 777 mop
  • 解析:chmod是linux下修改文件权限的工具,777代表所有读写权限。具体的百度chmod即可。权限设置了以后,脚本的图标将变成下面这个样子。

    文件夹

重启或新建终端,执行脚本。

  • 解析:重启或新建终端是为了读取到刚修改的终端配置文件,让Linux的全局命令搜索路径生效。遍历到我们所开发的脚本。

脚本常用功能

设置不同颜色的console.log

  • 介绍:不同颜色的log除了美观,还可以起到警示的作用。需呀
  • 基本用法:

    // colors不是Node自带模块,需要事先npm install colors安装const colors = require('colors'); // 引用colors模块,常用颜色    black,red,green,yellow,blue,magenta,cyan,white,gray,greyconsole.log(colors.red('filePath or targetPath can not be empty!')); // 在控制台输出红色的文案

获取终端所在目录路径

  • 介绍:如题所示,获取终端当前所在目录,而不是脚本所在路径
  • 基本用法:let basePath = process.cwd(); // 其中process是node全局变量,提供当前 Node 进程的信息

携带参数运行脚本

  • 介绍:平时我们使用linux命令都会伴随一些参数,那么在node中怎么实现,怎么获取运行时携带的参数呢?通过process.argv即可,它将返回一个数组,由命令行执行脚本时的各个参数组成。它的第一个成员总是node,第二个成员是脚本文件名,其余成员是脚本文件的参数。
  • 基本用法:

    let elem1 = process.argv[2]; // 携带的参数一let elem2 = process.argv[3]; // 携带的参数二

调用linux命令

  • 介绍:有时候我们需要的功能并不是仅靠node就能实现的,还需要linux命令做支持。那怎么通过node调用Linux命令呢?
  • 基本用法:

    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命令遍历到的文件信息   });

打开页面

  • 介绍:怎么通过Node用浏览器打开特定页面呢?mac自带了open命令,我们通过node调用open命令打开页面即可。
  • 基本用法:

    require('child_process').exec(`open http://baidu.com`); // 打开百度

    // 这是网上找到的,兼容各运行环境的打开页面方法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方法,本质上只是直接去调用具体的Linux命令。如调用ls,相当于直接找到系统里面ls这个脚本,执行它。

    这和我们平常在终端里面执行有什么区别呢?
    在终端里面,我们调用命令是携带上下文的。即第二条命令会在执行完第一条命令之后的环境下执行,例如

    cd /ls

    这两条命令是先切换到根路径,再打印跟路径下的文件信息。

    如果像上面一样,通过

    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功能,虽然看似很简答。但如果善于运用,也可以做出一些提高效率的小工具。

,一键查看自定义文档

  • 功能介绍:自定义常用文档,方便地查看。例如markdown语法,常用全局匹配的正则什么的。省的重复打开笔记。
  • 基本思路:「colors颜色控制」+「携带参数运行脚本」
  • 示例代码:
#!/usr/bin/env node'use strict';const colors = require('colors'); // 命令行颜色black,red,green,yellow,blue,magenta,cyan,white,gray,greylet 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)); // 找不到页面相关信息}

,一键打开常用页面并复制密码到剪切板

  • 功能介绍:简单,一个命令打开特定页面,而且帮你把特定文案复制到剪切板。例如?登陆密码。
  • 基本思路:「复制剪切板」+「打开页面」+「colors颜色控制」
  • 示例代码:
#!/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,greyconst 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}`); // 打开特定页面

,一键gulp打包项目,一键动态刷新

  • 功能介绍:解决了每个项目都需要配置gulp及其依赖的麻烦。功能就如标题所说,一键gulp打包项目,一键动态刷新(需结合)
  • 基本思路:「携带参数运行脚本」+「携带上下文执行linux命令」
  • 示例代码:(这里还需结合gulpfile.js文件一起使用,详情请查看笔者)
#!/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,greyconst 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();}

,一键上传文件或文件夹到服务器

  • 功能介绍:如题,可上传整个文件夹,不需要打开ftp软件这么麻烦(注意scp命令不支持强制覆盖文件夹功能)
  • 基本思路:「复制剪切板」+「调用linux命令」+ 「scp命令」
  • 示例代码:
#!/usr/bin/env node'use strict';const colors = require('colors'); // 命令行颜色black,red,green,yellow,blue,magenta,cyan,white,gray,greyconst 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();

还有其他的,像什么「一键git」「一键svn」,这些就根据实际需要组合开发啦。

问题求助

笔者在开发脚本时,遇到两个问题,有兴趣的大神可以指点指点

文件夹

复制剪切板和scp的冲突

这是「一键上传文件或文件夹到服务器」遇到的问题,复制剪切板和scp命令会冲突,如果放在同一个bash进程执行会失败,没找到原因。

linux应答式异步交互,实现ssh的一键登录。

这个功能我用linux的shell脚本实现过。但是放在node没能找到实现思路,

转载地址:http://oppxl.baihongyu.com/

你可能感兴趣的文章
PHP以树状形式遍历目录结构
查看>>
我的友情链接
查看>>
通过mysql 插入一句话***
查看>>
centos 分区扩容
查看>>
JBoss EAP 6 monitoring using remoting-jmx and Zabbix
查看>>
邮件服务器
查看>>
OOAD-设计模式-原型模式
查看>>
Java FAQ(2)
查看>>
JavaScript常用事件总结
查看>>
squid在企业网中的应用
查看>>
主元素 Majority Element
查看>>
关于加密的一些笔记
查看>>
MySQL并发处理
查看>>
android Bitmap的内存优化
查看>>
我的友情链接
查看>>
mysql主从备份
查看>>
高并发Web服务的演变—节约系统内存和CPU
查看>>
MyBatis的Batch处理导致秒杀系统超卖的问题
查看>>
远程备份电脑 —— 方案二:不需要使用.bat批运行文件
查看>>
解决Redhat Linux5 yum出现This system is not registered with RHN的方法
查看>>