隨着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沒能找到實現思路,