Node中异常:exit code与 dockerfile

更新日期: 2019-07-30阅读: 3k标签: 异常

最近观察项目 CI 跑的情况如何时,会偶尔发现一两个镜像虽然构建成功但是容器跑不起来的情况。究其原因,是因为一个 exit code 的问题


throw new Error 与 Promise.reject 区别

以下是两段代码,第一个是抛出一个异常,第二个是 Promise.reject,两段代码都会如下打印出一段异常信息,那么两者有什么区别?

function error () {
  throw new Error('hello, error')
}

error()
// /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)
//     at Object.<anonymous> (/Users/shanyue/Documents/note/demo.js:5:1)
//     at Module._compile (internal/modules/cjs/loader.js:701:30)
async function error () {
  return new Error('hello, error')
}

error()

// (node:60356) UnhandledPromiseRejectionWarning: Error: hello, world
//    at error (/Users/shanyue/Documents/note/demo.js:2:9)
//    at Object.<anonymous> (/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)

从一个比较底层的角度来说,两者的 exit code 不一样,那 exit code 是什么东西?


exit code

exit code 代表一个进程的返回码,通过系统调用 exit_group 来触发。在 POSIX 中,0 代表正常的返回码,而 1-255代表异常返回码,不过一般错误码都是 1。这里有一张附表 Appendix E. Exit Codes With Special Meanings

所以,在 node 的应用中经常会有 process.exit(1) 来代表因为不期望的异常而中断。

现在看一个关于 cat 的异常以及它的 exit code 与系统调用

$ cat a
cat: a: No such file or directory

# -e 代表只显示 write 与 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 +++

可以看出,它的 exit code 是 1,并且把错误信息写到 stderr (标准错误的 fd 为2) 中了


如何查看 exit code

其实从上边的内容可以看出,可以使用 strace 来判断进程的 exit code。但是这样实在太不方便了,特别是在 shell 编程环境中。

有一种简单的方法,通过 echo $? 来输出返回码

$ cat a
cat: a: No such file or directory

$ echo $?
1

在对上述两个测试用例查看 exit code,我们会发现 throw new Error() 的 exit code 为 1,而 Promise.reject() 的为 0。


Dockerfile 在 node 中的注意点

node 中的异常与 exit code 都说完了,接下来该说与 Dockerfile 的关联了。

当使用 Dockerfile 构建镜像时,如果其中 RUN 的进程返回非0的返回码,则构建就会失败。

而在 Node 中的错误处理中,我们倾向于所有的异常都交由 async/await 来处理,而当发生异常时,由于此时 exit code 为 0 并不会导致镜像构建失败。 如下所示

FROM node:alpine

RUN node -e "Promise.reject('hello, world')"
$ docker build -t demo .
Sending build context to Docker daemon  14.85kB
Step 1/2 : FROM node:alpine
 ---> d97a436daee9
Step 2/2 : RUN node -e "Promise.reject('hello, world')"
 ---> Running in 0281c660ab82
(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(). (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 0281c660ab82
 ---> 2146545654d2
Successfully built 2146545654d2
Successfully tagged demo:latest

而在编译时能发现的问题,绝不要放在运行时。所以,构建镜像需要执行 node 的脚本时,对异常处理需要手动指定 1 的 exit code:process.exit(1)。

runScript().catch(() => {
  process.exit(1)
})
<hr/>

原文来自:https://shanyue.tech/post/exit-code-node-and-docker


链接: https://www.fly63.com/article/detial/4411

前端JS 异常处理实践

大多时候(除:网络故障与请求被阻止外),使用fetch()返回的 Promise被标记为resolve,包括(接收到一个代表错误的 HTTP 状态码时,HTTP 响应的状态码是 404 或 500,但是,此时会将 resolve 的返回值的 ok 属性设置为 false

JavaScript错误处理权威指南

JavaScript 错误和一般处理 throw new Error(\'something went wrong\') 会在 JavaScript 中创建一个错误实例,并停止脚本的执行,除非你对错误做了一些处理。当你作为 JavaScript 开发者开启自己的职业生涯时,你自己很可能不会这样做

慎用try catch

ECMA-262第3版引入了try catch语句,作为JavaScript中处理异常的一种标准方式。基本的语法如下所示。但是在前端js代码中很少看到try catch语句,并不是所以代码都需要加try catch来作得不偿失的保险

前端开发中的Error以及异常捕获

在前端项目中,由于JavaScript本身是一个弱类型语言,加上浏览器环境的复杂性,网络问题等等,很容易发生错误。做好网页错误监控,不断优化代码,提高代码健壮性是一项很重要的工作

PHP异常处理机制

异常(Exception)是一种错误处理机制,用于在指定的错误发生时改变脚本的正常流程。当异常被触发时,当前代码状态被保存,代码执行被切换到预定义的异常处理器函数(如果有)

js中的异常处理

js中的异常处理语句有两个,一个是try……catch……,一个是throw。try……catch用于语法错误,错误有name和message两个属性。throw用于逻辑错误。对于逻辑错误,js是不会抛出异常的

关于try、catch、finally的执行顺序

try中没有抛出异常,则catch语句不执行,如果有finally语句,则接着执行finally语句,继而接着执行finally之后的语句;不管是否try...catch,finally都会被执行。当try...catch中有return的话,finally后会执行try...catch中的return

Laravel异常:捕获,处理和创建

很多开发者在开发过程中都会遇到异常,处理过程大同小异:捕获然后处理,事实上也确实是如此。只是从laravel自带的Exception入手,谈一谈怎样用一个更好的方式处理错误信息。

js中try、catch、finally的执行规则

首先一个常识就是,在浏览器执行JS脚本过程中,当出现脚本错误,并且你没有手动进行异常捕捉时,他会在浏览器下面出现黄色的叹号,这是正常的

从JavaScript到Python之异常

不少前端工程师看到这个标题可能会产生质问:我js用得好好的,能后端能APP,为什么还要学习Python?至少有下面两个理由:

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!