摘要:全局腳本設(shè)置的本質(zhì)思路其實(shí)原理很簡單將的全局命令搜索路徑,加上腳本所在文件夾的路徑。權(quán)限設(shè)置了以后,腳本的圖標(biāo)將變成下面這個樣子。重啟或新建終端,執(zhí)行腳本。
前語
隨著node的流行,JS已經(jīng)可以解決大部分問題。這對前端工程師十分友好。
相信很多同學(xué)在開發(fā)業(yè)務(wù)之余,都會寫一些小腳本代替手工完成繁瑣,重復(fù)的工作,從而提高工作效率。
但部分同學(xué)開發(fā)的腳本,僅局限于腳本所在路徑,通過node xxx 去運(yùn)行程序,這局限了腳本的使用范圍和使用便捷性。
本文就給大家介紹一個簡單且一勞永逸的方法,把自己開發(fā)的node腳本部署在全局環(huán)境。讓腳本可以像Linux命令一樣,全局便捷地使用,從此打開新世界的大門。
全局腳本設(shè)置的本質(zhì)思路 其實(shí)原理很簡單:將Linux的全局命令搜索路徑,加上腳本所在文件夾的路徑。 具體設(shè)置過程 找到終端配置文件終端配置文件默認(rèn)路徑為「/User/用戶名」,筆者的mac用戶名為Momo,故以下示例中用戶名均為「Momo」。
原配終端為bash,對應(yīng)配置文件為「.bash.rc」。裝了zsh終端的同學(xué),對應(yīng)修改「.zsh.rc」。
解析:.rc文件為終端的配置文件,在重啟終端,或者新開終端tab都會讀取該文件。
修改Linux的全局命令搜索路徑打開文件,加上腳本所在文件夾。筆者的腳本均放在了myShell(其實(shí)應(yīng)該叫myScript)文件夾中,所以加上一句export PATH=/Users/Momo/myShell:$PATH
解析:在Linux中,全局命令搜索路徑就是通過PATH變量保存起來的。「:」是字符串鏈接符的意思。類似于js中,var str = "1" + "2";中的「+」
在頭部加上#!/usr/bin/env node,"use strict";。
解析:#!/usr/bin/env node是指本腳本是通過「/usr/bin/env」路徑下的node軟件運(yùn)行。相當(dāng)于文件中什么軟件打開。"use strict";是指使用js的嚴(yán)格語法。
注意這兩句一定要放置為js文件頂部,否則系統(tǒng)將不知道用什么軟件執(zhí)行。運(yùn)行失敗
終端運(yùn)行chmod 777 腳本文件名,如示例chmod 777 mop
解析:chmod是linux下修改文件權(quán)限的工具,777代表所有讀寫權(quán)限。具體的百度chmod即可。權(quán)限設(shè)置了以后,腳本的圖標(biāo)將變成下面這個樣子。
重啟或新建終端,執(zhí)行腳本。解析:重啟或新建終端是為了讀取到剛修改的終端配置文件,讓Linux的全局命令搜索路徑生效。遍歷到我們所開發(fā)的腳本。
腳本常用功能 設(shè)置不同顏色的console.log介紹:不同顏色的log除了美觀,還可以起到警示的作用。
基本用法:
// 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!")); // 在控制臺輸出紅色的文案獲取終端所在目錄路徑
介紹:如題所示,獲取終端當(dāng)前所在目錄,而不是腳本所在路徑
基本用法:let basePath = process.cwd(); // 其中process是node全局變量,提供當(dāng)前 Node 進(jìn)程的信息
攜帶參數(shù)運(yùn)行腳本介紹:平時我們使用linux命令都會伴隨一些參數(shù),那么在node中怎么實(shí)現(xiàn),怎么獲取運(yùn)行時攜帶的參數(shù)呢?通過process.argv即可,它將返回一個數(shù)組,由命令行執(zhí)行腳本時的各個參數(shù)組成。它的第一個成員總是node,第二個成員是腳本文件名,其余成員是腳本文件的參數(shù)。
基本用法:
let elem1 = process.argv[2]; // 攜帶的參數(shù)一 let elem2 = process.argv[3]; // 攜帶的參數(shù)二調(diào)用linux命令
介紹:有時候我們需要的功能并不是僅靠node就能實(shí)現(xiàn)的,還需要linux命令做支持。那怎么通過node調(diào)用Linux命令呢?
基本用法:
const child_process = require("child_process"); // child_process是node負(fù)責(zé)子進(jìn)程的模塊 child_process.exec("ls -a", function (error, stdout, stderr) { // 通過child_process下的exec函數(shù)執(zhí)行l(wèi)inux命令 error && console.log("error " + error); // 執(zhí)行出錯時的錯誤信息 console.log("Child Process STDOUT: " + stdout); // stdout是執(zhí)行l(wèi)inux命令后的執(zhí)行 結(jié)果。在這里即返回執(zhí)行l(wèi)s -a命令遍歷到的文件信息 });打開頁面
介紹:怎么通過Node用瀏覽器打開特定頁面呢?mac自帶了open命令,我們通過node調(diào)用open命令打開頁面即可。
基本用法:
require("child_process").exec(`open http://baidu.com`); // 打開百度
// 這是網(wǎng)上找到的,兼容各運(yùn)行環(huán)境的打開頁面方法 let cmd = ""; // 運(yùn)行的指令 if (process.platform == "wind32") { cmd = "start "%ProgramFiles%Internet Exploreriexplore.exe""; } else if (process.platform == "linux") { cmd = "xdg-open"; } else if (process.platform == "darwin") { cmd = "open"; } require("child_process").exec(`${cmd} http://baidu.com`);攜帶上下文執(zhí)行l(wèi)inux命令
介紹:上面介紹到的調(diào)用linux方法,本質(zhì)上只是直接去調(diào)用具體的Linux命令。如調(diào)用ls,相當(dāng)于直接找到系統(tǒng)里面ls這個腳本,執(zhí)行它。
這和我們平常在終端里面執(zhí)行有什么區(qū)別呢?
在終端里面,我們調(diào)用命令是攜帶上下文的。即第二條命令會在執(zhí)行完第一條命令之后的環(huán)境下執(zhí)行,例如
cd / ls
這兩條命令是先切換到根路徑,再打印跟路徑下的文件信息。
如果像上面一樣,通過
require("child_process").exec(`cd /`); require("child_process").exec(`ls`);
則只是執(zhí)行了兩個相互獨(dú)立的命令,一個是切換目錄,一個是打印文件信息。ls打印的不是切換目錄后的文件信息,而是運(yùn)行腳本時所在的文件信息。
那怎么攜帶上下文執(zhí)行l(wèi)inux命令呢?
基本用法:
// 注意,這里使用到了colors模塊,用于顯示不同顏色的輸出。不需要的話,也可以直接console.log()打印。 const subProcess = require("child_process").spawn("bash"); // 使用子程序去運(yùn)行某個軟件,在這里就是運(yùn)行bash軟件。相當(dāng)于運(yùn)行一個終端 subProcess.stdout.on("data", function(data) { console.log(colors.green(data)); }); // 監(jiān)聽命令執(zhí)行后,bash返回的信息 subProcess.on("error", function() { console.log(colors.red("error " + arguments)); }); // 消息的錯誤監(jiān)聽 subProcess.on("close", (code) => { // 關(guān)閉bash進(jìn)程后觸發(fā)的事件 if (code === 0) { console.log(colors.blue(`執(zhí)行成功!`)); } else { console.log(colors.blue(`執(zhí)行失敗,錯誤碼為:${code}`)); } }); // 監(jiān)聽進(jìn)程退出 //向子進(jìn)程發(fā)送命令 subProcess.stdin.write(`cd / `); // 切換目錄, 表示回車,執(zhí)行cd命令 subProcess.stdin.write(`ls -a `); // 寫入數(shù)據(jù) subProcess.stdin.end(); // 結(jié)束進(jìn)程,相當(dāng)于關(guān)閉終端將某數(shù)據(jù)復(fù)制到剪切板
介紹:這是一個很常用的功能
基本用法:
const copyProcess = require("child_process").spawn("bash"); // 用于復(fù)制密碼的進(jìn)程 copyProcess.stdin.write(`echo ${Config.server.password} | pbcopy`); // 將特定文本拷貝到剪切板中 copyProcess.stdin.end(); // 結(jié)束進(jìn)程常用腳本
上面介紹了一些基本的node功能,雖然看似很簡答。但如果善于運(yùn)用,也可以做出一些提高效率的小工具。
mhelp,一鍵查看自定義文檔功能介紹:自定義常用文檔,方便地查看。例如markdown語法,常用全局匹配的正則什么的。省的重復(fù)打開筆記。
基本思路:「colors顏色控制」+「攜帶參數(shù)運(yùn)行腳本」
示例代碼:
#!/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", } }; // 自定義幫助文檔 // 設(shè)置文檔name為他本身 let allHelpName = ""; let match = false; // 是否找到匹配項(xiàng) for (let helpItem in helpInfo) { allHelpName += helpItem + ` `; if (helpItem === helpName) { match = true; for (let detailItem in helpInfo[helpItem]) { console.log(colors.green(detailItem + " : " + helpInfo[helpItem][detailItem])); // 找不到頁面相關(guān)信息 } return; } } if (!match) { console.log(colors.red("can not find matched helpInfo! the all helpName is")); // 找不到頁面相關(guān)信息 console.log(colors.red(allHelpName)); // 找不到頁面相關(guān)信息 }mop,一鍵打開常用頁面并復(fù)制密碼到剪切板
功能介紹:簡單,一個命令打開特定頁面,而且?guī)湍惆烟囟ㄎ陌笍?fù)制到剪切板。例如?登陸密碼。
基本思路:「復(fù)制剪切板」+「打開頁面」+「colors顏色控制」
示例代碼:
#!/usr/bin/env node "use strict"; const proess = require("child_process"); const copyProcess = proess.spawn("bash"); // 用于復(fù)制密碼的進(jìn)程,為了避免同一個進(jìn)程拷貝和上傳時的沖突 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]; // 是否只顯示數(shù)據(jù),不打開頁面 let dataItem = dataInfo[dataName]; // 遍歷成功后獲取的頁面對象 // 輸入腳本簡介 if (process.argv[2] === "-h") { console.log(colors.green(introduce)); copyProcess.stdin.end(); return; } // 檢測數(shù)據(jù)有效性 if (!dataName) { // 參數(shù)為空 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}】 `; } console.log(colors.red("can not find matched dataInfo! the all dataName is")); // 找不到頁面相關(guān)信息 console.log(colors.red(allDataName)); // 找不到頁面相關(guān)信息 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`); // 寫入數(shù)據(jù) copyProcess.stdin.end(); !onlyShow && dataItem.url && require("child_process").exec(`open ${dataItem.url}`); // 打開特定頁面mgulp,一鍵gulp打包項(xiàng)目,一鍵動態(tài)刷新
功能介紹:解決了每個項(xiàng)目都需要配置gulp及其依賴的麻煩。功能就如標(biāo)題所說,一鍵gulp打包項(xiàng)目,一鍵動態(tài)刷新(需結(jié)合livereload工具)
基本思路:「攜帶參數(shù)運(yùn)行腳本」+「攜帶上下文執(zhí)行l(wèi)inux命令」
示例代碼:(這里還需結(jié)合gulpfile.js文件一起使用,詳情請查看筆者github上的文件結(jié)構(gòu))
#!/usr/bin/env node "use strict"; const Process = require("child_process").spawn("bash"); // 使用子程序去運(yùn)行某個軟件。在這里就是運(yùn)行bash軟件。并獲取其上下文。 const colors = require("colors"); // 命令行顏色black,red,green,yellow,blue,magenta,cyan,white,gray,grey const Config = require("../config"); // 服務(wù)器信息 const introduce = Config.shellInfo["mgulp"].introduce; // 腳本介紹,用在momoShell中介紹 const elem = process.argv; // 輸入的參數(shù) const basePath = process.cwd(); const action = elem[2]; // 文件名 // 消息監(jiān)聽,監(jiān)聽子進(jìn)程的輸出。并在主進(jìn)程中打印出來。 function onData(data) { console.log(colors.green(data)); } // 設(shè)置消息監(jiān)聽 Process.stdout.on("data", onData); Process.on("error", function() { console.log(colors.red("error " + arguments)); }); Process.on("close", (code) => { if (code === 0) { console.log(colors.blue(`執(zhí)行成功!`)); } else { console.log(colors.blue(`執(zhí)行成功失敗,錯誤碼為:${code}`)); } }); // 監(jiān)聽進(jìn)程退出 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 `); // 切換pwd Process.stdin.write(`gulp default --${inputPath} --${outputPath} `); // 執(zhí)行g(shù)ulp,通過「--」來讓gulp不解析為gulp任務(wù) Process.stdin.end(); } else if (action === "-watch") { // 輸入腳本簡介 let watchList = elem[3]; if (!watchList) { // 檢測數(shù)據(jù)有效性 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) { // 監(jiān)聽所有文件,及旗下文件夾內(nèi)的文件 item = item + "/*.*," + item + "/*/*.*"; } return item; }); Process.stdin.write("cd /Users/Momo/Desktop/intruction/Node/shell "); // 切換pwd Process.stdin.write("gulp reload --${watchList.join(",")} "); // 執(zhí)行g(shù)ulp Process.stdin.end(); } } else { // 輸入腳本簡介 console.log(colors.red("please input action")); Process.stdin.end(); }mupload,一鍵上傳文件或文件夾到服務(wù)器
功能介紹:如題,可上傳整個文件夾,不需要打開ftp軟件這么麻煩(注意scp命令不支持強(qiáng)制覆蓋文件夾功能)
基本思路:「復(fù)制剪切板」+「調(diào)用linux命令」+ 「scp命令」
示例代碼:
#!/usr/bin/env node "use strict"; const colors = require("colors"); // 命令行顏色black,red,green,yellow,blue,magenta,cyan,white,gray,grey const Config = require("../config"); // 服務(wù)器信息 const copyProcess = require("child_process").spawn("bash"); // 用于復(fù)制密碼的進(jìn)程,為了避免同一個進(jìn)程拷貝和上傳時的沖突 const subProcess = require("child_process").spawn("bash"); // 使用子程序去運(yùn)行某個軟件。在這里就是運(yùn)行bash軟件。并獲取其上下文。 const introduce = Config.shellInfo["mupload"].introduce; // 腳本介紹,用在momoShell中介紹 let elem = process.argv; // 輸入的參數(shù) let basePath = process.cwd(); let filePath = basePath + "/" + elem[2]; // 文件名 let targetPath = elem[3]; // 目標(biāo)路徑 // 將服務(wù)器密碼拷貝到剪切板中 copyProcess.stdin.write(`echo ${Config.server.password} | pbcopy`); // 寫入數(shù)據(jù) copyProcess.stdin.end(); // 輸入腳本簡介 if (process.argv[2] === "-h") { console.log(colors.green(introduce)); copyProcess.stdin.end(); subProcess.stdin.end(); return; } // 檢測數(shù)據(jù)有效性 if (!filePath || !targetPath) { console.log(colors.red("filePath or targetPath can not be empty!")); subProcess.stdin.end(); return; } // 兼容目標(biāo)路徑 if (targetPath[targetPath.length - 1] === "/") { if (elem[2].indexOf("/") !== -1) { targetPath += elem[2].substr(elem[2].indexOf("/") + 1); } else { targetPath += elem[2]; } } // 消息監(jiān)聽,監(jiān)聽子進(jìn)程的輸出。并在主進(jìn)程中打印出來。 function onData(data) { console.log(colors.green(data)); } //設(shè)置消息監(jiān)聽 subProcess.stdout.on("data", onData); subProcess.on("error", function() { console.log(colors.red("error " + arguments)); }); subProcess.on("close", (code) => { if (code === 0) { console.log(colors.blue(`上傳成功!`)); console.log(colors.red(`注意,上傳文件夾并不會覆蓋原文件,請登錄服務(wù)器查看文件是否替換成功`)); } else { console.log(colors.blue(`上傳失敗,錯誤碼為:${code}`)); } }); // 監(jiān)聽進(jìn)程退出 //向子進(jìn)程發(fā)送命令 subProcess.stdin.write(`scp -C -r -p ${filePath} root@${Config.server.ip}:${targetPath} `); // 寫入數(shù)據(jù) subProcess.stdin.end();還有其他的,像什么「一鍵git」「一鍵svn」,這些就根據(jù)實(shí)際需要組合開發(fā)啦。 問題求助
筆者在開發(fā)腳本時,遇到兩個問題,有興趣的大神可以指點(diǎn)指點(diǎn)
復(fù)制剪切板和scp的沖突這是「一鍵上傳文件或文件夾到服務(wù)器」遇到的問題,復(fù)制剪切板和scp命令會沖突,如果放在同一個bash進(jìn)程執(zhí)行會失敗,沒找到原因。
linux應(yīng)答式異步交互,實(shí)現(xiàn)ssh的一鍵登錄。這個功能我用linux的shell腳本實(shí)現(xiàn)過。但是放在node沒能找到實(shí)現(xiàn)思路,
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/92619.html
摘要:深入淺出一直想致力于寫一篇關(guān)于廣義講解系統(tǒng)的文章,苦于時間有限,資源有限。事件驅(qū)動機(jī)制是通過內(nèi)部單線程高效率地維護(hù)事件循環(huán)隊列來實(shí)現(xiàn)的,沒有多線程的資源占用和上下文的切換。 深入淺出Node.js 一直想致力于寫一篇關(guān)于廣義講解Node.js系統(tǒng)的文章,苦于時間有限,資源有限。這篇文章是在結(jié)合自己的學(xué)習(xí)心得以及與行業(yè)大佬共同探討下爭對于熟練掌握J(rèn)S語言后的廣義Node.js.至于為什么...
摘要:深入淺出一直想致力于寫一篇關(guān)于廣義講解系統(tǒng)的文章,苦于時間有限,資源有限。事件驅(qū)動機(jī)制是通過內(nèi)部單線程高效率地維護(hù)事件循環(huán)隊列來實(shí)現(xiàn)的,沒有多線程的資源占用和上下文的切換。 深入淺出Node.js 一直想致力于寫一篇關(guān)于廣義講解Node.js系統(tǒng)的文章,苦于時間有限,資源有限。這篇文章是在結(jié)合自己的學(xué)習(xí)心得以及與行業(yè)大佬共同探討下爭對于熟練掌握J(rèn)S語言后的廣義Node.js.至于為什么...
摘要:深入淺出一直想致力于寫一篇關(guān)于廣義講解系統(tǒng)的文章,苦于時間有限,資源有限。事件驅(qū)動機(jī)制是通過內(nèi)部單線程高效率地維護(hù)事件循環(huán)隊列來實(shí)現(xiàn)的,沒有多線程的資源占用和上下文的切換。 深入淺出Node.js 一直想致力于寫一篇關(guān)于廣義講解Node.js系統(tǒng)的文章,苦于時間有限,資源有限。這篇文章是在結(jié)合自己的學(xué)習(xí)心得以及與行業(yè)大佬共同探討下爭對于熟練掌握J(rèn)S語言后的廣義Node.js.至于為什么...
摘要:基礎(chǔ)篇整合最近有朋友也想學(xué)習(xí)相關(guān)方面的知識,如果你是后端想接近前端,作為一門跑在服務(wù)端的語言從這里入門再好不過了。事件驅(qū)動機(jī)制是通過內(nèi)部單線程高效率地維護(hù)事件循環(huán)隊列來實(shí)現(xiàn)的,沒有多線程的資源占用和上下文的切換。 nodeJs 基礎(chǔ)篇整合 最近有朋友也想學(xué)習(xí)nodeJs相關(guān)方面的知識,如果你是后端想接近前端,node作為一門跑在服務(wù)端的JS語言從這里入門再好不過了。如果你正好喜歡前端,...
閱讀 691·2021-11-23 09:51
閱讀 3281·2019-08-30 15:54
閱讀 445·2019-08-30 15:52
閱讀 3117·2019-08-30 13:58
閱讀 2920·2019-08-30 13:53
閱讀 2689·2019-08-29 14:18
閱讀 2420·2019-08-27 10:54
閱讀 2371·2019-08-26 18:09