成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

如何優(yōu)雅的關(guān)閉容器,看本文就夠了

系統(tǒng) Linux
要說(shuō)如何優(yōu)雅的關(guān)閉容器,那就不得不提到信號(hào)(Signal)的理念,以及 Dockerfile 中 ENTRYPOINT 和 CMD 指令了。在具體說(shuō)優(yōu)雅關(guān)閉之前,先了解一下信號(hào)這個(gè) Linux 中的基礎(chǔ)概念。

 最近把 Docker 官方的 Docker Reference 文檔又讀了一遍,發(fā)現(xiàn)有些細(xì)節(jié)深究起來(lái),還是有很多可挖的。針對(duì)寫(xiě) Dockerfile ,大部分時(shí)候只要照葫蘆畫(huà)瓢,基本也不會(huì)有什么大的問(wèn)題,但是如果再深入理解一下那就更有意思了。

[[438741]]

要說(shuō)如何優(yōu)雅的關(guān)閉容器,那就不得不提到信號(hào)(Signal)的理念,以及 Dockerfile 中 ENTRYPOINT 和 CMD 指令了。在具體說(shuō)優(yōu)雅關(guān)閉之前,先了解一下信號(hào)這個(gè) Linux 中的基礎(chǔ)概念。

1 信號(hào)

信號(hào)是事件發(fā)生時(shí)對(duì)進(jìn)程的通知機(jī)制,有時(shí)也稱之為軟件中斷。

信號(hào)有不同的類型,Linux 對(duì)標(biāo)準(zhǔn)信號(hào)的編號(hào)為 1~31,可以通過(guò) kill -l 獲取信號(hào)名稱: 

  1. # kill -l  
  2.  1) SIGHUP       2) SIGINT       3) SIGQUIT     
  3.  4) SIGILL       5) SIGTRAP      6) SIGABRT    
  4.  7) SIGBUS       8) SIGFPE       9) SIGKILL 
  5.  10) SIGUSR1    11) SIGSEGV     12) SIGUSR2 
  6.  13) SIGPIPE    14) SIGALRM     15) SIGTERM 
  7. ... ... 

實(shí)際列出的信號(hào)超過(guò)了 31 個(gè),有些是其它名稱的同義詞,有些則是定義但未使用的。以下介紹幾個(gè)常用的信號(hào):

  •  1) SIGHUP 當(dāng)終端斷開(kāi)(掛機(jī))時(shí),將發(fā)送該信號(hào)給終端控制進(jìn)程。SIGHUP 信號(hào)還可用于守護(hù)進(jìn)程(比如,init 等)。許多守護(hù)進(jìn)程會(huì)在收到 SIGHUP 信號(hào)時(shí)重新進(jìn)行初始化并重讀配置文件。
  •  2) SIGINT 當(dāng)用戶鍵入終端中斷字符(通常為 Control-C ) 時(shí),終端驅(qū)動(dòng)程序?qū)l(fā)送該信號(hào)給前臺(tái)進(jìn)程組。該信號(hào)的默認(rèn)行為是終止進(jìn)程。
  •  3) SIGQUIT 當(dāng)用戶在鍵盤(pán)上鍵入退出字符(通常為 Control-\ )時(shí),該信號(hào)將發(fā)往前臺(tái)進(jìn)程組。默認(rèn)情況下,該信號(hào)終止進(jìn)程,并生成用于調(diào)試的核心轉(zhuǎn)儲(chǔ)文件。進(jìn)程如果陷入無(wú)限循環(huán),或者不再響應(yīng)時(shí),使用 SIGQUIT 信號(hào)就很合適。
  •  9) SIGKILL 此信號(hào)為 “必殺(sure kill)” 信號(hào),處理器程序無(wú)法將其阻塞、忽略或者捕獲,故而 “一擊必殺”,總能終止程序。
  •  15) SIGTERM 這是用來(lái)終止進(jìn)程的標(biāo)準(zhǔn)信號(hào),也是 kill 、 killall 、 pkill 命令所發(fā)送的默認(rèn)信號(hào)。精心設(shè)計(jì)的應(yīng)用程序應(yīng)當(dāng)為 SIGTERM 信號(hào)設(shè)置處理器程序,以便其能夠預(yù)先清除臨時(shí)文件和釋放其它資源,從而全身而退。因此,總是應(yīng)該先嘗試使用 SIGTERM 信號(hào)來(lái)終止進(jìn)程,而把 SIGKILL 作為最后手段,去對(duì)付那些不響應(yīng) SIGTERM 信號(hào)的失控進(jìn)程。
  •  20) SIGTSTP 這是作業(yè)控制的停止信號(hào),當(dāng)用戶在鍵盤(pán)上輸入掛起字符(通常為 Control-Z )時(shí),將該信號(hào)給前臺(tái)進(jìn)程組,使其停止運(yùn)行。

