成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Node 腳本遭遇異常時如何安全退出

開發 前端
一個 Node 相關的項目中,總是少不了跑腳本。跑一個腳本拉取配置、處理一些數據以及定時任務更是家常便飯。

一個 Node 相關的項目中,總是少不了跑腳本。跑一個腳本拉取配置、處理一些數據以及定時任務更是家常便飯。

在一些重要流程中能夠看到腳本的身影:

  • CI,用以測試、質量保障及部署等
  • Docker,用以構建鏡像
  • Cron,用以定時任務

如果在這些重要流程中腳本出錯無法及時發現問題,將有可能引發更加隱蔽的問題。

最近觀察項目鏡像構建,會偶爾發現一兩個鏡像雖然構建成功,但容器卻跑不起來的情況。「究其原因,是因為 Exit Code 的問題」。

[[339305]]

Exit Code

什么是 exit code?

exit code 代表一個進程的返回碼,通過系統調用 exit_group 來觸發。在 POSIX 中,0 代表正常的返回碼,1-255 代表異常返回碼,一般主動拋出的錯誤碼都是 1。在 Node 應用中使用 process.exitCode = 1 來代表因不期望的異常而中斷。

這里有一張關于異常碼的附表 Appendix E. Exit Codes With Special Meanings[1]。

異常碼在操作系統中隨處可見,以下是一個關于 cat 命令的異常以及它的 exit code,并使用 strace 追蹤系統調用。

  1. $ cat a 
  2. cat: a: No such file or directory 
  3.  
  4. # 使用 strace 查看 cat 的系統調用 
  5. # -e 只顯示 write 與 exit_group 的系統調用 
  6. $ strace -e write,exit_group cat a 
  7. write(2, "cat: ", 5cat: )                    = 5 
  8. write(2, "a", 1a)                        = 1 
  9. write(2, ": No such file or directory", 27: No such file or directory) = 27 
  10. write(2, "\n", 1 
  11. )                       = 1 
  12. exit_group(1)                           = ? 
  13. +++ exited with 1 +++ 

從系統調用的最后一行可以看出,該進行的 exit code 是 1,并把錯誤信息輸出到 stderr (標準錯誤的 fd 為 2) 中

如何查看 exit code

從 strace 中可以來判斷進程的 exit code,但是不夠方便過于冗余,特別身處 shell 編程環境中。

「有一種簡單的方法,通過 echo $? 來確認返回碼」

  1. $ cat a 
  2. cat: a: No such file or directory 
  3.  
  4. $ echo $? 

throw new Error與Promise.reject區別

