kill 、killall、pkill、xkill pgrep ps 命令解釋

來源:互聯網
上載者:User

終止一個進程或終止一個正在啟動並執行程式,一般是通過 kill 、killall、pkill、xkill 等進行。比如一個程式已經死掉,但又不能退出,這時就應該考慮應用這些工具。

另外應用的場合就是在伺服器管理中,在不涉及資料庫伺服器程式的父進程的停止運行,也可以用這些工具來終止。為什麼資料庫伺服器的父進程不能用這些工具殺死呢?原因很簡單,這些工具在強行終止資料庫伺服器時,會讓資料庫產生更多的檔案片段,當片段達到一定程度的時候,資料庫就有崩潰的危險。比如mysql伺服器最好是按其正常的程式關閉,而不是用pkill mysqld 或killall mysqld 這樣危險的動作;當然對於佔用資源過多的資料庫子進程,我們應該用kill 來殺掉。

1 kill

kill的應用是和ps 或pgrep 命令結合在一起使用的;

kill 的用法:

kill [訊號代碼] 進程ID

註:訊號代碼可以省略;我們常用的訊號代碼是 -9 ,表示強制終止;

舉例:

[root@localhost ~]# ps auxf |grep httpd
root 4939 0.0 0.0 5160 708 pts/3 S+ 13:10 0:00 \_ grep httpd
root 4830 0.1 1.3 24232 10272 ? Ss 13:02 0:00 /usr/sbin/httpd
apache 4833 0.0 0.6 24364 4932 ? S 13:02 0:00 \_ /usr/sbin/httpd
apache 4834 0.0 0.6 24364 4928 ? S 13:02 0:00 \_ /usr/sbin/httpd
apache 4835 0.0 0.6 24364 4928 ? S 13:02 0:00 \_ /usr/sbin/httpd
apache 4836 0.0 0.6 24364 4928 ? S 13:02 0:00 \_ /usr/sbin/httpd
apache 4837 0.0 0.6 24364 4928 ? S 13:02 0:00 \_ /usr/sbin/httpd
apache 4838 0.0 0.6 24364 4928 ? S 13:02 0:00 \_ /usr/sbin/httpd
apache 4839 0.0 0.6 24364 4928 ? S 13:02 0:00 \_ /usr/sbin/httpd
apache 4840 0.0 0.6 24364 4928 ? S 13:02 0:00 \_ /usr/sbin/httpd

我們查看httpd 伺服器的進程;您也可以用pgrep -l httpd 來查看;

我們看上面例子中的第二列,就是進程PID的列,其中4830是httpd伺服器的父進程,從4833-4840的進程都是它4830的子進程;如果我們殺掉父進程4830的話,其下的子進程也會跟著死掉;

[root@localhost ~]# kill 4840 註:殺掉4840這個進程;
[root@localhost ~]# ps -auxf |grep httpd 註:查看一下會有什麼結果?是不是httpd伺服器仍在運行?
[root@localhost ~]# kill 4830 註:殺掉httpd的父進程;
[root@localhost ~]# ps -aux |grep httpd 註:查看httpd的其它子進程是否存在,httpd伺服器是否仍在運行?

對於殭屍進程,可以用kill -9 來強制終止退出;

比如一個程式已經徹底死掉,如果kill 不加訊號強度是沒有辦法退出,最好的辦法就是加訊號強度 -9 ,後面要接殺父進程;比如;

[root@localhost ~]# ps aux |grep gaim
beinan 5031 9.0 2.3 104996 17484 ? S 13:23 0:01 gaim
root 5036 0.0 0.0 5160 724 pts/3 S+ 13:24 0:00 grep gaim

[root@localhost ~]# pgrep -l gaim
5031 gaim
[root@localhost ~]# kill -9 5031


2 killall

killall 通過程式的名字,直接殺死所有進程,咱們簡單說一下就行了。

用法:killall 正在啟動並執行程式名

killall 也和ps或pgrep 結合使用,比較方便;通過ps或pgrep 來查看哪些程式在運行;

舉例:

[root@localhost beinan]# pgrep -l gaim
2979 gaim
[root@localhost beinan]# killall gaim


3 pkill

pkill 和killall 應用方法差不多,也是直接殺死運行中的程式;如果您想殺掉單個進程,請用kill 來殺掉。

應用方法:

#pkill 正在啟動並執行程式名

舉例:

[root@localhost beinan]# pgrep -l gaim
2979 gaim
[root@localhost beinan]# pkill gaim