值得注意的是, Control-D 不會(huì)發(fā)起信號(hào),它表示 EOF(End-Of-File),關(guān)閉標(biāo)準(zhǔn)輸入(stdin)管道(比如可以通過(guò) Control-D 退出當(dāng)前 shell)。如果程序不讀取當(dāng)前輸入的話,是不受 Control-D 影響的。

程序可以針對(duì)信號(hào)捕捉,然后執(zhí)行相應(yīng)函數(shù):

 

以上知識(shí)大部分都來(lái)自 《Linux/UNIX 系統(tǒng)編程手冊(cè)》,想要了解更多的,可以查看該書(shū)上冊(cè)的 20、21、22 章節(jié)。

2 ENTRYPOINT 、 CMD

可能有人會(huì)問(wèn),說(shuō)了半天,那信號(hào)和優(yōu)雅的關(guān)閉容器有半毛錢(qián)的關(guān)系啊?話說(shuō),這和錢(qián)確實(shí)沒(méi)關(guān)系,但是和如何優(yōu)雅關(guān)閉容器卻關(guān)系密切。

接著說(shuō) Dockerfile 中的 ENTRYPOINT 和 CMD 指令,它們的主要功能是指定容器啟動(dòng)時(shí)執(zhí)行的程序。

CMD 有三種格式:

  •  CMD ["executable","param1","param2"] (exec 格式, 推薦使用這種格式)
  •  CMD ["param1","param2"] (作為 ENTRYPOINT 指令參數(shù))
  •  CMD command param1 param2 (shell 格式,默認(rèn) /bin/sh -c )

ENTRYPOINT 有兩種格式:

  •  ENTRYPOINT ["executable", "param1", "param2"] (exec 格式,推薦優(yōu)先使用這種格式)
  •  ENTRYPOINT command param1 param2 (shell 格式)

其中,不管你 Dockerfile 用其中哪個(gè)指令,兩個(gè)指令都推薦使用 exec 格式,而不是 shell 格式。原因就是因?yàn)槭褂?shell 格式之后,程序會(huì)以 /bin/sh -c 的子命令啟動(dòng),并且 shell 格式下不會(huì)傳遞任何信號(hào)給程序。這也就導(dǎo)致,在 docker stop 容器的時(shí)候,以這種格式運(yùn)行的程序捕捉不到發(fā)送的信號(hào),也就談不上優(yōu)雅的關(guān)閉了。 

  1. ➜  ~ docker stop --help  
  2. Usage:  docker stop [OPTIONS] CONTAINER [CONTAINER...]  
  3. Stop one or more running containers  
  4. Options:  
  5.       --help       Print usage  
  6.   -t, --time int   Seconds to wait for stop before killing it (default 10) 

docker stop 停掉容器的時(shí)候,默認(rèn)會(huì)發(fā)送一個(gè) SIGTERM 的信號(hào),默認(rèn) 10s 后容器沒(méi)有停止的話,就 SIGKILL 強(qiáng)制停止容器。通過(guò) -t 選項(xiàng)可以設(shè)置等待時(shí)間。 

  1. ➜  ~ docker kill --help  
  2. Usage:  docker kill [OPTIONS] CONTAINER [CONTAINER...]  
  3. Kill one or more running containers  
  4. Options:  
  5.       --help            Print usage  
  6.   -s, --signal string   Signal to send to the container (default "KILL") 

通過(guò) docker kill 的 -s 選項(xiàng)還可以指定給容器發(fā)送的信號(hào)。

