Docker运行脚本以捕获中断信号

时间:2018-05-09 16:20:36

标签: bash docker docker-compose dockerfile

我有一个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

目前脚本的唯一目的是测试一切工作。

1 个答案:

答案 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...