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

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

问题描述

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

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

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