In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-03-28 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
This article mainly explains "analyzing the death and aftermath of a Node process". The content of the explanation is simple and clear, and it is easy to learn and understand. Please follow the editor's train of thought to study and learn "analyze the death and aftermath of a Node process".
Exit Code
What is exit code?
Exit code represents the return code of a process, which is triggered by a system call to exit_group.
In POSIX, 0 represents a normal error code, and 1-255 represents an exception error code. in business practice, the error code thrown actively is 1. Call API process.exitCode = 1 in the Node application to represent that the process exits because of an unexpected exception.
Here is a schedule of exception codes Appendix E. Exit Codes With Special Meanings [1].
Exit Code NumberMeaningExampleComments1Catchall for general errorslet "var1 = 1amp 0" Miscellaneous errors, such as "divide by zero" and other impermissible operations2Misuse of shell builtins (according to Bash documentation) empty_function () {} Missing keyword or command, or permission problem (and diff return code on a failed binary file comparison). 126Command invoked cannot execute/dev/nullPermission problem or command is not an executable127 "command not found" illegal_commandPossible problem with $PATH or a typo128Invalid argument to exitexit 3.14159exit takes only integer args in the range 0255 (see first footnote) 128+nFatal error signal "n" kill-9$ PPID of script$? Returns 137128 + 9) 130Script terminated by Control-CCtl-CControl-C is fatal error signal 2, see above) 255*Exit status out of rangeexit-1exit takes only integer args in the range 0-255
Exception codes can be found everywhere in the operating system. Here is an exception about the cat process and its exit code, and uses strace to track system calls.
$cat a cat: a: No such file or directory # use strace to view the system calls of cat #-e shows only the system calls of write and exit_group $strace-e write,exit_group cat a write (2, "cat:", 5cat:) = 5 write (2, "a", 1a) = 1 write (2, ": No such file or directory") 27: No such file or directory) = 27 write (2, "\ n", 1) = 1 exit_group (1) =? + exited with 1 +
As can be seen from the last line displayed by the strace tracking process, the process's exit code is 1 and the error message is output to stderr (stderr's fd is 2)
How to view exit code
The exit code of the process can be judged from the strace, but it is not convenient and redundant, and it is impossible to locate the abnormal code in the first place.
There is an easier way to do this through echo $? To confirm the return code
$cat a cat: a: No such file or directory $echo $? 1$ node-e "preocess.exit (52)" $echo $? 52
Where is the unperceived pain: the difference between throw new Error and Promise.reject
Here are two pieces of code. The first paragraph throws an exception, the second paragraph Promise.reject, and both pieces of code print out an exception message as follows, so what's the difference between the two?
Function error () {throw new Error ('hello, error')} error () / / Output: / / Users/shanyue/Documents/note/demo.js:2 / / throw new Error (' hello, world') / / ^ / Error: hello, world / / at error (/ Users/shanyue/Documents/note/demo.js:2:9) async function error () {return new Error ('hello) Error')} error () / Output: / / (node:60356) UnhandledPromiseRejectionWarning: Error: hello, world / / at error (/ Users/shanyue/Documents/note/demo.js:2:9) / / at Object. (/ Users/shanyue/Documents/note/demo.js:5:1) / / at Module._compile (internal/modules/cjs/loader.js:701:30) / / at Object.Module._extensions..js (internal/modules/cjs/loader.js:712:10)
Use echo $? for the above two test cases. If we look at exit code, we will find that the exit code of throw new Error () is 1 and that of Promise.reject () is 0.
From the operating system's point of view, an exit code of 0 means that the process runs and exits successfully, but even if there is Promise.reject, the operating system will consider it to have executed successfully.
This leaves a security risk when executing scripts in Dockerfile and CI.
The hidden trouble of Dockerfile in the construction of Node image
When building an image or CI using Dockerfile, the build will fail if the process returns a non-zero return code.
This is an easy-to-understand mirror image with Promise.reject () problems, from which we can see what the problem is.
FROM node:12-alpine RUN node-e "Promise.reject ('hello, world')"
The process of building the image is as follows, and the last two lines indicate that the image is built successfully: even though the unhandledPromiseRejection information is printed out during the build process, the image is still built successfully.
$docker build-t demo. Sending build context to Docker daemon 33.28kB Step 1 UnhandledPromiseRejectionWarning 2: FROM node:12-alpine-> 18f4bc975732 Step 2 UnhandledPromiseRejectionWarning 2: RUN node-e "Promise.reject ('hello, world')"-> Running in 79a6d53c5aa6 (node:1) UnhandledPromiseRejectionWarning: hello, world (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) (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. Removing intermediate container 79a6d53c5aa6-> 09f07eb993fe Successfully built 09f07eb993fe Successfully tagged demo:latest
However, if you are in a node 15 image, the image will fail to build, for the following reasons.
FROM node:15-alpine RUN node-e "Promise.reject ('hello, world')" $docker build-t demo. Sending build context to Docker daemon 2.048kB Step 1x2: FROM node:15-alpine-- > 8bf655e9f9b2 Step 2 hello 2: RUN node-e "Promise.reject ('hello, world')"-- > Running in 4573ed5d5b08 node:internal/process/promises:245 triggerUncaughtException (err, true / * fromPromise * /); ^ [UnhandledPromiseRejection: 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 (). The promise rejected with the reason "hello, world". {code: 'ERR_UNHANDLED_REJECTION'} The command' / bin/sh-c node-e "Promise.reject ('hello, world')"' returned a non-zero code: 1
Promise.reject scripting solution
Never put problems that can be found at compile time at run time. Therefore, when the node script needs to be executed in the construction image or CI, the exception handling needs to manually specify process.exitCode = 1 to expose the problem in advance.
RunScript () .catch (() = > {process.exitCode = 1})
When building an image, Node also has suggestions for exception solutions:
RunScript () .catch (() = > {process.exitCode = 1})
According to the prompt,-unhandled-rejections=strict will set the exit code of Promise.reject to 1 and fix the Promise exception exit code in future node versions.
The next version, Node 15.0, already treats unhandled-rejections as an exception and returns a non-zero exit code.
$node-unhandled-rejections=strict error.js
Signal
On the outside, how do you kill a process? Answer: kill $pid
More precisely, a kill command is used to send signal to a process rather than kill the process. Probably because more people kill the process, it becomes kill.
The kill utility sends a signal to the processes specified by the pid operands.
Each signal is represented by a number, and the signal list can be printed by kill-l
# list all signal $kill-l 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGTERM 16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ 26) SIGVTALRM 27) SIGWINCH 29) SIGIO 29) SIGPWR 31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+2 37) SIGRTMIN+3 38) SIGRTMIN+4 39) SIGRTMIN+6 41) SIGRTMIN+7 43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51 SIGRTMAX-13 52) SIGRTMAX-12 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX -8 57) SIGRTMAX-7 58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2 63) SIGRTMAX-1 64) SIGRTMAX
Among these signals, the ones that have the most contact with the terminal process are the following, in which SIGTERM is the default signal sent by kill, and SIGKILL is the forced kill process signal.
Whether the signal digital can capture description SIGINT2 can capture Ctrl+C interrupt process SIGQUIT3 can capture Ctrl+D interrupt process SIGKILL9 cannot capture forced interrupt process (cannot block) SIGTERM15 can capture graceful termination process (default signal) SIGSTOP19 cannot capture graceful termination process
In Node, process.on can listen for a trappable exit signal without exiting. The following example monitors SIGINT and SIGTERM signals. SIGKILL cannot be monitored, and setTimeout guarantees that the program will not exit.
Console.log (`Pid: ${process.pid} `) process.on ('SIGINT', () = > console.log (' Received: SIGINT')) / / process.on ('SIGKILL', () = > console.log (' Received: SIGKILL')) process.on ('SIGTERM', () = > console.log (' Received: SIGTERM')) setTimeout (() = > {}, 1000000)
Run the script, start the process, you can see the pid of the process, use kill-2 97864 to send the signal, the process receives the signal and does not exit
$node signal.js Pid: 97864 Received: SIGTERM Received: SIGINT Received: SIGINT Received: SIGINT
Elegant handling of exit in container
When you need to close the expired Pod during the upgrade of K8s container service, a SIGTERM signal will be sent to the main process of the container (PID 1), and 30 seconds will be reserved for the aftermath. If the container has not exited after 30 seconds, K8s will continue to send a SIGKILL signal. If the ancient emperor Bai Aya gave you death, he would teach you decency.
In fact, it is not just the container, but the script in CI also has to handle the exit of the process gracefully.
When the SIGTERM/SIGINT signal is received, set aside one minute to do the unfinished business.
Async function gracefulClose (signal) {await new Promise (resolve = > {setTimout (resolve, 60000)}) process.exit ()} process.on ('SIGINT', gracefulClose) process.on (' SIGTERM', gracefulClose)
This is the right thing to do to set aside time for the script, but what if there is a steady stream of requests from a service? Then let the service shut down actively and call server.close () to end the service.
Const server = http.createServer (handler) function gracefulClose (signal) {server.close (() = > {process.exit ()})} process.on ('SIGINT', gracefulClose) process.on (' SIGTERM', gracefulClose) Thank you for your reading. This is the content of "analyzing the death and aftermath of a Node process". After the study of this article, I believe that you have a deeper understanding of the analysis of the death and aftermath of a Node process, and the specific use needs to be verified in practice. Here is, the editor will push for you more related knowledge points of the article, welcome to follow!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.