關于kill -0 pid的作用詳解
在服務器運維以及程序開發過程中,經常會用到kill命令或者kill()方法。那么,kill是做什么以及信號0的作用又是什么,一起來探尋吧。
kill可以使用的信號
- [root@localhost ~]# 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
注意:
下面內容常作為面試題:前31個信號和后31個信號的區別?
在Linux上執行kill -l看到可使用信號共有62個(仔細看沒有32、33哦)。
- 編號為1 ~ 31的信號為傳統UNIX支持的信號,是不可靠信號(非實時的)
- 編號為34 ~ 64的信號是后來擴充的,稱做可靠信號(實時信號)
不可靠信號、可靠信號區別:前者不支持排隊,可能會造成信號丟失,而后者不會。
kill的文檔描述
通過man命令可以看到關于kill指令的描述以及參數解釋,這里截取部分描述,如下:
- [root@localhost ~]# man 1 kill
- KILL(1) User Commands KILL(1)
- NAME
- kill - terminate a process
- SYNOPSIS
- kill [-s signal|-p] [-q sigval] [-a] [--] pid...
- kill -l [signal]
- DESCRIPTION
- The command kill sends the specified signal to the specified process or process group. If no signal is specified, the TERM signal is sent. The TERM signal
- will kill processes which do not catch this signal. For other processes, it may be necessary to use the KILL (9) signal, since this signal cannot be caught.
- Most modern shells have a builtin kill function, with a usage rather similar to that of the command described here. The '-a' and '-p' options, and the possi‐
- bility to specify processes by command name are a local extension.
- If sig is 0, then no signal is sent, but error checking is still performed.
- ......
- # [root@localhost ~]# man 2 kill
- KILL(2) Linux Programmer's Manual KILL(2)
- NAME
- kill - send signal to a process
- SYNOPSIS
- #include <sys/types.h>
- #include <signal.h>
- int kill(pid_t pid, int sig);
- Feature Test Macro Requirements for glibc (see feature_test_macros(7)):
- kill(): _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _POSIX_SOURCE
- DESCRIPTION
- The kill() system call can be used to send any signal to any process group or process.
- If pid is positive, then signal sig is sent to the process with the ID specified by pid.
- If pid equals 0, then sig is sent to every process in the process group of the calling process.
- If pid equals -1, then sig is sent to every process for which the calling process has permission to send signals, except for process 1 (init), but see below.
- If pid is less than -1, then sig is sent to every process in the process group whose ID is -pid.
- If sig is 0, then no signal is sent, but error checking is still performed; this can be used to check for the existence of a process ID or process group ID.
- For a process to have permission to send a signal it must either be privileged (under Linux: have the CAP_KILL capability), or the real or effective user ID of
- the sending process must equal the real or saved set-user-ID of the target process. In the case of SIGCONT it suffices when the sending and receiving processes
- belong to the same session.
從描述可知,無論是man 1文檔還是man 2文檔都指出:kill命令用于向指定的pid進程發送信號,進程在接收到對應的信號之后會進行對應的操作。
關于信號0的作用
man 1 文檔中有一句 If sig is 0, then no signal is sent, but error checking is still performed, 意思是:如果sig為0,則不發送信號,但仍然進行錯誤檢查。
man 2 文檔中有一句 If sig is 0, then no signal is sent, but error checking is still performed; this can be used to check for the existence of a process ID or process group ID,意思是:如果sig為0,則不發送信號,但仍然進行錯誤檢查; 這可以用來檢查是否存在進程ID或進程組ID。
也就是說,kill -0 pid 執行時不會發送信號,但是會對pid對應進程做錯誤檢查。如果返回0則進程、服務正在運行中;反之是其他值,則進程死了或者服務已停止。
信號0的用法
既然,信號kill -0 pid不發送信號,主要用于檢查對應進程做錯誤檢查。那么,在開發中我們就可以通過kill返回的錯誤信息來判斷進程是否存在、正常運行。
shell腳本中示例:
- #!/bin/bash
- PIDFILE=$1
- if [ -f $PIDFILE ]; then
- PID="$(cat $PIDFILE)"
- if kill -0 "$PID" &> /dev/null; then
- echo "process is exists"
- exit 0
- else
- echo "process is not exists"
- exit 5
- fi
- fi
Go代碼中示例:
- func processExists(pid int) bool {
- if err := syscall.Kill(pid, 0); err == nil {
- return true
- } else {
- return false
- }
- }
【編輯推薦】