4 xkill

xkill 是在案頭用的殺死圖形介面的程式。比如當firefox 出現崩潰不能退出時,點滑鼠就能殺死firefox 。當xkill運行時出來和個人腦骨的表徵圖,哪個圖形程式崩潰一點就OK了。如果您想終止xkill ,就按右鍵取消;

xkill 調用方法:

[root@localhost ~]# xkill**************************************pgrep

pgrep 是通過程式的名字來查詢進程的工具,一般是用來判斷程式是否正在運行。在伺服器的配置和管理中,這個工具常被應用,簡單明了;

用法:

#ps 參數選項 程式名

常用參數

-l 列出程式名和進程ID;
-o 進程起始的ID;

ps以前就大約瞭解一點殭屍進程的概念,今天再好好地通過網上資源並實際寫C程式實驗了,現在對殭屍進程總結一下。
1.殭屍進程概念:
殭屍進程(Zombie Process):就是已經結束了的進程,但是沒有從進程表中刪除。太多了會導致進程表裡麵條目滿了,進而導致系統崩潰,倒是不佔用其他系統資源。
Linux進程的狀態中,殭屍進程是非常特殊的一種,它已經放棄了幾乎所有記憶體空間,沒有任何可執行代碼,也不能被調度,僅僅在進程列表中保留一個位置,記載該進程的退出狀態等資訊供其他進程收集,除此之外,殭屍進程不再佔有任何記憶體空間。它需要它的父進程來為它收屍,如果他的父進程沒安裝SIGCHLD訊號處理函數調用wait或waitpid()等待子進程結束,又沒有顯式忽略該訊號,那麼它就一直保持殭屍狀態,如果這時父進程結束了,那麼init進程自動會接手這個子進程,為它收屍,它還是能被清除的。但是如果如果父進程是一個迴圈,不會結束,那麼子進程就會一直保持殭屍狀態,這就是為什麼系統中有時會有很多的殭屍進程。

2.殭屍進程產生的原因:
每個Linux進程在進程表裡都有一個進入點(entry),核心程式執行該進程時使用到的一切資訊都儲存在進入點。當用ps命令察看系統中的進程資訊時,看到的就是進程表中的相關資料。當以fork()系統調用建立一個新的進程後,核心進程就會在進程表中給這個新進程分配一個進入點,然後將相關資訊儲存在該進入點所對應的進程表內。這些資訊中有一項是其父進程的識別碼。當這個進程走完了自己的生命週期後,它會執行exit()系統調用,此時原來進程表中的資料會被該進程的退出碼(exit code)、執行時所用的CPU時間等資料所取代,這些資料會一直保留到系統將它傳遞給它的父進程為止。由此可見,defunct進程的出現時間是在子進程終止後,但是父進程尚未讀取這些資料之前。

3.殭屍進程的查看:
用top命令,可以看到
Tasks: 123 total, 1 running, 122 sleeping, 0 stopped, 0 zombie
zombie前面的數量就是殭屍進程到數量;
ps -ef
出現:
root 13028 12956 0 10:51 pts/2 00:00:00 [ls] <defunct>
最後有defunct的標記,就表明是殭屍進程。

4.殭屍進程解決辦法:
4.1 改寫父進程,在子進程死後要為它收屍。具體做法是接管SIGCHLD訊號。子進程死後,會發送SIGCHLD訊號給父進程,父進程收到此訊號後,執行 waitpid()函數為子進程收屍。這是基於這樣的原理:就算父進程沒有調用wait,核心也會向它發送SIGCHLD訊息,儘管對的預設處理是忽略,如果想響應這個訊息,可以設定一個處理函數。
4.2 把父進程殺掉。父進程死後,殭屍進程成為"孤兒進程",過繼給1號進程init,init始終會負責清理殭屍進程.它產生的所有殭屍進程也跟著消失。
kill -9 `ps -ef | grep "Process Name" | awk '{ print $3 }'`
其中,“Process Name”為處於zombie狀態的進程名。
4.3 殺父進程不行的話,就嘗試用skill -t TTY關閉相應終端,TTY是進程相應的tty號(終端號)。但是,ps可能會查不到特定進程的tty號,這時就需要自己判斷了。
4.4 實在不行,重啟系統吧,這也是最常用到方法之一。

5.殭屍進程執行個體:
/*-----zombie1.c-----*/
#include "sys/types.h"
#include "sys/wait.h"
#include "stdio.h"
#include "unistd.h"

