Ruby 退出时退出,退出代码 1 响应 TERM,如果在没有 shell 的情况下运行



如果 Ruby 收到 TERM 信号,它通常会以退出代码 143 退出,根据此来源,这表明进程成功响应了该信号。但是如果我让脚本在没有 shell 的情况下运行,退出代码为 1。

带壳:

> cat Dockerfile 
FROM ruby:alpine
CMD ruby -e "Process.kill('TERM', Process.pid)" # <- shell form
> docker build -t term_shell . > /dev/null
> docker run term_shell
Terminated
> echo $?
143

不带外壳:

> cat Dockerfile
FROM ruby:alpine
CMD ["ruby", "-e", "Process.kill('TERM', Process.pid)"] # <- exec form
> docker build -t term_exec . > /dev/null
> docker run term_exec
> echo $?
1

但是如果我以 143 退出自己,则退出代码符合预期:

> cat Dockerfile
FROM ruby:alpine
CMD ["ruby", "-e", "exit(143)"] # <- exec form
> docker build -t exit_exec . > /dev/null
> docker run exit_exec
> echo $?
143

为什么?当 ruby 收到 TERM 时,退出代码是否不是来自 Ruby,而是来自 shell?

第二个示例的退出代码1,因为调用Process.kill('TERM', Process.pid)失败。ruby -e由于此失败而退出,在这种情况下,状态代码为1

  • 使用CMD ruby -e "Process.kill('TERM', Process.pid)",docker 在 shell 中执行给定的命令。在正在运行的容器中,这意味着 pid 为 1 的根进程将被/bin/sh -c,并且ruby -e命令将在具有另一个 pid 的子进程中执行(例如 6(。
  • 使用CMD ["ruby", "-e", "Process.kill('TERM', Process.pid)"],docker 直接ruby -e作为根进程执行,pid 1。

Linux 上的 PID 1 的行为与普通 PID 不同。来自 docker 文档:

注意:在容器内作为 PID 1 运行的进程由 Linux 特别处理:它忽略任何具有默认操作的信号。因此,该过程不会在SIGINT或SIGTERM上终止,除非它被编码为这样做。

因此,在您的情况下,TERM信号不会发送给您的进程。

您可以在本文中找到有关 PID 1 行为的更多信息: https://hackernoon.com/my-process-became-pid-1-and-now-signals-behave-strangely-b05c52cc551c

相关内容

  • 没有找到相关文章

最新更新