繁体   English   中英

Docker bash shell 脚本未捕获 SIGINT 或 SIGTERM

[英]Docker bash shell script does not catch SIGINT or SIGTERM

我在一个目录中有以下两个文件:

Dockerfile

FROM debian

WORKDIR /app
COPY start.sh /app/

CMD ["/app/start.sh"]

start.sh (权限 755 使用chmod +x start.sh

#!/bin/bash
trap "echo SIGINT; exit" SIGINT
trap "echo SIGTERM; exit" SIGTERM
echo Starting script
sleep 100000

然后我运行以下命令:

$ docker build . -t tmp
$ docker run --name tmp tmp

然后我希望按 Ctrl+C 会向程序发送一个 SIGINT,程序会将 SIGINT 打印到屏幕然后退出,但这并没有发生。

我还尝试运行$ docker stop tmp ,我希望它会向程序发送一个 SIGTERM,但检查$ docker logs tmp后显示没有捕获到 SIGTERM。

为什么 SIGINT 和 SIGTERM 没有被 bash 脚本捕获?

CTRL+C 向在该控制台上运行的docker发送信号。
向您可以使用的脚本发送信号

docker exec -it <containerId> /bin/sh -c "pkill -INT -f 'start\.sh'"

或者在脚本中包含echo "my PID: $$"并发送

docker exec -it <containerId> /bin/sh -c "kill -INT <script pid>"

docker 中的某些 shell 实现可能会忽略该信号。 此脚本将正确响应pkill -15 请注意,指定的信号没有SIG前缀

#!/bin/sh
trap "touch SIGINT.tmp; ls -l; exit" INT TERM
trap "echo 'really exiting'; exit" EXIT
echo Starting script
while true; do sleep 1; done

由于sleep可能会忽略某些信号,因此 long sleep命令被一个无限循环的短命令取代。

实际上,如果您使用以下命令之一运行容器,您的Dockerfilestart.sh入口点脚本对我来说就像Ctrl+C一样工作:

  • docker run --name tmp -it tmp
  • docker run --rm -it tmp

文件详情

docker run --help

  • --interactive = -i CLI 标志要求即使没有连接也保持 STDIN 打开
    (通常对交互式 shell 有用,或者当还传递--detach = -d CLI 标志时)
  • --tty = -t CLI 标志要求分配一个伪 TTY
    (特别是将信号转发到 shell 入口点,对您的用例特别有用)

相关说明

为了完整起见,请注意有几个相关问题可能会使docker stop花费太多时间并“退回”到docker kill ,这可能在 shell 入口点启动其他一些进程时出现:

  • 首先,当 shell 入口点的最后一行运行另一个主程序时,不要忘记在这行前面加上exec内置命令:
    exec prog arg1 arg2 ...
  • 但是当 shell 入口点打算长时间运行时,捕获信号(至少INT / TERM ,但不是KILL )非常重要;
    {另见这个问题: Docker Run Script to catch interrupt signal }
  • 否则,如果信号没有转发到子进程,我们就有可能遇到“PID 1 僵尸收割问题”,例如
    {有关详细信息,另请参阅此 SO 问题:加速 docker-compose shutdown }

我找到的解决方案是只使用--init标志。

docker run --init [MORE OPTIONS] IMAGE [COMMAND] [ARG...]

根据他们的文档......

在此处输入图像描述

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM