Docker bash shell 脚本无法捕获 SIGINT 或 SIGTERM 文档详情相关说明

如何解决Docker bash shell 脚本无法捕获 SIGINT 或 SIGTERM 文档详情相关说明

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

Dockerfile

FROM debian

workdir /app
copY start.sh /app/

CMD ["/app/start.sh"]

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

#!/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。请注意,信号被指定为 without the SIG prefix

#!/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 may ignore some signals 起,长 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 interruption signal}
  • 否则,如果信号没有转发到子进程,我们就有可能遇到“PID 1 僵尸收割问题”,例如
    {另请参阅此 SO 问题了解详情:Speed up docker-compose shutdown}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?