容器中用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命令

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM