:信號(hào)與前臺(tái)進(jìn)程這一層)
授權(quán)與合規(guī)聲明本文全部操作對(duì)象均為自建隔離靶場(chǎng)本機(jī)容器或隔離虛擬機(jī)涉及安全測(cè)試的環(huán)節(jié)必須以取得合法授權(quán)為前提。未經(jīng)授權(quán)的滲透測(cè)試違反《中華人民共和國(guó)網(wǎng)絡(luò)安全法》與《刑法》相關(guān)條款須承擔(dān)相應(yīng)法律責(zé)任。本文只講環(huán)境配置、版本對(duì)照與靶場(chǎng)隔離不含任何攻擊步驟、利用載荷與繞過(guò)手法請(qǐng)勿將文中環(huán)境指向任何非自有系統(tǒng)。一、一條命令停不下來(lái)先分清是哪一件事1.1 事情往往是這樣開(kāi)始的你敲了一條命令屏幕上開(kāi)始往外滾東西或者干脆什么都不動(dòng)只有光標(biāo)在那兒等著。你覺(jué)得不對(duì)勁按下了中斷組合鍵。有時(shí)候一次就回來(lái)了提示符重新出現(xiàn)有時(shí)候你按了三四次屏幕還是老樣子。更讓人迷惑的是同一條命令、同一個(gè)終端昨天按一次就回來(lái)今天怎么按都沒(méi)用。還有另一種情形你直接關(guān)掉終端窗口以為事情就這樣結(jié)束了。過(guò)了一會(huì)兒新開(kāi)一個(gè)終端去看發(fā)現(xiàn)之前那個(gè)東西還在跑。這幾種現(xiàn)象嘴上說(shuō)的都是停不下來(lái)可它們落在不同的位置上。第一種是你發(fā)出的信號(hào)到底給了誰(shuí)、對(duì)方有沒(méi)有理它第二種是發(fā)信號(hào)的那個(gè)源頭終端走了之后作業(yè)被怎么處置。本文講的是前一層信號(hào)與前臺(tái)進(jìn)程。1.2 分流只需要三個(gè)問(wèn)題分流不需要復(fù)雜工具三個(gè)問(wèn)題就夠。第一個(gè)問(wèn)題按鍵之后命令本身有沒(méi)有變化如果它停了說(shuō)明信號(hào)送到了而且被當(dāng)成了要處理的事如果它毫無(wú)反應(yīng)那要問(wèn)的就是——信號(hào)沒(méi)送到它手里還是它收到了卻選擇不理。這兩個(gè)原因的解釋完全不同。第二個(gè)問(wèn)題你按了幾次一次就回來(lái)和按好幾次才有反應(yīng)看起來(lái)是兩個(gè)毛病其實(shí)是同一件事的兩面。原因在第三章和第四章。第三個(gè)問(wèn)題終端窗口是不是被你關(guān)掉了如果是那走的根本不是按鍵這條路而是第五章要講的另一條路。這三個(gè)問(wèn)題各自對(duì)應(yīng)一個(gè)只讀動(dòng)作。??代碼待驗(yàn)證ps# 只讀看當(dāng)前這個(gè)會(huì)話下有哪些進(jìn)程dockerps# 只讀看容器列表以及它們各自當(dāng)前的狀態(tài)兩條都只做看這一件事不啟動(dòng)、不停止、也不改任何配置。你看到的現(xiàn)象更可能落在哪一層本文的哪一章按鍵之后命令停了提示符回來(lái)了信號(hào)送到了而且被當(dāng)成要處理的事第三章、第四章按了好幾次命令還在跑信號(hào)到了但接收方自己接管了它第四章關(guān)掉終端之后它居然還在跑終端退出與作業(yè)被如何處理第五章容器停不下來(lái)過(guò)幾秒才停容器的停止信號(hào)與寬限期第六章1.3 本文只講控制層先把范圍說(shuō)清楚。本文的觀察對(duì)象是控制層你怎么把一件事停下來(lái)以及停下來(lái)這個(gè)動(dòng)作到底發(fā)給了誰(shuí)。有幾件事本文不寫(xiě)不寫(xiě)怎么強(qiáng)行終止別人的進(jìn)程不寫(xiě)進(jìn)程注入這一類話題也不展開(kāi)容器的資源限制與內(nèi)存那一層。文中出現(xiàn)的每一條命令都只做看這件事。二、中斷組合鍵發(fā)出的是哪個(gè)信號(hào)2.1 一個(gè)鍵一個(gè)信號(hào)按下中斷組合鍵之后終端做的事不是把那條命令關(guān)掉而是發(fā)出一個(gè)信號(hào)。這一點(diǎn)是所有后續(xù)討論的前提按鍵本身不等于停止按鍵只是把一封信寄出去。這封信叫什么名字官方手冊(cè)寫(xiě)得很直接。Bash 官方手冊(cè)在講信號(hào)的那一節(jié)里描述這個(gè)信號(hào)來(lái)源時(shí)用的措辭是usually generated by ^C——也就是說(shuō)中斷組合鍵產(chǎn)出的信號(hào)就是SIGINT。那么停下來(lái)這個(gè)動(dòng)作是誰(shuí)做的是收到信號(hào)的那個(gè)進(jìn)程自己做的。信號(hào)到了它手上它可以按默認(rèn)方式對(duì)待對(duì)SIGINT來(lái)說(shuō)默認(rèn)就是終止自己也可以自己接管、決定不終止。所以按了鍵和停下來(lái)了之間從來(lái)不是等號(hào)。2.2 shell 自己對(duì)這些信號(hào)的態(tài)度還有一個(gè)容易被忽略的角色shell 本身。你在終端上敲的那個(gè)鍵最終是終端把信號(hào)發(fā)給了一批進(jìn)程而 shell 在不在這批進(jìn)程里取決于下一章要講的進(jìn)程組歸屬。同時(shí)shell 收到某些信號(hào)時(shí)也有自己的默認(rèn)態(tài)度。官方原話是逐字引用When Bash is interactive, in the absence of any traps, it ignores SIGTERM (so that ‘kill 0’ does not kill an interactive shell), and catches and handles SIGINT (so that the wait builtin is interruptible). When Bash receives a SIGINT, it breaks out of any executing loops. In all cases, Bash ignores SIGQUIT.這段話里含三件事逐條拆開(kāi)看第一交互式 shell 忽略SIGTERM你在終端里沖著這個(gè) shell 發(fā)SIGTERM它不會(huì)因此退出官方還給這條設(shè)計(jì)配了理由——為了不讓kill 0把交互式 shell 干掉。第二交互式 shell 會(huì)接住并處理SIGINT目的是讓wait這個(gè)內(nèi)建命令可以被中斷它收到SIGINT之后會(huì)跳出正在執(zhí)行的循環(huán)。第三在任何情況下Bash 都忽略SIGQUIT。官方用的是In all cases沒(méi)有留例外。截至 2026-09-27官方手冊(cè)這一節(jié)對(duì)交互式 shell 的口徑就是上面這三句。信號(hào)名交互式 Bash 的默認(rèn)態(tài)度官方依據(jù)逐字要點(diǎn)本文位置SIGTERM忽略it ignores SIGTERM (so that kill 0 does not kill an interactive shell)本章SIGINT接住并處理收到后跳出正在執(zhí)行的循環(huán)catches and handles SIGINT (so that the wait builtin is interruptible)本章SIGQUIT在任何情況下都忽略In all cases, Bash ignores SIGQUIT.本章SIGHUP默認(rèn)退出The shell exits by default upon receipt of a SIGHUP.第五章2.3 信號(hào)名從哪里來(lái)信號(hào)是一組帶名字的東西kill -l這個(gè)動(dòng)作的作用就是把信號(hào)名列出來(lái)。本文只把它是一個(gè)列出信號(hào)名的動(dòng)作這件事放在這里不貼它列出的內(nèi)容——本批一律不貼終端里的原始輸出。??代碼待驗(yàn)證kill-l# 只讀列出信號(hào)名不發(fā)送任何信號(hào)也不改變?nèi)魏螙|西有一點(diǎn)要單獨(dú)說(shuō)清楚kill -l只是看名字它自己不發(fā)信號(hào)、不結(jié)束任何進(jìn)程。名字和編號(hào)的對(duì)應(yīng)關(guān)系請(qǐng)以你自己系統(tǒng)上的手冊(cè)為準(zhǔn)本文不列任何編號(hào)對(duì)照表討論范圍只涉及五個(gè)名字SIGINT、SIGTERM、SIGKILL、SIGQUIT、SIGHUP。三、鍵盤(pán)信號(hào)到底發(fā)給了誰(shuí)3.1 未啟用作業(yè)控制同一個(gè)進(jìn)程組這是全文最硬的一條也是為什么有時(shí)按一下就回來(lái)了、有時(shí)按好幾次也沒(méi)用的根子。官方原話逐字引用the shell receives keyboard-generated signals such as SIGINT (usually generated by ‘^C’) that users commonly intend to send to that command. This happens because the shell and the command are in the same process group as the terminal, and ‘^C’ sends SIGINT to all processes in that process group.把這段翻成要點(diǎn)是三層意思第一你在終端里按下中斷鍵時(shí)這個(gè)信號(hào)的收件人不是你以為的那一個(gè)進(jìn)程而是終端那個(gè)進(jìn)程組里的所有進(jìn)程。第二之所以這件事會(huì)順帶打到 shell 身上是因?yàn)槲磫⒂米鳂I(yè)控制時(shí)shell 和它正在跑的那條命令處在同一個(gè)進(jìn)程組里——也就是與終端相關(guān)聯(lián)的那個(gè)進(jìn)程組。第三官方對(duì)這句話的用途也說(shuō)得很明白用戶的本意是把這個(gè)信號(hào)發(fā)給那條命令但因?yàn)閮烧咄Mshell 也跟著收到了。這解釋了一個(gè)很日常的現(xiàn)象——你按中斷鍵的時(shí)候那條命令停了命令行會(huì)話有時(shí)候也會(huì)跟著頓一下。3.2 啟用作業(yè)控制shell 不在那個(gè)進(jìn)程組里那么為什么有時(shí)候感覺(jué)又不一樣了因?yàn)?shell 到底在不在那個(gè)進(jìn)程組里是會(huì)變的。官方對(duì)另一種情形的表述是逐字引用the shell does not receive keyboard-generated signals, because it is not in the same process group as the terminal.啟用作業(yè)控制之后shell 把自己移出了與終端關(guān)聯(lián)的那個(gè)進(jìn)程組于是鍵盤(pán)產(chǎn)生的信號(hào)打不到它身上。信號(hào)還是照發(fā)只是那份收件名單里沒(méi)有它了。兩種情形并排看就是下面這張表情形shell 在不在終端那個(gè)進(jìn)程組里鍵盤(pán)信號(hào)發(fā)給誰(shuí)shell 會(huì)不會(huì)收到未啟用作業(yè)控制在該進(jìn)程組里的所有進(jìn)程會(huì)收到啟用作業(yè)控制不在該進(jìn)程組里的進(jìn)程不含 shell不會(huì)收到這張表解決了本文開(kāi)頭那個(gè)困惑的前一半你按下的每一次信號(hào)都發(fā)出去了但到底有幾方收到取決于當(dāng)時(shí)誰(shuí)和誰(shuí)在同一個(gè)組里。3.3 為什么這件事對(duì)排障有用這一章的價(jià)值不在于記住進(jìn)程組這個(gè)詞而在于改掉一個(gè)默認(rèn)假設(shè)你在終端里按鍵不是你直接對(duì)那條命令說(shuō)話而是往一個(gè)組里廣播了一封信誰(shuí)收到、誰(shuí)理它是接收方自己的選擇。所以當(dāng)你發(fā)現(xiàn)我按了它沒(méi)停的時(shí)候第一條判斷不是我按得不夠用力而是這封信到了它手上沒(méi)有以及它收到之后做了什么。后半個(gè)問(wèn)題就是下一章。??代碼待驗(yàn)證ps# 只讀看當(dāng)前會(huì)話下有哪些進(jìn)程以及它們各自的歸屬信息本文不給怎么改進(jìn)程組歸屬的示范動(dòng)作——那屬于改環(huán)境的操作不是看。四、命令結(jié)束之后shell 的兩條判斷4.1 未啟用作業(yè)控制時(shí)shell 還要再判一次前兩章講了未啟用作業(yè)控制時(shí)shell 和命令在同一個(gè)組里所以 shell 自己也收到了那個(gè)信號(hào)。既然收到了shell 該怎么做官方說(shuō)它會(huì)等前臺(tái)命令先結(jié)束然后做判斷判斷的依據(jù)是這條命令是怎么結(jié)束的。于是就有了兩條路。第一條路命令確實(shí)是因?yàn)檫@個(gè)信號(hào)而結(jié)束的。官方原話逐字引用If the command terminates due to the SIGINT, Bash concludes that the user meant to send the SIGINT to the shell as well, and acts on the SIGINT意思是既然命令是被SIGINT終止的Bash 就認(rèn)為你本來(lái)也想讓 shell 收到這個(gè)信號(hào)。走這一條路你按一次鍵命令停了shell 也按收到SIGINT的方式動(dòng)作——所以提示符干脆地回來(lái)了。第二條路命令不是因?yàn)檫@個(gè)信號(hào)而結(jié)束的。官方原話逐字引用If the command does not terminate due to SIGINT, the program handled the SIGINT itself and did not treat it as a fatal signal. In that case, Bash does not treat SIGINT as a fatal signal, either…意思是如果命令沒(méi)被這個(gè)信號(hào)干掉那就說(shuō)明這個(gè)程序自己接管了這個(gè)信號(hào)并且不把它當(dāng)成會(huì)要命的信號(hào)。這種情況下Bash 也不把它當(dāng)成會(huì)要命的信號(hào)。官方在這里舉了一個(gè)很具體的例子編輯器會(huì)把SIGINT當(dāng)成一個(gè)普通操作來(lái)處理比如中止一條正在進(jìn)行的編輯命令而不是退出程序本身。4.2 這就解釋了按了沒(méi)用把這兩條路放在一起那個(gè)困惑就解開(kāi)了。你按下中斷鍵信號(hào)發(fā)到了整個(gè)進(jìn)程組里前臺(tái)那個(gè)程序收到了。接下來(lái)往哪條路走取決于這個(gè)程序自己愿不愿意停它愿意停命令結(jié)束B(niǎo)ash 判定你也想讓 shell 停shell 跟著一起動(dòng)作它自己接管了這個(gè)信號(hào)、并且不認(rèn)為這個(gè)信號(hào)要命它就會(huì)繼續(xù)跑Bash 也跟著不把它當(dāng)回事。所以按好幾次才有反應(yīng)這件事多數(shù)時(shí)候不是信號(hào)沒(méi)送到而是接收方每一次都選擇了自己處理。你按多少次它就自己處理多少次只有當(dāng)它處理到某個(gè)邊界、真的退出了這個(gè)循環(huán)才結(jié)束。還要補(bǔ)一個(gè)前提這條判斷是未啟用作業(yè)控制時(shí)的邏輯。啟用作業(yè)控制時(shí)shell 根本不在那個(gè)組里、收不到鍵盤(pán)信號(hào)也就談不上跟著一起停。命令結(jié)束的方式Bash 的判斷你看到的結(jié)果命令因該信號(hào)而結(jié)束認(rèn)為你也想把這個(gè)信號(hào)發(fā)給 shell并且照做命令停shell 也跟著動(dòng)作命令沒(méi)因該信號(hào)結(jié)束程序自己處理了它不把這個(gè)信號(hào)當(dāng)成會(huì)要命的信號(hào)命令繼續(xù)跑看起來(lái)像按了沒(méi)用??代碼待驗(yàn)證信號(hào)送到了 和 對(duì)方停下來(lái)了 是兩件事判斷順序是 1. 這個(gè)信號(hào)發(fā)出去了嗎——按鍵這個(gè)動(dòng)作本身就發(fā)出去了。 2. 誰(shuí)收到了——取決于當(dāng)時(shí)誰(shuí)和誰(shuí)在同一個(gè)進(jìn)程組里第三章。 3. 收到的人怎么處理它——它自己說(shuō)了算這就是本章的兩條分岔。五、關(guān)掉終端窗口之后SIGHUP 與 disown5.1 shell 收到 SIGHUP 就退出前面幾章講的是按鍵這條路。還有一條路是終端本身沒(méi)了你關(guān)掉終端窗口或者連接斷開(kāi)了。官方對(duì) shell 在這種情況下的行為寫(xiě)得很明確逐字引用The shell exits by default upon receipt of a SIGHUP. Before exiting, an interactive shell resends the SIGHUP to all jobs, running or stopped.兩句話兩個(gè)要點(diǎn)。第一shell 收到SIGHUP時(shí)默認(rèn)行為就是退出。第二也是最容易讓人意外的一點(diǎn)在退出之前交互式 shell 會(huì)把這個(gè)SIGHUP再發(fā)一遍給它手上的所有作業(yè)不管這些作業(yè)是正在運(yùn)行的還是已經(jīng)停下的。也就是說(shuō)關(guān)掉終端這件事不是只管 shell 自己它會(huì)順手把信號(hào)轉(zhuǎn)發(fā)出去。這一條正好解釋了本文開(kāi)頭那個(gè)現(xiàn)象。你以為關(guān)掉窗口就等于結(jié)束了其實(shí)這條鏈?zhǔn)沁@樣的終端沒(méi)了 → shell 收到SIGHUP→ shell 決定退出 → 退出之前先把SIGHUP轉(zhuǎn)發(fā)給它帶著的那些作業(yè)。至于每個(gè)作業(yè)收到之后停不停仍然回到第四章那個(gè)問(wèn)題——它自己怎么處理這個(gè)信號(hào)。5.2 讓某個(gè)作業(yè)不收到它既然默認(rèn)是轉(zhuǎn)發(fā)給所有作業(yè)那自然會(huì)有一個(gè)反過(guò)來(lái)的需求我不想讓某個(gè)作業(yè)收到這封信。官方給的答案是disown——把這個(gè)作業(yè)從作業(yè)表里移出它就不會(huì)被轉(zhuǎn)發(fā)到了。這里要分清的是disown處理的是要不要把它算在我的作業(yè)里這件事而不是給它發(fā)一個(gè)停止信號(hào)。它本身不是一種停下來(lái)的動(dòng)作它改變的是一份名單。5.3 交互式 shell 對(duì) SIGTERM 與 SIGQUIT回到第二章那張表把兩種外來(lái)信號(hào)再對(duì)一次交互式 shell忽略SIGTERM理由是為了不讓kill 0把交互式 shell 干掉并且在任何情況下都忽略SIGQUIT。這兩條合起來(lái)能回答一個(gè)常見(jiàn)的疑問(wèn)“我在終端里沖著 shell 發(fā)一個(gè)終止信號(hào)它怎么不退出”——因?yàn)檫@是它有意為之的默認(rèn)態(tài)度不是它壞了。要讓它走走的是另一條路終端退出帶來(lái)的SIGHUP。情形默認(rèn)行為官方依據(jù)逐字要點(diǎn)交互式 shell 收到SIGTERM忽略it ignores SIGTERM (so that kill 0 does not kill an interactive shell)交互式 shell 收到SIGQUIT在任何情況下都忽略In all cases, Bash ignores SIGQUIT.交互式 shell 收到SIGINT接住并處理catches and handles SIGINT交互式 shell 收到SIGHUP默認(rèn)退出退出前把SIGHUP轉(zhuǎn)發(fā)給所有作業(yè)運(yùn)行中的與已停止的The shell exits by default upon receipt of a SIGHUP. Before exiting, an interactive shell resends the SIGHUP to all jobs, running or stopped.想讓某個(gè)作業(yè)不被轉(zhuǎn)發(fā)到用disown把它從作業(yè)表里移出同上下面這份資料把信號(hào)發(fā)給誰(shuí)、誰(shuí)理它、終端退出之后作業(yè)怎么辦這三段整理成了一頁(yè)和本章的對(duì)照表呼應(yīng)配套資料把信號(hào)歸屬、兩條判定、終端退出整理成一頁(yè)對(duì)照表放在資料包里掃碼即可獲取六、容器這一側(cè)docker stop 之后為什么要等幾秒6.1 默認(rèn)先 SIGTERM寬限期后才 SIGKILL前五章講的是你在終端里跑東西。容器里的程序是另一套入口但問(wèn)的是同一個(gè)問(wèn)題停下來(lái)這個(gè)動(dòng)作到底發(fā)給了誰(shuí)、發(fā)的是什么。Docker CLI 對(duì)docker container stop的說(shuō)明是逐字引用The main process inside the container will receive SIGTERM, and after a grace period, SIGKILL. The first signal can be changed with the STOPSIGNAL instruction in the container’s Dockerfile, or the --stop-signal option to docker run and docker create.拆成三層看第一先發(fā)給容器里的主進(jìn)程一個(gè)SIGTERM。注意是主進(jìn)程——容器里往往有好幾個(gè)進(jìn)程在跑先收到這封信的是被指定為主進(jìn)程的那一個(gè)。第二寬限期過(guò)去之后再發(fā)SIGKILL。官方在另一句里把這件事說(shuō)得更直逐字引用If the container does not exit after the timeout elapses, it’s forcibly killed with a SIGKILL signal.也就是說(shuō)寬限期是給它一個(gè)自己收尾的機(jī)會(huì)這個(gè)機(jī)會(huì)用完了它還沒(méi)退才走強(qiáng)制結(jié)束那一手。這就回答了本文開(kāi)頭那個(gè)問(wèn)題docker stop之后為什么要等幾秒——那幾秒不是命令卡了而是它本來(lái)就在等等主進(jìn)程自己把收尾做完。第三第一封信的名字是可以換的換的地方有兩個(gè)鏡像里的STOPSIGNAL或者啟動(dòng)時(shí)的--stop-signal選項(xiàng)。6.2 默認(rèn)是幾秒以及這個(gè)數(shù)到底從哪來(lái)關(guān)鍵的一句在這里逐字引用If no default is configured for the container, the Daemon determines the default, and is 10 seconds for Linux containers, and 30 seconds for Windows containers.這句話里有一個(gè)極容易被略過(guò)去的條件“如果沒(méi)有為容器配置默認(rèn)值”。也就是說(shuō)這個(gè)數(shù)不是容器自己帶來(lái)的而是在容器沒(méi)有自帶配置的時(shí)候由守護(hù)進(jìn)程來(lái)決定。截至 2026-09-27官方這一頁(yè)給出的守護(hù)進(jìn)程口徑是Linux 容器 10 秒Windows 容器 30 秒。為什么要強(qiáng)調(diào)默認(rèn)值從哪來(lái)因?yàn)樗苯記Q定排障的下一步。你看到等了十來(lái)秒才停不一定說(shuō)明這條命令寫(xiě)死了 10 秒而可能是這個(gè)容器沒(méi)有自己的配置、落到了守護(hù)進(jìn)程的默認(rèn)上。要確認(rèn)走的是哪一條默認(rèn)就得看容器本身有沒(méi)有配過(guò)。6.3 信號(hào)與寬限期怎么改官方對(duì)這兩個(gè)開(kāi)關(guān)的說(shuō)明是逐字引用--signalSignal to send to the container--timeout/-tSeconds to wait before killing the container兩條合起來(lái)就是這一章的全部機(jī)制一個(gè)開(kāi)關(guān)決定第一封信叫什么名字另一個(gè)開(kāi)關(guān)決定等多久。寬限期這個(gè)數(shù)由超時(shí)參數(shù)給出官方在這一頁(yè)寫(xiě)作--timeout簡(jiǎn)寫(xiě)-t在不同入口下它也可能寫(xiě)作--stop-timeout具體以你所用入口的文檔為準(zhǔn)。而等多久還有一個(gè)特殊取值逐字引用If you set --timeout to -1, no timeout is applied, and the daemon waits indefinitely for the container to exit.設(shè)成-1就是不設(shè)時(shí)限守護(hù)進(jìn)程會(huì)一直等下去等到容器自己退出為止。這一條用的時(shí)候要留意它不是一個(gè)更快停下來(lái)的設(shè)置而是一個(gè)不再走強(qiáng)制那一手、愿意一直等下去的設(shè)置。你觀察到的現(xiàn)象對(duì)應(yīng)的機(jī)制官方依據(jù)逐字要點(diǎn)docker stop之后等了幾秒才停寬限期到了才走強(qiáng)制結(jié)束after a grace period, SIGKILL等待的時(shí)間大約是十來(lái)秒Linux 容器容器沒(méi)配默認(rèn)值由守護(hù)進(jìn)程決定If no default is configured for the container, the Daemon determines the default想換第一封信的名字鏡像的STOPSIGNAL或--stop-signalcan be changed with the STOPSIGNAL instruction ... or the --stop-signal option想改等待時(shí)長(zhǎng)寬限期參數(shù)--timeout/-tSeconds to wait before killing the container想不設(shè)時(shí)限、一直等把超時(shí)設(shè)為-1no timeout is applied, and the daemon waits indefinitely6.4 只讀地看一眼容器現(xiàn)在是什么狀態(tài)??代碼待驗(yàn)證dockerps# 只讀看容器列表與當(dāng)前狀態(tài)dockerinspect容器名# 只讀看這個(gè)容器自身的配置里有沒(méi)有覆蓋默認(rèn)值docker inspect在這里的用處就是回答 6.2 那個(gè)問(wèn)題這個(gè)容器的默認(rèn)值是不是沒(méi)配。沒(méi)配時(shí)間就來(lái)自守護(hù)進(jìn)程配過(guò)就是配置里寫(xiě)的那一條。本文不給停止容器的示范動(dòng)作——這里只講停下來(lái)這個(gè)動(dòng)作的語(yǔ)義。七、把這一層變成動(dòng)作7.1 三個(gè)只讀動(dòng)作第一步先看東西還在不在。??代碼待驗(yàn)證ps# 只讀看當(dāng)前會(huì)話下還有哪些進(jìn)程dockerps# 只讀看容器列表和它們當(dāng)前的狀態(tài)這一步回答的是分流里的第一個(gè)問(wèn)題。重點(diǎn)不是看它跑得好不好而是先確認(rèn)它在不在。第二步看它有沒(méi)有自己的配置。??代碼待驗(yàn)證dockerinspect容器名# 只讀看容器自身的信號(hào)與超時(shí)相關(guān)配置有沒(méi)有被改過(guò)dockerversion# 只讀確認(rèn)你在跟哪一個(gè)客戶端與守護(hù)進(jìn)程打交道第二步回答的是第六章那個(gè)默認(rèn)值從哪來(lái)的問(wèn)題沒(méi)配過(guò)才是守護(hù)進(jìn)程的默認(rèn)。而docker version用來(lái)確認(rèn)你面對(duì)的是哪一個(gè)守護(hù)進(jìn)程——同一臺(tái)機(jī)器上裝了兩個(gè)環(huán)境時(shí)這一步能省掉很多繞路。7.2 現(xiàn)象到動(dòng)作的對(duì)照表把前面幾章的判斷收成一張表出問(wèn)題時(shí)按行對(duì)號(hào)現(xiàn)象更可能落在哪一層先做哪個(gè)只讀動(dòng)作按中斷鍵命令停了信號(hào)送到了而且被當(dāng)成要處理的事看它是否已經(jīng)不在進(jìn)程列表里按了好幾次命令還在跑接收方自己接管了這個(gè)信號(hào)先確認(rèn)它是不是本來(lái)就這么設(shè)計(jì)別再重復(fù)按鍵關(guān)掉終端之后它還在終端退出與作業(yè)被如何處理看還有哪些進(jìn)程活著再考慮disown這類名單調(diào)整docker stop之后等了幾秒容器的寬限期看這個(gè)容器有沒(méi)有屬于自己的默認(rèn)值配置對(duì) shell 發(fā)終止信號(hào)它不理交互式 shell 有意忽略SIGTERM不用重試這就是它的默認(rèn)行為這張表只需要記住一句先判斷信送到了沒(méi)有和對(duì)方理不理再?zèng)Q定要不要做別的動(dòng)作。7.3 一頁(yè)自檢表與三條可帶走的動(dòng)作出問(wèn)題的時(shí)候先把下面這張自檢表過(guò)一遍檢查項(xiàng)為什么查它在哪一層我按的是哪一類鍵不同的鍵產(chǎn)出不同的信號(hào)名信號(hào)來(lái)源當(dāng)時(shí) shell 在不在同一個(gè)進(jìn)程組里決定 shell 會(huì)不會(huì)也收到這封信進(jìn)程組歸屬命令是被告知結(jié)束的還是自己收尾的決定 shell 下一步跟不跟著停兩條判定終端是不是沒(méi)了SIGHUP走的是另一條路終端退出這個(gè)容器有沒(méi)有配過(guò)默認(rèn)值沒(méi)配過(guò)這個(gè)數(shù)就來(lái)自守護(hù)進(jìn)程容器側(cè)我想做的動(dòng)作是不是強(qiáng)行結(jié)束別人不在本文范圍也不該做邊界三條可以帶走的動(dòng)作先分清是沒(méi)送到還是不理會(huì)按鍵這個(gè)動(dòng)作每次都會(huì)把信號(hào)發(fā)出去差別在接收方。容器側(cè)先看配置有沒(méi)有被覆蓋沒(méi)被覆蓋走的才是守護(hù)進(jìn)程的默認(rèn)。不要靠重復(fù)按鍵來(lái)解決問(wèn)題重復(fù)按解決不了接收方自己的選擇。本文的使用限制所有命令均為待驗(yàn)證本文寫(xiě)作環(huán)境沒(méi)有可用的 docker 環(huán)境文中每條命令都沒(méi)有實(shí)際運(yùn)行過(guò)參數(shù)寫(xiě)法與默認(rèn)行為請(qǐng)以各自官方文檔為準(zhǔn)。本文不寫(xiě)任何命令的輸出文本kill -l只作為列出信號(hào)名的動(dòng)作出現(xiàn)本文不列它列出的內(nèi)容也不列任何信號(hào)編號(hào)對(duì)照表。本文不給可照抄的停止示范不寫(xiě)怎么強(qiáng)制結(jié)束進(jìn)程不寫(xiě)進(jìn)程組歸屬怎么改。其它層不在本文范圍容器的資源限制與內(nèi)存那一層另有專文本文只講信號(hào)與時(shí)序。把這一層的判斷順序整理成一頁(yè)放在資料里和本章的自檢表呼應(yīng)配套資料把分流、看配置、別重按三步和上面這張自檢表合成一頁(yè)放在資料包里掃碼即可獲取附表 A本文引用事實(shí)與官方出處對(duì)照表#事實(shí)照口徑一手出處 URL核驗(yàn)日期本文位置1官方原文When Bash is interactive, in the absence of any traps, it ignores SIGTERM (so that ‘kill 0’ does not kill an interactive shell), and catches and handles SIGINT (so that the wait builtin is interruptible). When Bash receives a SIGINT, it breaks out of any executing loops. In all cases, Bash ignores SIGQUIT.https://www.gnu.org/software/bash/manual/html_node/Signals.html2026-09-27第 2、5 章2官方原文the shell receives keyboard-generated signals such as SIGINT (usually generated by ‘^C’) that users commonly intend to send to that command. This happens because the shell and the command are in the same process group as the terminal, and ‘^C’ sends SIGINT to all processes in that process group.https://www.gnu.org/software/bash/manual/html_node/Signals.html2026-09-27第 3 章3官方原文the shell does not receive keyboard-generated signals, because it is not in the same process group as the terminal.https://www.gnu.org/software/bash/manual/html_node/Signals.html2026-09-27第 3 章4官方原文If the command terminates due to the SIGINT, Bash concludes that the user meant to send the SIGINT to the shell as well, and acts on the SIGINThttps://www.gnu.org/software/bash/manual/html_node/Signals.html2026-09-27第 4 章5官方原文If the command does not terminate due to SIGINT, the program handled the SIGINT itself and did not treat it as a fatal signal. In that case, Bash does not treat SIGINT as a fatal signal, either…官方在本句后舉的例子是編輯器把 SIGINT 當(dāng)作普通操作例如中止一條編輯命令https://www.gnu.org/software/bash/manual/html_node/Signals.html2026-09-27第 4 章6官方原文The shell exits by default upon receipt of a SIGHUP. Before exiting, an interactive shell resends the SIGHUP to all jobs, running or stopped.要讓某個(gè)作業(yè)不收到它可用 disown 把該作業(yè)從作業(yè)表里移出https://www.gnu.org/software/bash/manual/html_node/Signals.html2026-09-27第 5 章7官方原文The main process inside the container will receive SIGTERM, and after a grace period, SIGKILL. The first signal can be changed with the STOPSIGNAL instruction in the container’s Dockerfile, or the --stop-signal option to docker run and docker create.https://docs.docker.com/reference/cli/docker/container/stop/2026-09-27第 6 章8官方原文If no default is configured for the container, the Daemon determines the default, and is 10 seconds for Linux containers, and 30 seconds for Windows containers.https://docs.docker.com/reference/cli/docker/container/stop/2026-09-27第 6 章9官方原文If the container does not exit after the timeout elapses, it’s forcibly killed with a SIGKILL signal.https://docs.docker.com/reference/cli/docker/container/stop/2026-09-27第 6 章10官方對(duì)--signal的說(shuō)明Signal to send to the container對(duì)--timeout/-t的說(shuō)明Seconds to wait before killing the containerhttps://docs.docker.com/reference/cli/docker/container/stop/2026-09-27第 6 章11官方原文If you set --timeout to -1, no timeout is applied, and the daemon waits indefinitely for the container to exit.https://docs.docker.com/reference/cli/docker/container/stop/2026-09-27第 6 章說(shuō)明第 1–6 行取自 Bash 官方手冊(cè) 3.7.6 Signals 一節(jié)第 7–11 行取自 Docker CLI 對(duì)docker container stop的參考頁(yè)均由本批次于2026-09-27一手核驗(yàn)。本文所有命令均未實(shí)測(cè)已在正文逐處標(biāo)注代碼待驗(yàn)證本文不列任何信號(hào)編號(hào)對(duì)照表。附表 B術(shù)語(yǔ)速查表術(shù)語(yǔ)一句話解釋控制層本文的觀察對(duì)象你怎么把一件事停下來(lái)以及停下來(lái)這個(gè)動(dòng)作發(fā)給了誰(shuí)信號(hào)終端或 shell 發(fā)出去的一個(gè)通知按鍵不等于停止只是把通知寄出去SIGINT中斷組合鍵產(chǎn)出的那個(gè)信號(hào)官方措辭是usually generated by ^CSIGTERM容器停止時(shí)默認(rèn)先發(fā)給主進(jìn)程的那個(gè)信號(hào)交互式 shell 對(duì)它是忽略SIGKILL寬限期用完之后才發(fā)出去的那個(gè)信號(hào)屬于強(qiáng)制結(jié)束SIGQUIT交互式 Bash 在任何情況下都忽略的那個(gè)信號(hào)SIGHUPshell 收到后默認(rèn)退出的那個(gè)信號(hào)退出前會(huì)轉(zhuǎn)發(fā)給它帶的所有作業(yè)前臺(tái)命令當(dāng)前正在終端里跑、占著輸入輸出的那條命令進(jìn)程組一組進(jìn)程的集合鍵盤(pán)信號(hào)發(fā)給的是終端那個(gè)進(jìn)程組里的所有進(jìn)程作業(yè)控制啟用后 shell 會(huì)把自己移出終端那個(gè)進(jìn)程組因此收不到鍵盤(pán)信號(hào)兩條判定未啟用作業(yè)控制時(shí)shell 等前臺(tái)命令結(jié)束后做的分岔判斷寬限期容器停止時(shí)留給主進(jìn)程自己收尾的那段時(shí)間主進(jìn)程容器里被指定為主要那一個(gè)的進(jìn)程停止信號(hào)先發(fā)給它STOPSIGNAL鏡像里用來(lái)改寫(xiě)第一封信叫什么名字的那條指令disown把某個(gè)作業(yè)從作業(yè)表里移出使它在 shell 退出時(shí)不被轉(zhuǎn)發(fā)到信號(hào)只讀動(dòng)作本文給出的全部動(dòng)作類型只看不改不啟動(dòng)、不停止、不修改代碼待驗(yàn)證本文命令未在本機(jī)實(shí)測(cè)的標(biāo)記請(qǐng)以官方文檔為準(zhǔn)寫(xiě)在最后這篇用到的資料寫(xiě)這篇文章時(shí)我把 Bash 官方手冊(cè)講信號(hào)的那一節(jié)和 Docker 官方講容器停止的那一頁(yè)對(duì)照著讀了一遍。發(fā)現(xiàn)停不下來(lái)這件事官方其實(shí)拆成了三段信號(hào)發(fā)給誰(shuí)、誰(shuí)收到之后怎么處理、寬限期里到底在等什么。這三段散在兩份文檔里于是順手整理了幾份配套的東西靶場(chǎng)環(huán)境對(duì)照表DVWA、upload-labs 在 Windows / macOS / Linux 三平臺(tái)的可行性與推薦路徑Web 安全學(xué)習(xí)路線圖從基礎(chǔ)打牢到安全管理四個(gè)階段各學(xué)什么常用靶場(chǎng)清單每個(gè)靶場(chǎng)練什么、適合哪個(gè)階段資料是我自己整理的放在下面這個(gè)碼上掃碼即可獲取添加時(shí)備注「靶場(chǎng)」優(yōu)先通過(guò)。拿到之后建議先看環(huán)境對(duì)照表那一份先把這臺(tái)機(jī)器上還有哪些東西在等著你這件事想清楚再回頭看你的容器有沒(méi)有自己的默認(rèn)值——控制這一層的問(wèn)題多數(shù)是在這里定下來(lái)的。