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


    场景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之后的命令将不会执行

    方法3

    docker run --init 也就是加入 --init参数  https://docs.docker.com/engine/reference/run/

    或者在镜像里面加入tini  https://github.com/krallin/tini

    ENV TINI_VERSION v0.19.0
    ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini /tini
    RUN chmod +x /tini
    ENTRYPOINT ["/tini", "--"]
    CMD ["/home/default/start.sh"]

    经过测试tini更多关心的还是僵尸进程的清理,对于子进程信号传递(特别是多级子进程)默认情况下支持的并不好,使用tini最好配合exec命令

  • 相关阅读:
    linux分析、诊断及调优必备的“杀器”之二
    浏览器被“hao123.3377.com”主页劫持的解决办法
    Nginx一个实现负载均衡的强大web server
    【百度之星
    c/c++ 参数传递
    【百度之星】-IP聚合
    百度之星-大搬家-递推
    IOS开发之Swift学习笔记
    【Leetcode】84. Largest Rectangle in Histogram 85. Maximal Rectangle
    【Leetcode】82. Remove Duplicates from Sorted List II
  • 原文地址:https://www.cnblogs.com/37yan/p/12936026.html
Copyright © 2020-2023  润新知