int main(int argc, char* argv[])
{
while(1)
{
pid_t chi = fork();
if(chi == 0)
{
execl("/bin/bash","bash","-c","ls",NULL);
}
sleep(2);
}
}
會不停地產生僵死進程ls;

/*-----zombie2.c-----*/
#include <stdio.h>
#include<sys/types.h>

main()
{
if(!fork())
{
printf("child pid=%d\n", getpid());
exit(0);
}
/*wait();*/
/*waitpid(-1,NULL,0);*/
sleep(60);
printf("parent pid=%d \n", getpid());
exit(0);
}
60s內會不斷產生殭屍進程,直到父進程exit(0);
如果在調用wait/waitpid來為子進程收屍,就不會產生殭屍進程了。

PS:運行例子,先gcc zombie1.c -o zombie編譯,然後運行zombie;
然後可以可用ps -ef來查看是否產生了殭屍進程。
其他知識:
execl:進程進入了shell環境執行 執行完進程結束
system=fork+exec+waitpid:執行完進程仍然存在,只是用它的子進程執行了操作。

ps 的參數說明
ps 提供了很多的選項參數,常用的有以下幾個:

l 長格式輸出;
u 按使用者名稱和啟動時間的順序來顯示進程;
j 用任務格式來顯示進程;
f 用樹形格式來顯示進程;

a 顯示所有使用者的所有進程(包括其它使用者);
x 顯示不控制終端的進程;
r 顯示運行中的進程;
ww 避免詳細參數被截斷;

我們常用的選項是組合是 aux 或 lax,還有參數 f 的應用。

ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 3532 0.0 0.2 2428 452 ? Ss 20:40 0:00 gpm -m /dev/input/mice -t imps2
htt 3564 0.0 1.7 29460 3704 ? Sl 20:41 0:00 htt_server -nodaemon
root 3574 0.0 0.4 5236 992 ? Ss 20:41 0:00 crond
root 3627 0.0 0.2 3448 552 ? SNs 20:41 0:00 anacron -s
root 3636 0.0 0.1 2304 420 ? Ss 20:41 0:00 /usr/sbin/atd
ubuntu2 3655 0.0 0.5 13840 1084 ? Ssl 20:41 0:00 dbus-daemon-1 --system

Stat狀態解釋:
X 死掉的進程
< 高優先順序
N 低優先順序
L 有些頁被鎖進記憶體
s 包含子進程
+ 位於背景進程組;
l 多線程,複製線程 multi-threaded (using CLONE_THREAD, like NPTL pthreads do)
WCHAN 正在等待的進程資源;

------------------------------------------------------------------------------------------

au(x) 輸出格式 :

USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
USER: 行程擁有者
PID: pid
%CPU: 佔用的 CPU 使用率
%MEM: 佔用的記憶體使用率
VSZ: 佔用的虛擬記憶體大小
RSS: 佔用的記憶體大小
TTY: 終端的次要裝置號碼 (minor device number of tty

)
STAT: 該行程的狀態:
D: 不可中斷的靜止
R: 正在執行中
S: 靜止狀態
T: 暫停執行
Z: 不存在但暫時無法消除
W: 沒有足夠的記憶體分頁可分配
<: 高優先序的行程
N: 低優先序的行程
L: 有記憶體分頁分配並鎖在記憶體內
START: 行程開始時間
TIME: 執行的時間
COMMAND:所執行的指令





------------------------------------------------------------------------------------------
D 不可中斷 uninterruptible sleep (usually IO)
R 運行 runnable (on run queue)
S 中斷 sleeping
T 停止 traced or stopped
Z 僵死 a defunct (”zombie”) process

在Unix系統管理中,當用ps命令觀察進程的執行狀態時,經常看到某些進程的狀態列為defunct,這就是所謂的“殭屍”進程。“殭屍”進程是一個早 已死亡的進程,但在進程表(processs table)中仍佔了一個位置(slot)。由於進程表的容量是有限的,所以,defunct進程不僅佔用系統的記憶體資源,影響系統的效能,而且如果其數 目太多,還會導致系統癱瘓。 但是當 父進程死後,殭屍進程成為"孤兒進程",過繼給1號進程init,init始終會負責清理殭屍進程.它產生的所有殭屍進程也跟著消失。

