Bash 腳本入口點 (PID=1) 僅在存在虛假陷阱(不執行任何操作)時才會殺死“tail”子程序
我在我的
Bash
腳本中遇到了一個奇怪的行為,我有這個Bash
正在執行的腳本PID 1
(它是一個entrypoint
forDocker
容器,如果你不熟悉 Docker,我假設你可以忽略這個資訊)。當我執行以下腳本時,
SIGTERM
一切都很快終止,一切似乎都很好(請記住,sshd
服務不存在!我的整個系統只啟動了這個腳本,它不再執行tail
,但直到現在它不是問題) .#!/bin/bash trap "pkill sshd" SIGTERM export PATH=/usr/local/samba/bin/:/usr/local/samba/sbin/:$PATH if [ -f /usr/local/samba/etc/smb.conf ]; then exec /usr/local/samba/sbin/samba -i else tail -f /dev/null & wait ${!} fi
當我刪除它時,問題就來了
trap
。現在我的系統掛了,似乎是因為tail還在執行,並且由於某種原因沒有結束(如果你熟悉Docker,Docker會等待10秒,然後殺死容器,因為它沒有響應SIGTERM
,再次如果您不熟悉 Docker,請忽略此資訊)。#!/bin/bash export PATH=/usr/local/samba/bin/:/usr/local/samba/sbin/:$PATH if [ -f /usr/local/samba/etc/smb.conf ]; then exec /usr/local/samba/sbin/samba -i else tail -f /dev/null & wait ${!} fi
有人可以向我解釋到底是什麼問題嗎?為什麼那個假貨
trap
能讓一切正常工作(雖然它實際上什麼也沒做,但它確實有效,因為它就在那裡)。我仍然想提一下,使用空的
trap
:trap "" SIGTERM
沒有幫助,陷阱中應該有一些東西可以工作(即使它什麼都不做)。希望有人能幫助我,謝謝!
實際上
t
在執行容器時添加參數(分配tty)可以解決問題。我用-d
參數執行它,現在用-td
.我不知道為什麼,但它做到了。如果有人能解釋為什麼會發生這種情況,那就太好了。
您沒有提供您的
Dockerfile
,也不清楚您如何將SIGTERM
信號發送到容器。但是,這是我試圖重現您的問題的方法:
我的
Dockerfile
:FROM ubuntu ADD ./entrypoint.sh /opt/entrypoint.sh # Using the exec form here, so that the process is assigned PID 1. ENTRYPOINT ["/opt/entrypoint.sh"]
建構容器:
$ docker build -f Dockerfile -t test_image .
每次更改入口點腳本時不要忘記重建容器。
使用以下命令執行容器:
$ docker run --rm -it --name test_trap test_image
現在,讓我們看看每次執行時發生了什麼。
1)使用腳本
trap
中的行:Bash
# The main process will receive SIGTERM, trap it and exit. $ docker stop test_trap # The main process will receive SIGTERM, trap it and exit. $ docker kill -s=TERM test_trap # The main process will receive SIGKILL and will be stopped immediately. $ docker kill -s=KILL test_trap
2)沒有
trap
線:# The main process will receive SIGTERM which will be ignored. # After a grace period (10s by default) it will receive SIGKILL and will be stopped. $ docker stop test_trap # The main process will receive SIGTERM which will be ignored. # Container will continue running. $ docker kill -s=TERM test_trap # The main process will receive SIGKILL and will be stopped immediately. $ docker kill -s=KILL test_trap
原因是核心
PID 1
特別對待一個程序並且不會殺死接收SIGTERM
信號的程序(以及SIGINT
)。有關此問題的更多資訊:
任何程序都可以為 TERM 註冊自己的處理程序,並在退出之前使用它們執行清理。如果程序沒有註冊自定義信號處理程序,核心通常會退回到 TERM 信號的預設行為:終止程序。
但是,對於 PID 1,核心在轉發 TERM 時不會回退到任何預設行為。如果您的程序沒有註冊自己的處理程序(大多數程序沒有),則 TERM 不會對程序產生影響。
來源 - https://engineeringblog.yelp.com/2016/01/dumb-init-an-init-for-docker.html
更新
我還不能發表評論,所以我會在這裡發表評論。這是同樣的
PID 1
問題。兩者都-d
和-td
信號處理按預期工作:TERM
被忽略,因為入口點程序被分配PID 1
,而KILL
終止程序。如果添加該trap
行,則TERM
信號將在兩種情況下都被擷取。如果由於任何原因它對您不起作用,那麼您應該發布您Dockerfile
執行的確切命令並相應地更新您的問題。