kill命令概述

通过man kill查看文档说明

  • kill命令将指定的信号发送到指定的进程或进程组。
  • 如果未指定信号,则默认的发送信号为TERM,当该进程未处理TERM信号时,该信号将杀死该进程。
  • 如果发送的信号为0,则不发送信号,但仍会执行错误检查。

linux信号列表

[root@test-master temp]# kill -l
 1) SIGHUP	 2) SIGINT	 3) SIGQUIT	 4) SIGILL	 5) SIGTRAP
 6) SIGABRT	 7) SIGBUS	 8) SIGFPE	 9) SIGKILL	10) SIGUSR1
11) SIGSEGV	12) SIGUSR2	13) SIGPIPE	14) SIGALRM	15) SIGTERM
16) SIGSTKFLT	17) SIGCHLD	18) SIGCONT	19) SIGSTOP	20) SIGTSTP
21) SIGTTIN	22) SIGTTOU	23) SIGURG	24) SIGXCPU	25) SIGXFSZ
26) SIGVTALRM	27) SIGPROF	28) SIGWINCH	29) SIGIO	30) SIGPWR
31) SIGSYS	34) SIGRTMIN	35) SIGRTMIN+1	36) SIGRTMIN+2	37) SIGRTMIN+3
38) SIGRTMIN+4	39) SIGRTMIN+5	40) SIGRTMIN+6	41) SIGRTMIN+7	42) SIGRTMIN+8
43) SIGRTMIN+9	44) SIGRTMIN+10	45) SIGRTMIN+11	46) SIGRTMIN+12	47) SIGRTMIN+13
48) SIGRTMIN+14	49) SIGRTMIN+15	50) SIGRTMAX-14	51) SIGRTMAX-13	52) SIGRTMAX-12
53) SIGRTMAX-11	54) SIGRTMAX-10	55) SIGRTMAX-9	56) SIGRTMAX-8	57) SIGRTMAX-7
58) SIGRTMAX-6	59) SIGRTMAX-5	60) SIGRTMAX-4	61) SIGRTMAX-3	62) SIGRTMAX-2
63) SIGRTMAX-1	64) SIGRTMAX

支持发送的信号非常多,但是这些信号中只有第 9 种信号(SIGKILL)才可以无条件的终止进程,其他信号进程都有权利忽略。并且这么多的信号中常用的也不多,下面我们解释几个常用信号的含义。

信号详述

  • SIGHUP
    启动被终止的程序,可让该进程重新读取自己的配置文件,类似重新启动。
  • SIGINT
    相当于用键盘输入 [ctrl]-c 来中断一个程序的进行。
  • SIGKILL
    代表强制中断一个程序的进行,如果该程序进行到一半,那么尚未完成的部分可能会有“半产品”产生,类似 vim会有 .filename.swp 保留下来。
  • SIGTERM
    以正常的方式来终止该程序。由于是正常的终止,所以后续的动作会将他完成。不过,如果该程序已经发生问题,就是无法使用正常的方法终止时,输入这个 signal 也是没有用的。该信号为kill命令的默认信号
  • SIGSTOP
    相当于用键盘输入 [ctrl]-z 来暂停一个程序的进行。

测试程序

package main

import (
	"time"
	"os"
	"syscall"
	"os/signal"
)

/**
 * 注意在linux平台下进行测试,如果在mac下进行测试可能不能达到效果
 */
func main() {
	println("begin")
	stop := SetupSignalHandler()
	<-stop
	println("sleep 5s ")
	time.Sleep(time.Duration(5) * time.Second)
	println("end")

}

//var shutdownSignals = []os.Signal{os.Interrupt, syscall.SIGTERM}
var shutdownSignals = []os.Signal{syscall.SIGTERM, syscall.SIGINT}

func SetupSignalHandler() (stopCh <-chan struct{}) {
	//返回值,根据该值,主程序判断是否准备退出
	stop := make(chan struct{})
	c := make(chan os.Signal, 1)
	signal.Notify(c, shutdownSignals...)
	go func() {
		println("准备接收信号")
		s1 := <-c

		println("第一次收到信号:" + s1.String())
		close(stop)
		s2 := <-c
		println("第二次收到信号:" + s2.String())
		os.Exit(1) // second signal. Exit directly.
	}()

	return stop
}