一、定義:什麼是孤兒進程和殭屍進程
殭屍進程:一個子進程在其父進程還沒有調用wait()或waitpid()的情況下退出。這個子進程就是殭屍進程。
孤兒進程:一個父進程退出,而它的一個或多個子進程還在運行,那麼那些子進程將成為孤兒進程。孤兒進程將被init進程(進程號為1)所收養,並由init進程對它們完成狀態收集工作。
殭屍進程將會導致資源浪費,而孤兒則不會。



子進程持續10秒鐘的殭屍狀態(EXIT_ZOMBIE)
------------------------------------------------------
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

main()
{
pid_t pid;
pid = fork();
if(pid < 0)
printf("error occurred!\n");
else if(pid == 0) {
printf("Hi father! I'm a ZOMBIE\n");
exit(0); //(1)
}
else {
sleep(10);
wait(NULL); //(2)
}
}

(1) 向父進程發送SIGCHILD訊號
(2) 父進程處理SIGCHILD訊號

執行exit()時根據其父進程的狀態決定自己的狀態:
如果父進程已經退出(沒有wait),則該子進程將會成為孤兒進程過繼給init進程
如果其父進程還沒有退出,也沒有wait(),那麼該進程將向父進程發送SIGCHILD訊號,進入殭屍狀態等待父進程為其收屍。如果父進程一直沒有執行wait(),那麼該子進程將會持續處於殭屍狀態。




子進程將成為孤兒進程
------------------------------------------------------
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

main()
{
pid_t pid;
pid = fork();
if(pid < 0)
printf("error occurred!\n");
else if(pid == 0) {
sleep(6);
printf("I'm a orphan\n");
exit(0);
}
else {
sleep(1);
printf("Children Bye!\n");
}
}

