#!/bin/sh
#
# Following guard prevents to stuck containers in DIND GitLab Runner
# If container still works in 300 seconds, this will kill yourself
THE_PID=$$
if [ $THE_PID -eq 1 ]; then
# Docker does not allow kill process 1, so restart as child process
/usr/local/bin/docker-entrypoint.sh
exit $?
fi
(sleep 300; echo "Killing process: $THE_PID"; kill -9 $THE_PID) &
YOUR_SCRIPT_TEXT....
7条答案
按热度按时间l7wslrjt1#
基本上,您需要PID 1退出以停止容器。
执行
kill -s SIGKILL 1
将不起作用,因为PID 1受到保护。正如@Thomasleveil所建议的那样,您可以将
trap "exit" SIGINT SIGTERM
这样的代码添加到PID 1脚本中,这意味着当发送kill -s SIGINT 1
时,进程将退出。比起你提出的方法(直接杀死子进程),我更喜欢这个方法,因为它给了父进程一个清理的机会,而且父进程应该能够在没有awk的情况下找到子进程的PID。处理这个问题最简单的方法是使用某种监督进程,Docker现在方便地提供了一个名为“tini”的进程。只需运行add参数
--init
todocker run
,Docker就会将tini设置为容器中的PID 1。完整的描述在这里:https://docs.docker.com/engine/reference/run/#specify-an-init-processnafvub8i2#
我遇到了同样的问题,我通过使用docker的healthcheck功能解决了它。
您可以在
heahthcheck.sh
这样的文件中添加检查以验证您的服务。然后在Dockerfile
中添加如下内容:字符串
这可以确保docker通过在指定的时间间隔内运行脚本来检查容器的健康状况,如果它连续失败5次,它会标记状态不健康。
现在,为了在状态不正常时重启容器,可以像这样使用autoheal:
型
这将在每次容器状态变得不健康时重新启动容器。
2ul0zpep3#
我最近不得不弄清楚这一点。在经历了很多挫折之后,我最终想到了这个:
在dockerfile中,指定一个ENTRYPOINT:
字符串
然后,提供这样的脚本。除了调用应用程序之外,它不需要做任何事情。您可以随意向脚本添加其他设置,但要注意,如果脚本在调用应用程序后执行了任何操作,它可能会屏蔽应用程序的返回代码。如果这与您相关,请确保让脚本捕获返回代码并将其作为自己的返回代码传播出去。
exec
来调用你的应用程序!*结果将是PID 1属于entrypoint.sh,而您的应用程序将具有其他PID。我的倾向于落在PID 9或10上。
然后,当需要终止应用程序时,只需确定其PID并调用
kill -SIGKILL $PID
或pkill -SIGKILL yourapp
。你的进程,不是PID 1,将收到信号并立即退出。您的entrypoint.sh
将立即退出,因为这是您设计的在流程退出后执行的操作。mlnl4t2r4#
来自@JakeRobb的灵感:你可以使用以下命令执行docker:
字符串
这将在低于1的PID上执行休眠。一旦你杀了它,循环就会退出。为此,在docker中用途:
型
uajslkp65#
/usr/local/bin/docker-entrypoint.sh
字符串
owfi6suc6#
我杀死了“阻塞过程”,即。docker正在运行的主进程;像这样(在这种情况下,docker正在运行一个sleep infinity命令,用于演示目的)。
ps-afx| grep睡眠|awk '{print $1}'| xargs kill-9
qgelzfjb7#
我试图杀死进程1,但没有成功。
给予用
shutdown -h now
评论@zero323。它工作正常(对不起,我不能直接投票给它,因为它不在答案列表中)。