如果在没有 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_shell
和 term_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 脚本