所以,說(shuō)了那么多,只要 Dockerfile 中通過(guò) exec 格式執(zhí)行容器啟動(dòng)命令就相安無(wú)事了?那當(dāng)然是,沒(méi)有那么簡(jiǎn)單的了,接下來(lái)我們通過(guò)實(shí)例來(lái)看看具體的效果是怎么樣的。

3 實(shí)例

通過(guò) Go 寫(xiě)一個(gè)簡(jiǎn)單的信號(hào)處理器: 

  1. ➜  ~ cat signals.go  
  2. package main  
  3. import ( 
  4.     "fmt"  
  5.     "os"  
  6.     "os/signal"  
  7.     "syscall"  
  8. func main() {  
  9.     sigs :make(chan os.Signal, 1)  
  10.     done :make(chan bool, 1)  
  11.     signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)  
  12.     go func() {  
  13.         sig :<-sigs  
  14.         fmt.Println()  
  15.         fmt.Println(sig)  
  16.         done <- true  
  17.     }()  
  18.     fmt.Println("awaiting signal")  
  19.     <-done  
  20.     fmt.Println("exiting")  

3.1 實(shí)例 1 

  1. ➜  ~ GOOS=linux GOARCH=amd64 go build signals.go  
  2. ➜  ~ ls  
  3. Dockerfile signals    signals.go  
  4. ➜  ~ cat Dockerfile  
  5. FROM busybox  
  6. COPY signals /signals  
  7. CMD ["/signals"]    # exec 格式執(zhí)行  
  8. ➜  ~ docker build -t signals . 

通過(guò) tmux 開(kāi)啟兩個(gè)面板,一個(gè)運(yùn)行容器,一個(gè)執(zhí)行 docker stop : 

  1. ➜  ~ docker run -it --rm --name signals signals  
  2. awaiting signal  
  3. terminated  
  4. exiting  
  1. ➜  ~ time docker stop signals  
  2. signals  
  3. docker stop signals  0.01s user 0.02s system 4% cpu 0.732 total 
  4. ➜  ~ 

可以發(fā)現(xiàn),容器停止之前,程序接收到信號(hào)并輸出相應(yīng)信息,并且停止總耗時(shí)為 0.732 s,達(dá)到了優(yōu)雅的效果。

修改 Dockerfile 中 CMD 執(zhí)行格式,執(zhí)行相同操作: 

  1. ➜  ~ cat Dockerfile  
  2. FROM busybox  
  3. COPY signals /signals  
  4. CMD /signals        # shell 格式執(zhí)行  
  5. ➜  ~ docker build -t signals .  
  1. ➜  ~ docker run -it --rm --name signals signals  
  2. awaiting signal  
  3. ➜  ~  
  1. ➜  ~ time docker stop signals  
  2. signals  
  3. docker stop signals  0.01s user 0.01s system 0% cpu 10.719 total 

通過(guò) shell 格式之后,可以發(fā)現(xiàn)容器停止之前,程序并未接收到任何信號(hào),并且停止時(shí)間為 10.719s,說(shuō)明該容器是被強(qiáng)制停止的。

結(jié)論很明顯,為了優(yōu)雅的退出容器,我們應(yīng)該采用 exec 這種格式。

3.2 實(shí)例 2

通過(guò)實(shí)例 1 我們都會(huì)在 Dockerfile 中都會(huì)通過(guò) exec 這種格式來(lái)執(zhí)行程序了,那如果執(zhí)行的程序本身也是一個(gè) shell 腳本呢? 

  1. ➜  ~ ls  
  2. Dockerfile signals    signals.go start.sh  
  3. ➜  ~ cat Dockerfile  
  4. FROM busybox  
  5. COPY signals /signals  
  6. COPY start.sh /start.sh     # 引入 shell 腳本啟動(dòng)  
  7. CMD ["/start.sh"]  
  8. ➜  ~ cat start.sh  
  9. #!/bin/sh  
  10. /signals  
  11. ➜  ~ 

測(cè)試依然引用實(shí)例 1 中的方法: 

  1. ➜  ~ docker run -it --rm --name signals signals  
  2. awaiting signal  
  3. ➜  ~  
  1. ➜  ~ time docker stop signals  
  2. signals  
  3. docker stop signals  0.01s user 0.02s system 0% cpu 10.765 total  
  4. ➜  ~ 

可以發(fā)現(xiàn),即使 Dockerfile 中的 CMD 指令使用的是 exec 格式,容器中的程序依然沒(méi)有接收到信號(hào),最后被強(qiáng)制關(guān)閉。因?yàn)?shell 腳本中執(zhí)行的原因,導(dǎo)致信號(hào)依然沒(méi)有被傳遞,我們需要針對(duì) shell 腳本做一些改造: 

  1. ➜  ~ cat start.sh  
  2. #!/bin/sh 
  3. exec /signals   # 加入 exec 執(zhí)行  
  4. ➜  ~ docker build -t signals .  
  1. ➜  ~ docker run -it --rm --name signals signals  
  2. awaiting signal  
  3. terminated  
  4. exiting  
  1. ➜  ~ time docker stop signals  
  2. signals  
  3. docker stop signals  0.02s user 0.02s system 4% cpu 0.744 total  
  4. ➜  ~ 

