文章目錄
- 簡介
- 使用kill來殺死程序
- kill的深入用法
- 僵屍程序和kill
- java thread dump
- 總結
和很多程式員打過交道,這些程式員可能熟知for周遊的好幾種寫法,但是卻對寫出來的程式部署的環境一無所知。我敢打賭,在spring boot出現之後,已經很少有程式員知道tomcat到底是怎麼運作的了。對于他們來說,運作一個jar包就完事了。
工具的先進性确實帶給我們很多便利,也提升了程式員的開發效率,同時也降低了程式員的進入門檻。今天想和大家一起讨論一下,linux中的kill指令到底是做什麼用的。
可能很很多小夥伴第一次接觸kill指令是同僚告訴他,把程序kill掉。那麼kill真的是用來殺程序的嗎?
先來看一個kill最基本,也是最常見的應用就是殺死程序。在殺死程序之前,我們需要找到這個程序ID。
一般情況下是使用ps指令找到這個程序ID。加入這個程序ID=54321。
那麼接下來就可以使用kill 54321來殺死這個程序了。
更資深一點的同學,可能還會使用kill -9 54321來強制殺死這個程序。
有沒有更深入的用法呢?有的,一起來看看。
先看一下kill的指令參數到底有那些:
kill
kill: usage: kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l [sigspec]
可以看到kill的參數是sig,也就是信号。也就是說kill的本質是向程式傳遞信号的。
如果使用 kill -l ,我們可以得到到底kill可以傳遞多少信号:
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
總共64個信号,可能不同的kill版本,信号有所不同,但是基本上都覆寫了常用的信号。
下面是一些常用信号的含義:
HUP 1 終端斷線
INT 2 中斷(同 Ctrl + C)
QUIT 3 退出(同 Ctrl + \)
TERM 15 終止
KILL 9 強制終止
CONT 18 繼續(與STOP相反, fg/bg指令)
STOP 19 暫停(同 Ctrl + Z)
怎麼看kill的版本呢?
/bin/kill --version
kill from util-linux 2.23.2
如果kill不傳sig,那麼将會傳預設的sig=TERM,也就是15。是以上面的kill 54321和 kill -15 54321是等價的。
一般情況下,我們優先使用SIGTERM信号。這是因為當程式收到了SIGTERM信号之後,會做一些程式的清理操作,或者說是優雅的關閉。
如果傳入kill -9 也就是SIGKILL,那麼應用程式将無法捕捉這個信号,進而導緻程式強制被關閉,有可能會照成一些異常情況,比如資料還沒有儲存,資料傳輸還沒有結束等等。
sig還有一個特殊值叫做0,如果傳入0的話,那麼并不會發送實際的信号,這個隻是做異常檢測用的。
pid就是process id,可以了解為是程序号。除了程序号之外,還可以傳入一些特殊值,比如:
- 0 表示目前程序group的所有程序
- -1 表示所有PID>1的程序
還有一個特殊的pid=1,這個pid表示的是初始程序init,這個程序是不可被殺死的。
除了PID之外,我們看到kill還可以接受jobspec。job id可以使用jobs指令來列出。
上面講到了pid=1的初始程序是不能被kill的。還有一種不能被kill的程序叫做僵屍程序。
僵屍程序是linux程式中一個非常獨特的狀态,它表示的是程序已經結束了,但是又還沒有完全死亡,就像僵屍一樣。
linux中的5大程序狀态分别是:RUNNING:正在運作或等待運作狀态,UNINTERRUPTABLE:不可中斷阻塞狀态,INTERRUPTABLE:可中斷阻塞狀态,STOPPED:挂起狀态和ZOMBIE:僵屍狀态。
那麼什麼是僵屍程序呢?
僵屍程序指的是程式在退出之後,該程序并不是馬上消失的,而是會保留一個被稱為僵屍的資料結構。這個資料結構很特殊,因為其沒有記憶體空間,沒有可執行的代碼,當然也不可以被排程。它隻是在程序清單中占有一個位置,記錄了該程序退出時候的各種資訊。
僵屍程序主要是保留程序退出的現場,供父程序或者系統管理者進行分析使用的,是以僵屍程序是交由父程序來進行收集和釋放的。因為僵屍程序已經退出了,是以使用kill是沒有用的,隻能等待其父程序退出,才能真正的退出。
怎麼檢視僵屍程序呢?最簡單的方法就是使用top指令:
top - 14:34:38 up 305 days, 4:23, 2 users, load average: 0.20, 0.29, 0.47
Tasks: 93 total, 1 running, 92 sleeping, 0 stopped, 0 zombie
%Cpu(s): 2.0 us, 0.7 sy, 0.0 ni, 97.3 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 1882008 total, 525524 free, 311440 used, 1045044 buff/cache
KiB Swap: 0 total, 0 free, 0 used. 1382560 avail Mem
上面的輸出,我們可以看到裡面有0個zombie。
kill還有一個非常有用的地方就是生成java程式的thread dump,将目前java程式的線程資訊dump出來,可以進行一些有用的分析,比如死鎖分析等。
怎麼對java程序做thread dump呢?很簡單使用kill -3 指令即可:
kill -3 <pid>
從上面我們的介紹可以指定3代表的信号是SIGQUIT。這說明JVM内置了這個信号的捕捉,如果接收到了這個信号,則會dump目前的線程資訊。
java thread dump在對java進行線程分析的時候非常有用。
本文介紹了kill的深入用法和底層的工作原理,還介紹了kill的幾個應用,希望下次有人再問你kill到底是什麼的時候,大家都可以很自豪的告訴他!