Docker Run Script 捕捉中断信号 [英] Docker Run Script to catch interruption signal

查看:17
本文介绍了Docker Run Script 捕捉中断信号的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个启动多个容器的 docker-compose.yml.其中之一使用 Dockerimage 文件来安装该容器中所需的一切.

我想添加一个每次等待中断信号 0、9 和 137 时运行的脚本.

现在,我正在尝试将脚本作为 Dockerimage 文件中的入口点运行,但似乎不起作用.

这是 Dockerimage 文件的内容:

RUN apt-get update &&[...]工作目录/应用程序"入口点 ["/bin/bash", "-c", "/application/scripts/cl.sh"]

我做错了吗?需要用下面的命令重建容器吗?

docker-compose 构建

<小时>

这是 bash 脚本 cl.sh 的内容

#!/bin/bash回声你好你好你好你好"trap 'echo "退出时发出 137 信号."' 137 0 9

目前脚本的唯一目的是测试一切是否正常.

解决方案

是的,可以实现你想要的,但是在展示相应的代码之前,我必须评论你的问题代码,其中包含一些问题:

  • trap 'echo "Exiting with a 137 signal."' 137 0 9 行不正确,因为 137 不是有效的信号编号(例如,请参见 关于信号的维基百科文章).

    也许你刚刚遇到 137,因为它是 exit code 对应于 signal 9(假设 137 = 128 + 9,请参阅 bash 文档中的这个附录.)

  • 0 (EXIT) 和 9 (KILL) 是有效的信号编号,但实际上最好只捕获 2 (INT) 和 15 (TERM),如 这个 SE/Unix 答案.

    事实上,虽然 INT 和 TERM 信号可用于优雅终止",但 KILL 信号意味着必须立即终止进程,如 man trap 中所述:

    <块引用>

    为 SIGKILL 或 SIGSTOP 设置陷阱会产生未定义的结果.[...] 捕获 SIGKILL 或 SIGSTOP 在语法上被一些历史实现所接受,但它没有效果.便携式 POSIX 应用程序无法尝试捕获这些信号.

  • 在入口点脚本的末尾设置陷阱是一个糟糕的策略,因为在这个地方它是无用的.相反,我建议您定义一个清理函数(最后一条指令是 exit),然后在脚本开头设置此函数的陷阱,然后运行您的(非终止)应用程序之后.

因此有以下概念验证:

<块引用>

Dockerfile

FROM debian:latest工作目录/app复制入口点.bash ./入口点 ["/bin/bash", "./entrypoint.bash"]

<块引用>

入口点.bash

#!/bin/bash清理(​​) {echo "清理中..."出口}陷阱清理 INT TERM尽管 :;做echo "您好!${SECONDS} 秒已过..."睡眠 1s完毕

要测试它,你只需要运行:

$ docker build -t test-trap .$ docker run -d --name=TEST-TRAP 测试陷阱# 等待几秒钟$ docker stop 测试陷阱$ docker logs -f 测试陷阱你好!0秒过去...你好!1秒过去了...你好!2 秒过去了……你好!3秒过去了……打扫干净...

I've a docker-compose.yml which starts several containers. One of which uses a Dockerimage file to install everything needed in that container.

I'd like to add a script which runs each time waiting for the interruption signals 0, 9 and 137.

Now, I'm trying to run the script as an Entrypoint in the Dockerimage file, but doesn't seems to work.

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


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:

  • 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).

    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) 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.

    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:

    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.

  • 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.

Hence the following proof-of-concept:

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

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