信號(hào)
信號(hào)是UNIX、類UNIX,以及其他POSIX兼容的操作系統(tǒng)中進(jìn)程間通信的一種有限制的方式。
它是一種異步的通知機(jī)制,用來(lái)提醒進(jìn)程一個(gè)事件(硬件異常、程序執(zhí)行異常、外部發(fā)出信號(hào))已經(jīng)發(fā)生。當(dāng)一個(gè)信號(hào)發(fā)送給一個(gè)進(jìn)程時(shí),操作系統(tǒng)中斷了進(jìn)程正常的控制流程。此時(shí),任何非原子操作都將被中斷。如果進(jìn)程定義了信號(hào)的處理函數(shù),那么它將被執(zhí)行,否則執(zhí)行默認(rèn)的處理函數(shù)。
查看信號(hào)
kill -l 查看
~ kill -l
HUP INT QUIT ILL TRAP ABRT BUS FPE KILL USR1 SEGV USR2 PIPE ALRM TERM 16 CHLD CONT STOP
TSTP TTIN TTOU URG XCPU XFSZ VTALRM PROF WINCH POLL 30 SYS
常用信號(hào)
| 命令 | 信號(hào) | 含義 |
|---|---|---|
| ctrl+c | SIGINT | 當(dāng)用戶鍵入終端中斷字符(如:Ctrl + C)終端驅(qū)動(dòng)程序?qū)l(fā)送該信號(hào)給前臺(tái)進(jìn)程組。該信號(hào)默認(rèn)行為是終止進(jìn)程 |
| ctrl+z | SIGTSTP | 作業(yè)控制的停止信號(hào),當(dāng)用戶在鍵盤輸入掛起字符(如:Ctrl+Z)時(shí),將發(fā)送該信號(hào)給前臺(tái)進(jìn)程組,使其停止運(yùn)行(該信號(hào)可以被處理和忽略) |
| ctrl+/ | SIGQUIT | 當(dāng)用戶在鍵盤鍵入退出字符(如Ctrl+\)時(shí),該信號(hào)將發(fā)往前臺(tái)進(jìn)程組。默認(rèn)情況下,該信號(hào)終止進(jìn)程,并生成可用于調(diào)試的核心轉(zhuǎn)儲(chǔ)文件。當(dāng)進(jìn)程陷入無(wú)限循環(huán)或者不在響應(yīng),使用該信號(hào)很合適 |
| SIGTERM | 這是用來(lái)終止進(jìn)程的標(biāo)準(zhǔn)信號(hào),也是kill和killall命令所發(fā)送的默認(rèn)信號(hào)。用戶經(jīng)常會(huì)使用kil -9顯示向進(jìn)程發(fā)送SIGKILL信號(hào),然而這一做法通常是錯(cuò)誤的。精心設(shè)計(jì)的應(yīng)用程序應(yīng)當(dāng)為SIGTERM信號(hào)設(shè)置處理器程序,以便于其能夠預(yù)先清理臨時(shí)文件和釋放資源,做到全身而退。發(fā)送SIGKILL信號(hào)可以殺掉某個(gè)進(jìn)程,從而繞開了SIGTERM的信號(hào)處理程序。因此,總是應(yīng)該首先嘗試使用SIGTERM信號(hào)來(lái)終止進(jìn)程,而把SIGKILL信號(hào)作為最后手段,去對(duì)付那些失控的進(jìn)程 | |
| SIGKILL | 此信號(hào)為必殺信號(hào),處理器程序無(wú)法阻塞、忽略或者捕獲,故而總能殺死進(jìn)程(僵尸進(jìn)程除外) | |
| SIGHUP | 當(dāng)終端斷開時(shí),將發(fā)送該信號(hào)給終端控制進(jìn)程。SIGHUP信號(hào)還可用于守護(hù)進(jìn)程 |
重啟流程
1.替換可執(zhí)行文件或修改配置文件
2.發(fā)送信號(hào)量SIGHUP
3.拒絕新連接求情舊進(jìn)程,并保證正在處理的連接正常
4.啟動(dòng)新的子進(jìn)程
5.新的子進(jìn)程開始處理新的請(qǐng)求
6.舊的進(jìn)程處理完舊連接后正常退出
package main
import (
"context"
"fmt"
"net/http"
"os"
"os/signal"
"syscall"
"time"
)
func main() {
s := http.Server{
Addr: ":8080",
Handler: nil,
ReadTimeout: 60,
WriteTimeout: 60,
MaxHeaderBytes: 1 << 20,
}
go func() {
if err := s.ListenAndServe(); err != nil && err != http.ErrServerClosed {
fmt.Printf("http.ListenAndServe err:%v", err)
}
}()
//監(jiān)聽信號(hào)
quit := make(chan os.Signal)
//監(jiān)聽 SIGINT 和 SIGTERM
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<- quit
fmt.Printf("Server quiting....")
//設(shè)置關(guān)閉后程序剩余多長(zhǎng)時(shí)間處理原有的請(qǐng)求
ctx, cancelFunc := context.WithTimeout(context.Background(), 5 * time.Second)
defer cancelFunc()
if err := s.Shutdown(ctx); err != nil {
fmt.Printf("s.Shutdown(ctx) err:%v", err)
}
fmt.Printf("Server Shutdown....")
}
上面啟動(dòng)后,按ctrl+c可看到執(zhí)行結(jié)果