以下是兩段代碼,第一段拋出一個異常,第二段 Promise.reject,兩段代碼都會如下打印出一段異常信息,那么兩者有什么區別?

  1. function error () { 
  2.   throw new Error('hello, error') 
  3.  
  4. error() 
  5.  
  6. // Output: 
  7.  
  8. // /Users/shanyue/Documents/note/demo.js:2 
  9. //   throw new Error('hello, world') 
  10. //   ^ 
  11. // 
  12. // Error: hello, world 
  13. //     at error (/Users/shanyue/Documents/note/demo.js:2:9) 
  14. //     at Object.<anonymous> (/Users/shanyue/Documents/note/demo.js:5:1) 
  15. //     at Module._compile (internal/modules/cjs/loader.js:701:30) 
  1. function error () { 
  2.   throw new Error('hello, error') 
  3.  
  4. error() 
  5.  
  6. // Output: 
  7.  
  8. // /Users/shanyue/Documents/note/demo.js:2 
  9. //   throw new Error('hello, world') 
  10. //   ^ 
  11. // 
  12. // Error: hello, world 
  13. //     at error (/Users/shanyue/Documents/note/demo.js:2:9) 
  14. //     at Object.<anonymous> (/Users/shanyue/Documents/note/demo.js:5:1) 
  15. //     at Module._compile (internal/modules/cjs/loader.js:701:30) 

在對上述兩個測試用例使用 echo $? 查看 exit code,我們會發現 throw new Error() 的 exit code 為 1,而 Promise.reject() 的為 0。

「從操作系統的角度來講,exit code 為 0 代表進程成功運行并退出,此時即使有 Promise.reject,操作系統也會視為它執行成功。」

這在 Dockerfile 與 CI 中將留有安全隱患。

Dockerfile 在 node 中的注意點

當使用 Dockerfile 構建鏡像時,如果 RUN 的進程返回非 0 的返回碼,構建就會失敗。

「而在 Node 中的錯誤處理中,我們傾向于所有的異常都交由 async/await 來處理,而當發生異常時,由于此時 exit code 為 0 并不會導致鏡像構建失敗。」

這是一個淺顯易懂的含 Promise.reject() 問題的鏡像。

  1. FROM node:12-alpine 
  2.  
  3. RUN node -e "Promise.reject('hello, world')" 

構建鏡像過程如下:「即使在構建過程打印出了 unhandledPromiseRejection 信息,但是鏡像仍然構建成功。」

  1. $ docker build -t demo . 
  2. Sending build context to Docker daemon  33.28kB 
  3. Step 1/2 : FROM node:12-alpine 
  4.  ---> 18f4bc975732 
  5. Step 2/2 : RUN node -e "Promise.reject('hello, world')" 
  6.  ---> Running in 79a6d53c5aa6 
  7. (node:1) UnhandledPromiseRejectionWarning: hello, world 
  8. (node:1) 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(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1) 
  9. (node:1) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code. 
  10. Removing intermediate container 79a6d53c5aa6 
  11.  ---> 09f07eb993fe 
  12. Successfully built 09f07eb993fe 
  13. Successfully tagged demo:latest 

Promise.reject 腳本解決方案

能在編譯時能發現的問題,絕不要放在運行時。所以,構建鏡像或 CI 中需要執行 node 腳本時,對異常處理需要手動指定 process.exitCode = 1 來提前暴露問題

  1. runScript().catch(() => { 
  2.   process.exitCode = 1 
  3. }) 

在構建鏡像時,也有關于異常解決方案的建議:

(node:1) 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(). To terminate the node process on unhandled promise rejection, use the CLI flag --unhandled-rejections=strict (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)

根據提示,--unhandled-rejections=strict 將會把 Promise.reject 的退出碼設置為 1,并在將來的 node 版本中修正 Promise 異常退出碼。

  1. $ node --unhandled-rejections=strict error.js 

--unhandled-rejections=strict 的配置對 node 有版本要求:

Added in: v12.0.0, v10.17.0

By default all unhandled rejections trigger a warning plus a deprecation warning for the very first unhandled rejection in case no unhandledRejection hook is used.

總結

  • 當進程結束的 exit code 為非 0 時,系統會認為該進程執行失敗
  • 通過 echo $? 可查看終端上一進程的 exit code
  • Node 中 Promise.reject 時 exit code 為 0
  • Node 中可以通過 process.exitCode = 1 顯式設置 exit code
  • 在 Node12+ 中可以通過 node --unhandled-rejections=strict error.js執行腳本,視 Promise.reject 的 exit code 為 1

 

責任編輯:趙寧寧 來源: 全棧成長之路
相關推薦

2013-06-07 09:12:43

OpenDaylighBig SwitchSDN

2015-11-09 14:46:49

Android安全

2011-04-18 09:03:22

2025-02-12 07:08:33

2019-04-28 05:09:04

企業分支安全防御網絡犯罪

2015-07-07 09:29:50

2012-06-13 13:25:16

UNIX操作系統

2016-07-11 11:38:32

2010-12-20 09:27:07

2023-10-12 22:35:08

2025-04-22 00:05:00

2013-08-16 09:43:26

2012-08-27 09:44:26

2021-12-30 08:13:00

JWT登錄令牌

2024-08-30 12:53:52

2022-08-12 07:01:00

Node.jsXSS腳本

2022-06-20 16:18:25

MySQL安全免密碼輸入

2013-08-26 10:19:24

納斯達克數據專線交易暫停

2009-05-26 16:23:25

運維管理IT管理摩卡

2019-06-17 08:00:55

multipassbash腳本
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 性欧美精品一区二区三区在线播放 | 日韩一区二区av | 狠狠狠色丁香婷婷综合久久五月 | 日韩一区二区免费视频 | 欧美亚洲国产一区二区三区 | 国产一区不卡 | 99视频网站 | 国产精品激情在线 | 免费观看www7722午夜电影 | 欧美一级淫片007 | 韩日一区二区 | 有码一区| 蜜桃传媒一区二区 | 日p视频免费看 | 成人精品久久 | 天天夜天天操 | 成人小视频在线观看 | 国产午夜精品一区二区三区嫩草 | 成人欧美一区二区三区在线观看 | 国产一区免费视频 | 在线观看免费黄色片 | 激情在线视频 | 欧美一级α片 | 国产精品一区二区福利视频 | 日韩久久综合网 | 第一区在线观看免费国语入口 | 国产97人人超碰caoprom | 一区在线观看 | 中文字幕三区 | 国产成人精品999在线观看 | 亚洲久在线 | 国产1区2区 | 国产一区二区影院 | 成人久久网 | 久热精品视频 | 91麻豆精品国产91久久久久久 | 国产精品99久久久久久宅男 | 午夜影视在线观看 | 国产美女视频黄a视频免费 国产精品福利视频 | 国产三级网站 | 免费一级淫片aaa片毛片a级 |