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

Posted

技术标签:

【中文标题】如果在没有 shell 的情况下运行,Ruby 会以退出代码 1 响应 TERM 退出【英文标题】:Ruby exits with exit code 1 responding to TERM if running without shell 【发布时间】:2018-05-04 07:31:16 【问题描述】:

如果 Ruby 收到 TERM 信号,它通常会以退出代码 143 退出,根据this source,这表明进程成功响应了该信号。但是如果我让脚本在没有 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?

【问题讨论】:

term_shellterm_exit 是什么? Docker 镜像使用docker run 命令上方的 Dockerfile 构建。 【参考方案1】:

第二个示例的退出代码是 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 直接以 pid 1 的根进程身份执行ruby -e

Linux 上的 PID 1 的行为与正常的不同。来自docker documentation:

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

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

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

【讨论】:

感谢您的链接,我意识到我们希望我们的容器使用--init 选项运行,该选项运行tini。 ECS 选项称为"linuxParameters": "initProcessEnabled": true

以上是关于如果在没有 shell 的情况下运行,Ruby 会以退出代码 1 响应 TERM 退出的主要内容,如果未能解决你的问题,请参考以下文章

OpenSUSE:如何在没有 /bin/bash --login 的情况下登录到 shell? (自动)[关闭]

如何在没有 shell 命令的情况下运行 websocket

在不出现 Windows 控制台的情况下运行 Python 脚本

如何在没有 Spark-Shell 的情况下从 AWS 控制台运行 Spark jar 文件

Linux下使Shell 命令脱离终端在后台运行

shell脚本检测服务