Docker Run Script捕捉中断信号 [英] Docker Run Script to catch interruption signal
问题描述
我有一个docker-compose.yml,它启动了多个容器. 其中之一使用Dockerimage文件安装该容器中所需的所有东西.
I've a docker-compose.yml which starts several containers. One of which uses a Dockerimage file to install everything needed in that container.
我想添加一个脚本,该脚本在每次等待中断信号0、9和137时运行.
I'd like to add a script which runs each time waiting for the interruption signals 0, 9 and 137.
现在,我正在尝试将该脚本作为Dockerimage文件中的入口点运行,但似乎不起作用.
Now, I'm trying to run the script as an Entrypoint in the Dockerimage file, but doesn't seems to work.
这是Dockerimage文件的内容:
This is the content of the Dockerimage file :
RUN apt-get update && [...]
WORKDIR "/application"
ENTRYPOINT ["/bin/bash", "-c", "/application/scripts/cl.sh"]
我做错什么了吗?我需要使用以下命令来重建容器吗?
Am I doing something wrong? Do I need to rebuild the containers with the following command?
docker-compose build
这是bash脚本cl.sh的内容
This is the content of the bash script cl.sh
#!/bin/bash
echo "HELLO HELLO HELLO HELLO"
trap 'echo "Exiting with a 137 signal."' 137 0 9
此脚本的唯一目的是测试所有工作.
The only purpose of the script at the moment is testing everything work.
推荐答案
是的,可以实现您想要的,但是在显示相应的代码之前,我必须对包含以下问题的问题的代码进行评论:
Yes it is possible to achieve what you want, but before presenting the corresponding code I have to comment on your question's code which contained some issues:
-
trap 'echo "Exiting with a 137 signal."' 137 0 9
行不正确,因为137不是有效的信号编号(例如,请参见有关信号的维基百科文章).
The line
trap 'echo "Exiting with a 137 signal."' 137 0 9
is incorrect because 137 is not a valid signal number (see for example the Wikipedia article on signals).
也许您刚遇到137,因为它是与信号 9对应的退出代码(假设137 = 128 + 9,请参见
Maybe you just encountered 137 as it is the exit code corresponding to the signal 9 (given that 137 = 128 + 9, see this appendix in the bash doc.)
0(EXIT)和9(KILL)是有效的信号编号,但是实际上最好按照
0 (EXIT) and 9 (KILL) are valid signal numbers, but in practice it is better to only trap 2 (INT) and 15 (TERM), as suggested in this SE/Unix answer.
实际上,尽管可以将INT和TERM信号用于正常终止",但KILL信号意味着必须立即终止该进程,并且如man trap
所述:
Indeed while the INT and TERM signals can be used for "graceful termination", the KILL signal means the process must be killed immediately and as mentioned in man trap
:
设置SIGKILL或SIGSTOP的陷阱会产生未定义的结果. […]陷阱SIGKILL或SIGSTOP在某些历史实现中在语法上被接受,但没有任何效果.便携式POSIX应用程序无法尝试捕获这些信号.
Setting a trap for SIGKILL or SIGSTOP produces undefined results. […] Trapping SIGKILL or SIGSTOP is syntactically accepted by some historical implementations, but it has no effect. Portable POSIX applications cannot attempt to trap these signals.
在入口点脚本的末尾设置陷阱是一个错误的策略,因为在此位置它是无用的.相反,我建议您定义一个清理函数(最后一条指令为exit
),然后在脚本开始时在此函数上设置一个陷阱,然后再运行(非终止)应用程序.
Setting the trap at the end of the entrypoint script is a bad strategy, as it is useless in this place. Instead, I suggest that you define a cleanup function (the last instruction of which being exit
), then set a trap on this function at the beginning of the script, and run your (non-terminating) application afterwards.
因此有以下概念证明:
Dockerfile
Dockerfile
FROM debian:latest
WORKDIR /app
COPY entrypoint.bash ./
ENTRYPOINT ["/bin/bash", "./entrypoint.bash"]
entrypoint.bash
entrypoint.bash
#!/bin/bash
cleanup() {
echo "Cleaning up..."
exit
}
trap cleanup INT TERM
while :; do
echo "Hello! ${SECONDS} secs elapsed..."
sleep 1s
done
要对其进行测试,只需运行:
To test it, you just need to run:
$ docker build -t test-trap .
$ docker run -d --name=TEST-TRAP test-trap
# wait a few seconds
$ docker stop TEST-TRAP
$ docker logs -f TEST-TRAP
Hello! 0 secs elapsed...
Hello! 1 secs elapsed...
Hello! 2 secs elapsed...
Hello! 3 secs elapsed...
Cleaning up...
这篇关于Docker Run Script捕捉中断信号的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!