本文目錄一覽:
- 1、nodejs 怎樣檢測子進程執行完成
- 2、手把手教你使用nodejs編寫cli(命令行)
- 3、如何在nodejs里調用執行系統命令
- 4、Nodejs child_process 模塊
- 5、怎樣安裝node模塊child
nodejs 怎樣檢測子進程執行完成
nodejs是一種單線程模型,但是,使用nodejs的child_process模塊可以實現多進程任務。利用child_process可以創建子進程,實現子進程和主進程之間的通信。
nodejs v0.12.7版本child_process提供以下同步和異步的方式創建進程:
異步創建:
child_process.spawn(command[, args][, options])
options.stdio
options.detached
options.customFds
child_process.exec(command[, options], callback)
child_process.execFile(file[, args][, options][callback])
child_process.fork(modulePath[, args][, options])
同步創建:
child_process.spawnSync(command[, args][, options])
child_process.execFileSync(command[, args][, options])
child_process.execSync(command[, options])
手把手教你使用nodejs編寫cli(命令行)
前端日常開發中,會遇見各種各樣的cli,比如一行命令幫你打包的webpack,一行命令幫你生成vue項目模板的vue-cli,還有創建react項目的create-react-app等等等等。這些工具極大地方便了我們的日常工作,讓計算機自己去干繁瑣的工作,而我們,就可以節省出大量的時間用於學習、交流、開發、 逛steam 。
但是有時候一些十分特別的需求,我們是找不到適合的cli工具去做的。比如說,你的項目十分龐大,你給項目添加一個新的路由,要經過 創建目錄 – 創建.vue文件 – 更新vue-router的路由列表 這一趟流程,就算快捷鍵創建目錄文件用得再熟悉,也比不過你一行命令來得快,特別是路由目錄嵌套深,.vue文件初始化模板複雜的時候。
所以呢,何不為自己項目寫一個cli?就專門做這些繁瑣的活?
nodejs的cli,本質就是跑node腳本嘛,基本上每位前端er都會:
然後命令行調用
可以做得更逼真一點,我們在package.json裡面的scripts字段上添加一下腳本名:
然後命令行調用:
但是,看到這裡你肯定會說,人家webpack還有vue-cli都是“有名字”的!什麼 vue-cli init app 、 webpack -p 的,多漂亮,看看這個命令行, node index.js ,還 npm run hello ,誰不會啊,丑不拉幾的,怕又不是來水文章的哦?差評!!
別急啊各位大人,接下來就說說,如何給這個node腳本起個名字。
姑且,先把這個cli的名字命名為 hello-cli ,就是我們能夠在命令行裡面,輸入 hello-cli ,然後它就打印一句 hello world ,沒有 node 也沒有 npm ,就是:
這樣,你的第一個cli腳本就成功安裝了,可以在命令行裡面,直接敲你的cli名字,看看結果輸出吧。
另外,如果你僅希望你的cli腳本僅在項目里執行,則需要在你項目裡面新建一個目錄,重複上述的操作,只是在第三步的時候,不要llink到全局裡面去,而是使用 npm i -D file:你的腳本cli目錄路徑 ,把它當成項目的依賴安裝到node_modules裡面去,如果安裝成功,那麼在項目的package.json你會看到多了一條依賴,這條依賴的值不是版本號,而是你腳本的路徑。然後在node_modules裡面會有一個.bin目錄,裡面就存放着你的可執行文件。
當然,這樣安裝的cli腳本,必須在項目的package.json的scripts字段上聲明腳本命令,然後通過 npm run 的方式執行。
哦?這樣子使用的話不就回到最最最開始的時候那種原始的 npm run hello 一樣么。
是的,但是有質的區別。使用 node index.js 這種方式調用的話固然簡單靈活,但是嚴重依賴腳本路徑,一旦目錄結構發生變動,寫在scripts的命令就要更改一次;但是使用npm安裝之後,本地的cli腳本就被拉到node_modules裡面,目錄結構變動對其影響不大。其次是不利於分享與發布,如果你想把你的cli腳本發布出去,那麼有一個好聽響亮的名字,比起在說明文檔裡面告訴使用者如何找到你的腳本路徑再用node執行它,簡直好上那麼一萬倍不是么?
這裡也給我們提供了一個cli開發流程思路:
名字有了,輸出也有了,看看我們跟那些大名鼎鼎的cli工具,在形式上還差點啥?對了,人家可以支持不同參數選項的,還可以根據輸入的不同,產生不同的結果。
這樣吧,我們給這個cli加一個功能,既然叫 hello-cli ,那不能只會 hello world 吧,必須要見誰就說 hello 才行:
雖然這個功能很簡單,但是至少也是實現了“根據輸入的不同,產生不同結果”的效果。
命令行上的參數,可以通過 process 這個變量獲取, process 是一個全局對象而不是一個包,不需要通過 require 引入。通過 process 這個對象我們可以拿到當前腳本執行環境等一系列信息,其中就包括命令行的輸入情況,這個信息,保存在 process.argv 這個屬性里。我們可以打印一下:
打印結果:
可以看出,argv是個數組,前兩位是固定的,分別是node程序的路徑和腳本存放的位置,從第三位開始才是額外輸入的內容。那麼實現上面的功能就很簡單了,只要讀取argv數組的第三位,然後輸出出來就可以了。
npm社區中也有一些優秀的命令行參數解析包,比如 yargs ,tj的 commander.js 等等
如果你想使用比較複雜的參數或者命令,建議還是用第三方包比較好,手寫解析太耗精力了。
現在,你可以自由自在的寫你自己的cli腳本了。
如果你希望寫一個項目打完包自動推上git的cli,或者自動從git倉庫裡面拉取項目啟動模板,那麼,你需要通過node的 child_process 模塊開啟子進程,在子進程內調用git命令:
不僅是git命令,包括系統命令、其他cli命令都可以在這裡執行。特別是系統命令,使用系統命令對文件目錄進行操作,效率比fs高到不知道哪裡去了。
社區上也有一些不錯的包,比如阮一峰老師推薦的 shelljs
如果你不那麼希望你的cli用起來那麼“硬核”,希望更人性化一點,比如提供一些友好的輸入、提示啊,給你的輸出加點顏色區分重點啊,寫個簡單的進度條啊等等,那麼你就需要美化一下你的輸出了。
除了顏色這部分,不使用第三方包實現起來非常繁瑣複雜,其他的功能,都可以試試自己寫。
顏色部分使用了第三方包 colors ,這裡就不演示了。
其他都是由nodejs自帶的 readline 模塊實現的。
繪製的思路跟canvas繪製動畫一樣,只不過canvas是清除畫布,而命令行這裡是通過 readline.clearScreenDown 清除輸出。
這樣,一個簡易的,人性化的,帶點點進度條動畫的命令行cli工具就寫好了,你也可以發揮你的想象力,去寫一些更有趣的效果出來。
畢竟我們前端,有瀏覽器我們可以寫動畫,沒了瀏覽器我們一樣可以寫動畫。
如何在nodejs里調用執行系統命令
這篇文章主要介紹了Nodejs中調用系統命令、Shell腳本和Python腳本的方法和實例,本文給出了利用子進程調用系統命令、執行系統命令、調用傳參數的shell腳本、調用python腳本的例子,需要的朋友可以參考下
每種語言都有自己的優勢,互相結合起來各取所長程序執行起來效率更高或者說哪種實現方式較簡單就用哪個,nodejs是利用子進程來調用系統命令或者文件,文檔見,NodeJS子進程提供了與系統交互的重要接口,其主要API有: 標準輸入、標準輸出及標準錯誤輸出的接口。
NodeJS 子進程提供了與系統交互的重要接口,其主要 API 有:
標準輸入、標準輸出及標準錯誤輸出的接口
child.stdin 獲取標準輸入
child.stdout 獲取標準輸出
child.stderr 獲取標準錯誤輸出
獲取子進程的PID:child.pid
提供生成子進程的方法:child_process.spawn(cmd, args=[], [options])
提供直接執行系統命令的方法:child_process.exec(cmd, [options], callback)
提供調用腳本文件的方法:child_process.execFile(file, [args], [options], [callback])
提供殺死進程的方法:child.kill(signal=’SIGTERM’)
用實例來感受一下,很有意思的,呵呵~~
1、利用子進程調用系統命令(獲取系統內存使用情況)
新建nodejs文件,名為cmd_spawn.js,代碼如下:
複製代碼 代碼如下:
var spawn = require(‘child_process’).spawn;
free = spawn(‘free’, [
Nodejs child_process 模塊
child_process.exec(command[, options][, callback])
開啟一個子進程執行 shell 命令,在回調中獲取輸出信息
在 lib/child_process 源碼中 exec 內部只是處理參數後調用了 execFile 方法。
exec 調用 execFile
child_process.execFile(file[, args][, options][, callback])
execFile 源碼
調用 spawn 創建進程 child
通過 child.stdout.on(‘data’) 收集輸出 stdout
當 child 進程 close 時把 _stdout 傳入 callback 內輸出
同樣當 child 進程 觸發 error 事件會把 _stderr 傳入 callback 中輸出,同時會 destroy 進程 child 的 stdout 和 stderr
execFile 通過 spawn 創建子進程執行命令,是 nodejs 圍繞 spawn 方法的封裝, 調用 spawn 執行命令一次性的把輸出結果和錯誤通過回調輸出。
exec 底層調用了 execFile,不過 exec 通過 option.shell = true 的配置使 spawn 創建的進程通過 /bin/sh -c 執行傳入的 shell 腳本
適合執行開銷小的命令
wiki Spawn (computing)
使用 spawn 創建子進程執行 命令時 options.stdio 比較常用的配置項就是默認的 pipe 和 inherit , ignore 選項將會忽略子進程的輸入輸出
如果使用 inherit 選項,命令的執行內容將會直接在控制台輸出,因為指定了輸出的 fd 的 1 process.stdio 標準輸出流直接會在控制台中輸出。
如果使用 pipe 選項, child.stdout 也可以通過 pipe 輸出流的方式輸出到可寫流中, 比如 fs.createWriteStream 簡單的文件可寫流。
通過執行 index.js 執行 spwan API 設置 detached: true 創建守護進程並解除父進程引用。守護進程將會一直向 stdout.log 中寫入數據。
通過守護進程的例子會發現 stdout.log 寫入的 父進程 ppid 與 index.js 打印出的父進程 pid 不一樣。這裡的 ppid:1 是 init 進程,當父進程退出後通過父進程創建還在執行的子進程將會被 init 進程收養成為 孤兒進程
ChildProcess.prototype.spawn 創建子進程源碼
通過 ChildProcess.prototype.spawn 創建子進程,通過 c++ 的 Pipe 創建不同 pipe 實例的和 Process 創建進程,這裡可以看下 stido 中 pipe 和 ipc 模式創建不同的 Pipe 實例
pipe ipc 創建 Pipe 實例的區別
setupChannel 添加 ipc send() 方法
child_process和IPC探究
【node源碼】child_process源碼閱讀
線程和進程
怎樣安裝node模塊child
默認安裝在 NodeJS 目錄下的: \node_modules\npm 目錄中,想要升級或降級的話(因為隨 NodeJS 一起發布的 npm 不一定是最新版本),請參考: suoling.net/update-npm/ 上面鏈接中介紹的 npm 的升級降級方式比 npm 官方介紹的幾種方法的操作要簡…
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/271931.html