可以看到,加入 exec 命令之后,程序又可以接收到信號(hào)正常退出了。當(dāng)然,如果你 Dockerfile 中的 CMD 是以 shell 格式運(yùn)行的,即使啟動(dòng)腳本中加入 exec 也是無(wú)效的。再者,如果你的程序本身不能針對(duì)信號(hào)做一些處理,也就談不上優(yōu)雅關(guān)閉了。 

 

責(zé)任編輯:龐桂玉 來(lái)源: Linux公社
相關(guān)推薦

2020-02-24 19:28:23

Rust語(yǔ)言Web框架應(yīng)用領(lǐng)域

2020-12-11 08:04:01

腳本動(dòng)態(tài) Async

2021-01-19 10:35:49

JVM場(chǎng)景函數(shù)

2019-10-09 10:06:48

容器監(jiān)控軟件

2022-04-11 08:17:07

JVMJava進(jìn)程

2021-03-28 09:17:18

JVM場(chǎng)景鉤子函數(shù)

2018-09-12 15:16:19

數(shù)據(jù)中心網(wǎng)絡(luò)機(jī)房

2017-12-19 10:03:44

JavaLinux代碼

2024-11-13 16:37:00

Java線程池

2018-08-17 09:14:43

餓了么容器演進(jìn)

2023-11-22 07:54:33

Xargs命令Linux

2024-02-04 09:08:00

Autofac容器.NET

2022-03-13 09:31:43

MQ消息隊(duì)列ActiveMQ

2019-08-16 09:41:56

UDP協(xié)議TCP

2021-09-30 07:59:06

zookeeper一致性算法CAP

2025-02-14 08:53:24

2021-04-24 23:06:47

JavaScript編程語(yǔ)言

2017-10-23 11:56:35

路由器升級(jí)更新

2023-10-17 08:15:28

API前后端分離

2022-09-07 09:19:49

Docker健康檢查
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 精品一区二区久久久久久久网精 | 九九久久精品 | 欧美在线激情 | 91精品国产一区二区三区 | 天天躁日日躁xxxxaaaa | 婷婷丁香在线视频 | 男女免费在线观看视频 | 久久久久久久久蜜桃 | 久久亚洲一区二区三区四区 | 亚洲三区视频 | 亚洲欧洲综合av | 日韩欧美在线视频一区 | 国产精品黄视频 | 美女在线观看国产 | 亚洲精品久久久久久一区二区 | 成人影院在线视频 | 免费亚洲一区二区 | 久久久久久久国产精品 | 午夜激情国产 | 久久久免费在线观看 | 亚州午夜精品 | 中文字幕av一区 | 福利国产 | 欧美啪啪| 亚洲福利一区 | 草久在线 | 成人在线免费视频 | 国产日韩欧美一区 | 国产精品久久久久久久久久久免费看 | 久久只有精品 | 久久精品中文字幕 | 国产高清一二三区 | 性国产xxxx乳高跟 | 九九热在线视频免费观看 | 日产久久| 伊人超碰 | 欧美综合国产精品久久丁香 | 欧美成人精品一区二区三区 | 一本大道久久a久久精二百 欧洲一区二区三区 | 午夜久久 | 欧美成人激情 |