您好,登錄后才能下訂單哦!
這篇文章主要介紹了如何主動終止Node.js進程,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
1、能夠嵌入動態文本于HTML頁面。2、對瀏覽器事件做出響應。3、讀寫HTML元素。4、在數據被提交到服務器之前驗證數據。5、檢測訪客的瀏覽器信息。6、控制cookies,包括創建和修改等。7、基于Node.js技術進行服務器端編程。
有幾個原因會導致 Node.js 進程終止。其中一些是可以避免的,例如拋出錯誤時,而另一些是無法防止的,例如內存不足。全局 process
是一個 Event Emitter 實例,當執行正常退出時,將發出一個 exit
事件。然后程序代碼可以通過偵聽這個事件來執行最后的同步清理工作。
下面是可以主動觸發進程終止的一些方法:
操作 | 例子 |
---|---|
手動流程退出 | process.exit(1) |
未捕獲的異常 | throw new Error() |
未兌現的 promise | Promise.reject() |
忽略的錯誤事件 | EventEmitter#emit('error') |
未處理的信號 | $ kill <PROCESS_ID> |
其中有許多是屬于偶然被觸發的,例如未捕獲的錯誤或未處理的 promise,但是其中也有為了直接使進程終止而創建的。
使用 process.exit(code)
來終止進程是最直接的方法。這在當你知道自己的過程已經到了生命周期的盡頭時非常有用。 code
值是可選的,默認值為0,最大可以設為 255。0 表示進程運行成功,而任何非零的數字都表示發生了問題。這些值可以被許多不同的外部工具使用。例如當測試套件運行時,非零值表示測試失敗。
直接調用 process.exit()
時,不會向控制臺寫入任何隱式文本。如果你編寫了以錯誤表示形式調用此方法的代碼,則你的代碼應該用戶輸出錯誤來幫助他們解決問題。例如運行以下代碼:
$ node -e "process.exit(42)" $ echo $?
在這種情況下,單行的 Node.js 程序不會輸出任何信息,盡管 shell 程序確實會打印退出狀態。遇到這樣的進程退出,用戶將無法理解究竟發生了什么事情。所以要參考下面這段程序配置錯誤時會執行的代碼:
function checkConfig(config) { if (!config.host) { console.error("Configuration is missing 'host' parameter!"); process.exit(1); } }
在這種情況下,用戶沒會很清楚發生了什么。他們運行這個程序,將錯誤輸出到控制臺上,并且他們能夠糾正這個問題。
process.exit()
方法非常強大。盡管它在程序代碼中有自己的用途,但實際上絕對不應該將其引入可重用的庫中。如果在庫中確實發生了錯誤,則應拋出這個錯誤,以便程序可以決定應該如何處理它。
雖然 process.exit()
很有用,但對于運行時錯誤,你需要使用其他工具。例如當程序正在處理 HTTP 請求時,一般來說錯誤不應該終止進程,而是僅返回錯誤響應。發生錯誤的位置信息也很有用,這正是應該拋出 Error
對象的地方。
Error
類的實例包含對導致錯誤的原因有用的元數據,例如棧跟蹤信息和消息字符串。從 Error
擴展你自己的錯誤類是很常見的操作。單獨實例化 Error
不會有太多副作用,如果發生錯誤則必須拋出。
在使用 throw
關鍵字或發生某些邏輯錯誤時,將引發 Error
。發生這種情況時,當前棧將會“展開”,這意味著每個函數都會退出,直到一個調用函數將調用包裝在 try/catch
語句中為止。遇到此語句后,將調用 catch
分支。如果錯誤沒有被包含在 try/catch
中,則該錯誤被視為未捕獲。
雖然你應該使用帶有 Error
的 throw
關鍵字,例如 throw new Error('foo')
,但從技術上講,你可以拋出任何東西。一旦拋出了什么東西,它就被認為是一個例外。拋出 Error
實例非常重要,因為捕獲這些錯誤的代碼很可能會期望得到錯誤屬性。
Node.js 內部庫中常用的另一種模式是提供一個 .code
屬性,該屬性是一個字符串值,在發行版之間應保持一致。比如錯誤的 .code
值是 ERR_INVALID_URI
,即使是供人類可讀的 .message
屬性可能會更改,但這個 code
值也不應被更改。
可悲的是,一種更常用的區分錯誤的模式是檢查 .message
屬性,這個屬性通常是動態的,因為可能回需要修改拼寫錯誤。這種方法是很冒險的,也是容易出錯的。 Node.js 生態中沒有完美的解決方案來區分所有庫中的錯誤。
當引發未捕獲的錯誤時,控制臺中將打印棧跟蹤信息,并且進程將回以退出狀態 1 終止。這是此類異常的例子:
/tmp/foo.js:1 throw new TypeError('invalid foo'); ^ Error: invalid foo at Object.<anonymous> (/tmp/foo.js:2:11) ... TRUNCATED ... at internal/main/run_main_module.js:17:47
上面的棧跟蹤片段表明錯誤發生在名為 foo.js
的文件的第 2 行第 11 列。
全局的 process
是一個事件發射器,可以通過偵聽 uncaughtException
事件來攔截未捕獲的錯誤。下面是一個使用它的例子,在退出前攔截錯誤以發送異步消息:
const logger = require('./lib/logger.js'); process.on('uncaughtException', (error) => { logger.send("An uncaught exception has occured", error, () => { console.error(error); process.exit(1); }); });
Promise 拒絕與拋出錯誤非常相似。如果 Promise 中的 reject()
方法被調用,或者在異步函數中引發了錯誤,則 Promise 可以拒絕。在這方面,以下兩個例子大致相同:
Promise.reject(new Error('oh no')); (async () => { throw new Error('oh no'); })();
這是輸出到控制臺的消息:
(node:52298) UnhandledPromiseRejectionWarning: Error: oh no at Object.<anonymous> (/tmp/reject.js:1:16) ... TRUNCATED ... at internal/main/run_main_module.js:17:47 (node:52298) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch().
與未捕獲的異常不同,從 Node.js v14 開始,這些 rejection 不會使進程崩潰。在未來的 Node.js 版本中,會使當前進程崩潰。當這些未處理的 rejection 發生時,你還可以攔截事件,偵聽 process
對象上的另一個事件:
process.on('unhandledRejection', (reason, promise) => {});
事件發射器是 Node.js 中的常見模式,許多對象實例都從這個基類擴展而來,并在庫和程序中使用。它們非常歡迎,值得和 error 與 rejection 放在一起討論。
當事件發射器發出沒有偵聽器的 error
事件時,將會拋出所發出的參數。然后將拋出出一個錯誤并導致進程退出:
events.js:306 throw err; // Unhandled 'error' event ^ Error [ERR_UNHANDLED_ERROR]: Unhandled error. (undefined) at EventEmitter.emit (events.js:304:17) at Object.<anonymous> (/tmp/foo.js:1:40) ... TRUNCATED ... at internal/main/run_main_module.js:17:47 { code: 'ERR_UNHANDLED_ERROR', context: undefined }
確保在你使用的事件發射器實例中偵聽 error
事件,以便你的程序可以正常處理事件而不會崩潰。
信號是操作系統提供的機制,用于把用數字表示的消息從一個程序發送到另一個程序。這些數字通常用等價的常量字符串來表示。例如,信號 SIGKILL
代表數字信號 9。信號可以有不同的用途,但通常用于終止程序。
不同的操作系統可以定義不同的信號,但是下面列表中的信號一般是通用的:
名稱 | 編號 | 可處理 | Node.js 默認 | 信號用途 |
---|---|---|---|---|
SIGHUP | 1 | 是 | 終止 | 父終端已關閉 |
SIGINT | 2 | 是 | 終止 | 終端試圖中斷,按下 Ctrl + C |
SIGQUIT | 3 | 是 | 終止 | 終端試圖退出,按下 Ctrl + D |
SIGKILL | 9 | 否 | 終止 | 進程被強行殺死 |
SIGUSR1 | 10 | 是 | 啟動調試器 | 用戶定義的信號1 |
SIGUSR2 | 12 | 是 | 終止 | 用戶定義的信號2 |
SIGTERM | 12 | 是 | 終止 | 代表優雅的終止 |
SIGSTOP | 19 | 否 | 終止 | 進程被強行停止 |
如果程序可以選擇實現信號處理程序,則 Handleable 一列則為是。為否的兩個信號無法處理。 Node.js 默認 這一列告訴你在收到信號時,Node.js 程序的默認操作是什么。最后一個信號用途指出了信號對應的作用。
在 Node.js 程序中處理這些信號可以通過偵聽 process
對象上的更多事件來完成:
#!/usr/bin/env node console.log(`Process ID: ${process.pid}`); process.on('SIGHUP', () => console.log('Received: SIGHUP')); process.on('SIGINT', () => console.log('Received: SIGINT')); setTimeout(() => {}, 5 * 60 * 1000); // keep process alive
在終端窗口中運行這個程序,然后按 Ctrl + C
,這個進程不會被終止。它將會聲明已接收到 SIGINT
信號。切換到另一個終端窗口,并根據輸出的進程 ID 值執行以下命令:
$ kill -s SIGHUP <PROCESS_ID>
這演示了一個程序怎樣向另一個程序發送信號,并且在第一個終端中運行的 Node.js 程序中輸出它所接收到的 SIGHUP
信號。
你可能已經猜到了,Node.js 也能把命令發送到其他程序。可以用下面的命令以把信號從臨時的 Node.js 進程發送到你現有的進程:
$ node -e "process.kill(<PROCESS_ID>, 'SIGHUP')"
這還會在你的第一個程序中顯示 SIGHUP
消息。現在,如果你想終止第一個進程,要運行下面的命令向其發送不能處理的 SIGKILL
信號:
$ kill -9 <PROCESS_ID>
這時程序應該結束。
這些信號在 Node.js 程序中經常用于處理正常的關閉事件。例如,當 Kubernetes Pod 終止時,它將向程序發送 SIGTERM
信號,之后啟動 30 秒計時器。然后程序可以在這 30 秒內正常關閉自己,關閉連接并保存數據。如果該進程在此計時器后仍保持活動狀態,則 Kubernetes 將向其發送一個 SIGKILL
。
感謝你能夠認真閱讀完這篇文章,希望小編分享的“如何主動終止Node.js進程”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,更多相關知識等著你來學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。