# ./a.out
Children Bye!
# I'm a orphan
(斷行符號後將會進入#)
#
二、有什麼害處:
殭屍進程會佔用系統資源,如果很多,則會嚴重影響伺服器的效能
孤兒進程不會佔用系統資源
處理流程:
只要老爹不等wait(sys/wait.h)兒子,兒子都將成為孤魂野鬼zombie(zombie),unix中預設老爹總是想看兒子死後的狀態(以便報仇)
if 老爹比兒子先再見
兒子將被init(id = 1)收養,最後的結果是zombie兒子徹底再見,系統資源釋放
else
{
兒子的zombie將一直存在,系統資源佔用...
if 老爹dead
兒子將被init(id = 1)收養,最後的結果是zombie兒子徹底再見,系統資源釋放

else 類似的兒子zombie越來越多,系統就等死了!!!
}
三、如何防止殭屍進程
首先明白如何產生殭屍進程:
1、子進程結束後向父進程發出SIGCHLD訊號,父進程預設忽略了它
2、父進程沒有調用wait()或waitpid()函數來等待子進程的結束
第一種方法: 捕捉SIGCHLD訊號,並在訊號處理函數裡面調用wait函數
轉貼Richard Steven的Unix Network Programming代碼

int
main(int argc, char **argv)
{
...
Signal(SIGCHLD, sig_chld);
for(;
}
...
}

void
sig_chld(int signo)
{
pid_t pid;
int stat;

while ( (pid = waitpid(-1, &stat, WNOHANG)) >; 0)
printf("child %d terminated\n", pid);
return;
}
第二種方法:兩次fork():轉載
在《Unix 環境進階編程》裡關於這個在8.6節有非常清楚的說明。

執行個體
回憶一下8 . 5節中有關僵死進程的討論。如果一個進程要f o r k一個子進程,但不要求它等待
子進程終止,也不希望子進程處於僵死狀態直到父進程終止,實現這一要求的訣竅是調用f o r k
兩次。程式8 - 5實現了這一點。
在第二個子進程中調用s l e e p以保證在列印父進程I D時第一個子進程已終止。在f o r k之後,
父、子進程都可繼續執行——我們無法預知哪一個會先執行。如果不使第二個子進程睡眠,則
在f o r k之後,它可能比其父進程先執行,於是它列印的父進程I D將是建立它的父進程,而不是
i n i t進程(進程ID 1)。

#include <sys/types.h>
#include <sys/wait.h>
#include "ourhdr.h"

int
main(void)
{
pid_t pid;

if ( (pid = fork()) < 0)
err_sys("fork error");
else if (pid == 0) { /* first child */
if ( (pid = fork()) < 0)
err_sys("fork error");
else if (pid > 0)
exit(0); /* parent from second fork == first child */

/* We're the second child; our parent becomes init as soon
as our real parent calls exit() in the statement above.
Here's where we'd continue executing, knowing that when
we're done, init will reap our status. */

sleep(2);
printf("second child, parent pid = %d\n", getppid());
exit(0);
}

if (waitpid(pid, NULL, 0) != pid) /* wait for first child */
err_sys("waitpid error");

/* We're the parent (the original process); we continue executing,
knowing that we're not the parent of the second child. */

exit(0);
}
//avoid zombie process by forking twice
-----------------------------orphan.c#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<stdlib.h>
int main()
{
pid_t pid;
pid = fork();
if(!pid){
while(1){
printf("A background process,PID:%d\n,ParentID:%d\n" ,getpid(),getppid());
sleep(3);
}
}
else if(pid > 0){
printf("I am parent process,my pid is %d\n",getpid() );
exit(0);
}
else {
printf("Process creation failed!\n");
}
return 0;
}
程式運行結果
I am parent process,my pid is 2026
A background process,PID:2027
,ParentID:2026
think@Ubuntu:~/work/process_thread/fork2$ A background process,PID:2027
,ParentID:1
A background process,PID:2027
,ParentID:1
A background process,PID:2027
,ParentID:1
A background process,PID:2027
,ParentID:1
A background process,PID:2027
,ParentID:1
A background process,PID:2027
,ParentID:1
---------------------------------------------------------Zombie.c#include
  #include
  main()
  {
   pid_t pid;
  
   pid=fork();
  
   if(pid<0) /* 如果出錯 */
   printf("error occurred!n");
   else if(pid==0) /* 如果是子進程 */
   exit(0);
   else /* 如果是父進程 */
   sleep(60); /* 休眠60秒,這段時間裡,父進程什麼也幹不了 */
   wait(NULL); /* 收集殭屍進程 */
  }
----------------------------
淺議孤兒進程和殭屍進程(defunc)http://blog.csdn.net/wzb56/archive/2011/04/16/6328472.aspxLinux進程學習總結http://hi.baidu.com/shansharp/blog/item/84b5b4dfb04f1a0b48540351.html



ps aux 裡面的STAT項的Sl+表示什嗎?
大寫的S和小寫s有什麼不同,'+'號表示什嗎?

google發現只有下面的情況,沒有說明上面的兩個東西.
ps -aux時顯示出來的項目都是些什麼意思?比如:RSS、VSZ、STAT等

USER: 行程擁有者
PID: pid
%CPU: 佔用的 CPU 使用率
%MEM: 佔用的記憶體使用率
VSZ: 佔用的虛擬記憶體大小
RSS: 佔用的記憶體大小
TTY: 終端的次要裝置號碼 (minor device number of tty)
STAT: 該行程的狀態:
D: 不可中斷的靜止 (通悸□□縝b進行 I/O 動作)
R: 正在執行中
S: 靜止狀態
T: 暫停執行
Z: 不存在但暫時無法消除
W: 沒有足夠的記憶體分頁可分配
<: 高優先序的行程
N: 低優先序的行程
L: 有記憶體分頁分配並鎖在記憶體內 (即時系統或捱A I/O)
START: 行程開始時間
TIME: 執行的時間
COMMAND:所執行的指令

gilet 發表於 2009-07-22 16:22
stat 中的參數意義如下:
D 不可中斷 Uninterruptible(usually IO)
R 正在運行,或在隊列中的 進程
S 處於休眠狀態
T 停止或被追蹤
Z 殭屍進程
W 進入記憶體交換(從核心2.6開始無效)
X 死掉的進程

< 高優先順序
n 低優先順序
s 包含子進程
+ 位於背景進程組

kns1024wh 發表於 2009-07-28 11:15
PROCESS STATE CODES
Here are the different values that the s, stat and state output specifiers
(header "STAT" or "S") will display to describe the state of a process.
D Uninterruptible sleep (usually IO)
R Running or runnable (on run queue)
S Interruptible sleep (waiting for an event to complete)
T Stopped, either by a job control signal or because it is being traced.
W paging (not valid since the 2.6.xx kernel)
X dead (should never be seen)
Z Defunct ("zombie") process, terminated but not reaped by its parent.

For BSD formats and when the stat keyword is used, additional characters may
be displayed:
< high-priority (not nice to other users)
N low-priority (nice to other users)
L has pages locked into memory (for real-time and custom IO)
s is a session leader
l is multi-threaded (using CLONE_THREAD, like NPTL pthreads do)
+ is in the foreground process group

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.