NodeJS感知和控制自身進程的運行環(huán)境和狀態(tài)
NodeJS可以感知和控制自身進程的運行環(huán)境和狀態(tài),也可以創(chuàng)建子進程并與其協(xié)同工作,這使得NodeJS可以把多個程序組合在一起共同完成某項工作,并在其中充當膠水和調(diào)度器的作用。和進程管理相關(guān)的API單獨介紹起來比較枯燥,因此這里從一些典型的應用場景出發(fā),分別介紹一些重要API的使用方法。
如何獲取命令行參數(shù)
在NodeJS中可以通過process.argv
獲取命令行參數(shù)。但是比較意外的是,node
執(zhí)行程序路徑和主模塊文件路徑固定占據(jù)了argv[0]
和argv[1]
兩個位置,而第一個命令行參數(shù)從argv[2]
開始。為了讓argv
使用起來更加自然,可以按照以下方式處理。
function main(argv) { // ... } main(process.argv.slice(2));
如何退出程序
通常一個程序做完所有事情后就正常退出了,這時程序的退出狀態(tài)碼為0
?;蛘咭粋€程序運行時發(fā)生了異常后就掛了,這時程序的退出狀態(tài)碼不等于0
。如果我們在代碼中捕獲了某個異常,但是覺得程序不應該繼續(xù)運行下去,需要立即退出,并且需要把退出狀態(tài)碼設置為指定數(shù)字,比如1
,就可以按照以下方式:
try { // ... } catch (err) { // ... process.exit(1); }
如何控制輸入輸出
NodeJS程序的標準輸入流(stdin)、一個標準輸出流(stdout)、一個標準錯誤流(stderr)分別對應process.stdin
、process.stdout
和process.stderr
,第一個是只讀數(shù)據(jù)流,后邊兩個是只寫數(shù)據(jù)流,對它們的操作按照對數(shù)據(jù)流的操作方式即可。例如,console.log
可以按照以下方式實現(xiàn)。
function log() { process.stdout.write( util.format.apply(util, arguments) + '\n'); }
如何降權(quán)
在Linux系統(tǒng)下,我們知道需要使用root權(quán)限才能監(jiān)聽1024以下端口。但是一旦完成端口監(jiān)聽后,繼續(xù)讓程序運行在root權(quán)限下存在安全隱患,因此最好能把權(quán)限降下來。以下是這樣一個例子。
http.createServer(callback).listen(80, function () { var env = process.env, uid = parseInt(env['SUDO_UID'] || process.getuid(), 10), gid = parseInt(env['SUDO_GID'] || process.getgid(), 10); process.setgid(gid); process.setuid(uid); });
上例中有幾點需要注意:
如果是通過
sudo
獲取root權(quán)限的,運行程序的用戶的UID和GID保存在環(huán)境變量SUDO_UID
和SUDO_GID
里邊。如果是通過chmod +s
方式獲取root權(quán)限的,運行程序的用戶的UID和GID可直接通過process.getuid
和process.getgid
方法獲取。process.setuid
和process.setgid
方法只接受number
類型的參數(shù)。降權(quán)時必須先降GID再降UID,否則順序反過來的話就沒權(quán)限更改程序的GID了。
如何創(chuàng)建子進程
以下是一個創(chuàng)建NodeJS子進程的例子。
var child = child_process.spawn('node', [ 'xxx.js' ]); child.stdout.on('data', function (data) { console.log('stdout: ' + data); }); child.stderr.on('data', function (data) { console.log('stderr: ' + data); }); child.on('close', function (code) { console.log('child process exited with code ' + code); });
上例中使用了.spawn(exec, args, options)
方法,該方法支持三個參數(shù)。第一個參數(shù)是執(zhí)行文件路徑,可以是執(zhí)行文件的相對或絕對路徑,也可以是根據(jù)PATH環(huán)境變量能找到的執(zhí)行文件名。第二個參數(shù)中,數(shù)組中的每個成員都按順序?qū)粋€命令行參數(shù)。第三個參數(shù)可選,用于配置子進程的執(zhí)行環(huán)境與行為。
另外,上例中雖然通過子進程對象的.stdout
和.stderr
訪問子進程的輸出,但通過options.stdio
字段的不同配置,可以將子進程的輸入輸出重定向到任何數(shù)據(jù)流上,或者讓子進程共享父進程的標準輸入輸出流,或者直接忽略子進程的輸入輸出。
進程間如何通訊
在Linux系統(tǒng)下,進程之間可以通過信號互相通信。以下是一個例子。
/* parent.js */ var child = child_process.spawn('node', [ 'child.js' ]); child.kill('SIGTERM'); /* child.js */ process.on('SIGTERM', function () { cleanUp(); process.exit(0); });
在上例中,父進程通過.kill
方法向子進程發(fā)送SIGTERM
信號,子進程監(jiān)聽process
對象的SIGTERM
事件響應信號。不要被.kill
方法的名稱迷惑了,該方法本質(zhì)上是用來給進程發(fā)送信號的,進程收到信號后具體要做啥,完全取決于信號的種類和進程自身的代碼。
另外,如果父子進程都是NodeJS進程,就可以通過IPC(進程間通訊)雙向傳遞數(shù)據(jù)。以下是一個例子。
/* parent.js */ var child = child_process.spawn('node', [ 'child.js' ], { stdio: [ 0, 1, 2, 'ipc' ] }); child.on('message', function (msg) { console.log(msg); }); child.send({ hello: 'hello' }); /* child.js */ process.on('message', function (msg) { msg.hello = msg.hello.toUpperCase(); process.send(msg); });
可以看到,父進程在創(chuàng)建子進程時,在options.stdio
字段中通過ipc
開啟了一條IPC通道,之后就可以監(jiān)聽子進程對象的message
事件接收來自子進程的消息,并通過.send
方法給子進程發(fā)送消息。在子進程這邊,可以在process
對象上監(jiān)聽message
事件接收來自父進程的消息,并通過.send
方法向父進程發(fā)送消息。數(shù)據(jù)在傳遞過程中,會先在發(fā)送端使用JSON.stringify
方法序列化,再在接收端使用JSON.parse
方法反序列化。
如何守護子進程
守護進程一般用于監(jiān)控工作進程的運行狀態(tài),在工作進程不正常退出時重啟工作進程,保障工作進程不間斷運行。以下是一種實現(xiàn)方式。
/* daemon.js */ function spawn(mainModule) { var worker = child_process.spawn('node', [ mainModule ]); worker.on('exit', function (code) { if (code !== 0) { spawn(mainModule); } }); } spawn('worker.js');
可以看到,工作進程非正常退出時,守護進程立即重啟工作進程。
到此這篇關(guān)于NodeJS感知和控制自身進程的運行環(huán)境和狀態(tài)的文章就介紹到這了,更多相關(guān)NodeJS感知和控制自身進程內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Node.js 構(gòu)建命令行工具之實現(xiàn) ls 命令的 -a 和 
本文介紹了如何使用Node.js實現(xiàn)一個簡單的命令行工具,模仿常用的ls命令,包括其-a和-l參數(shù)的功能,文章詳細講解了命令行參數(shù)的解析、文件類型的判斷、權(quán)限信息的處理、文件鏈接數(shù)和修改時間的格式化等步驟,并提供了完整的代碼實現(xiàn)2024-11-11node-gyp安裝vuetify編譯失敗gyp?ERR的問題及解決
這篇文章主要介紹了node-gyp安裝vuetify編譯失敗gyp?ERR的問題及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-03-03