容器中使用shell脚本启动如何优雅关闭(传送kill SIGTERM信号)

半兽人 发表于: 2020-12-02   最后更新时间: 2021-08-12 11:21:12  
{{totalSubscript}} 订阅, 2,275 游览

场景1

CMD ["java", "-jar", "app.jar"]

这时候java程序的PID=1也就是容器的主进程

执行docker stop <container>也就等于kill -15 1,这时候只要java程序能够处理SIGTERM信号即可

场景2

CMD ["/home/default/start.sh"]

start.sh

#!/bin/bash
echo "[INFO] 开始运行"
java -jar app.jar

很多时候我们一般会用一个shell脚本作为容器的主进程,这样启动逻辑就很灵活

执行docker stop <container>也就等于 kill -15 1,shell脚本收到SIGTERM信号后并不会把信号传给它的子进程,也就是说java程序不会做任何动作,直到宽限期到期会强制关闭容器等于kill -9

docker 使用 docker stop -t 参数指定宽限期默认是10秒,kubernetes里面使用 terminationGracePeriodSeconds: 30

解决

方法1

那么shell如何传递SIGTERM信号给它的子进程?

#!/bin/bash
echo "[INFO] 开始运行"
java -jar app.jar &
pid="$!"

_kill() {
  echo "[INFO] Receive sigterm"
  kill $pid
  wait $pid
  exit 143
}
trap _kill SIGTERM
wait

步骤是把java程序后台启动以获得它的PID,最后一行加入wait命令防止shell退出,trap命令捕捉SIGTERM信号并执行一个命令

方法2

假设shell脚本里面只需求启动一个子程序,其实有更简洁的办法

#!/bin/bash
echo "[INFO] 开始运行"
exec java -jar app.jar

exec特性是不产生新的子进程而是当前shell进程,所以exec之后的命令将不会执行。

更新于 2021-08-12
在线,6小时前登录

查看shell更多相关的文章或提一个关于shell的问题,也可以与我们一起分享文章