我有一个docker-compose.yml,它启动了几个容器。 其中一个使用Dockerimage文件来安装该容器中所需的所有内容。
我想添加一个脚本,每次等待中断信号0,9和137时都会运行。
现在,我尝试将脚本作为Dockerimage文件中的入口点运行,但似乎无法正常工作。
这是Dockerimage文件的内容:
RUN apt-get update && [...]
WORKDIR "/application"
ENTRYPOINT ["/bin/bash", "-c", "/application/scripts/cl.sh"]
我做错了吗?我是否需要使用以下命令重建容器?
docker-compose build
这是bash脚本cl.sh
的内容#!/bin/bash
echo "HELLO HELLO HELLO HELLO"
trap 'echo "Exiting with a 137 signal."' 137 0 9
目前脚本的唯一目的是测试一切工作。
答案 0 :(得分:1)
是的,可以实现您想要的效果,但在提供相应的代码之前,我必须对您的问题代码进行评论,其中包含一些问题:
第trap 'echo "Exiting with a 137 signal."' 137 0 9
行不正确,因为137不是有效的信号编号(例如参见Wikipedia article on signals)。
也许您刚刚遇到137,因为它是与信号 9对应的退出代码(假设137 = 128 + 9,请参阅this appendix in the bash doc.)< / p>
0(EXIT)和9(KILL)是有效的信号编号,但实际上最好只捕获2(INT)和15(TERM),如this SE/Unix answer中所示。
实际上,虽然INT和TERM信号可以用于&#34;正常终止&#34;,但KILL信号意味着必须立即杀死该进程,如man trap
中所述:
为SIGKILL或SIGSTOP设置陷阱会产生未定义的结果。 [...]陷阱SIGKILL或SIGSTOP在语法上被一些历史实现所接受,但它没有任何效果。便携式POSIX应用程序无法捕获这些信号。
在入口点脚本末尾设置陷阱是一个糟糕的策略,因为它在这个地方没用。相反,我建议您定义一个清理函数(最后一条指令为exit
),然后在脚本开头设置此函数的陷阱,然后运行您的(非终止)应用程序。 / p>
因此,以下概念证明:
Dockerfile
FROM debian:latest
WORKDIR /app
COPY entrypoint.bash ./
ENTRYPOINT ["/bin/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
要测试它,您只需要运行:
$ 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...