IBM的LPI複習資料之LPI101-Topic103 :GNU和Unix命令(5)建立、檢測、結束進程

來源:互聯網
上載者:User

摘要:學習Linux的進程管理,包括:如何前後前後台進程,找出啟動並執行程式,殺死進程,讓進程在你離開一天以後還保持運行。

1 概述

本文協助你學習Linux進程管理的基本知識:

  • (1) 管理前台和後台工作
  • (2) 如何在你登出系統之後自動執行一個進程
  • (3) 監視進程
  • (4) 選擇和排序進程
  • (5) 向進程發送訊號
1.1 預備知識

需要有一個能夠工作的Linux系統,在上面實驗指令碼,本文的是從Ubuntu上實驗擷取的。

2 管理前台和後台工作

如果你停下來思考一下,很容易發現除了終端程式之外,還有很多其他的程式在運行。實際上,如果你使用圖形案頭環境的話,你可能已經開啟了多個終端模擬視窗、瀏覽器程式、遊戲、試算表程式等等。以前的例子中,我們都是先輸入命令,然後等待命令執行完成,等待的過程中不能做其他的事情。在本文中,你將會在終端視窗中同時做更多的事情。

當你在終端視窗運行一個命令的時候,你是在前台運行它的。很多命令啟動並執行很快,然而假設你想在一個圖形案頭上顯示數字時鐘的情況。當然了,現在很多的圖形環境頭已經提供了這麼一個功能,我們忽略這個事實,現在只是為了做實驗。

如果你已經安裝了X Window系統,也就很可能已經附帶安裝了xclock或者xeyes程式。如果沒有安裝這些程式,就按裝名字類似xorg-x11-apps或者x11-apps的軟體包。我們在例子中使用xclock。可以使用如下命令:

xclock -d -update 1

其中的-update 1控制每秒更新一次,預設情況下是每分鐘更新一次。運行結果如所示。不幸的是,此時終端視窗失去了焦點,沒有了提示符。所以,非常需要奪回控制權。慶幸的是,bash有一個掛起鍵(Ctl+z),按下這對按鍵組合,終端視窗將會重新出現提示符,如下所示。

$ xclock -d -update 1^Z[1]+ stopped     xclock -d -update 1ian@attic4:~$ fg %1xclock -d -update 1^Z[1]+  Stopped                 xclock -d -update 1ian@attic4:~$ fg %?cloxclock -d -update 1^Z[1]+  Stopped                 xclock -d -update 1ian@attic4:~$ bg[1]+ xclock -d -update 1 &

時鐘還顯示在案頭上,只是它已經停止了運行,這就是掛起操作。實際上,如果你拖動其他的視窗經過時鐘的一部分,這部分都不會重新繪製。注意到終端輸出的訊息,其中的1是job號。你可以通過運行fg %1來重新啟動這個時鐘程式。你也可以使用全部或者部分程式的名字,如fg %xclock或者fg %?clo。如果你沒有給fg提供任何參數,那麼它將會重新啟動最後掛起的那個進程,在本例中,就是xclok。重啟進程後,fg也把這個job帶回了前台,你也就重新失去了bash的提示符。你需要做的是把job放入後台,這就是bg的作用,它使用和fg一樣的參數。bg和fg一樣,也是恢複xclock的運行,不同的是bg沒有把xclock帶入前台,而是放入後台執行,這樣終端視窗依舊有提示符,同時時鐘還在正常運行。

2.1 使用 "&"

當你把xclock放入後台運行後,輸出的訊息並沒有Stopped,而是在末尾加一個&。實際上,把一進程放入後台執行,並不需要先把它掛起。只要在運行它的命令列後加上&即可。現在讓我們後台運行一個類比時鐘。

ian@attic4:~$ xclock -bg wheat -update 1&[2] 4320

注意現在的輸出包含了一個job編號以及進程ID。關於PID我們稍後再說。現在我們使用jobs命令來看看有什麼job在運行。使用-l選項來列出PID,正如你看到的,job 2確實PID為4320。注意[2]+中的+號,它表示2號job是當前job,當使用fg不帶參數運行時,這個當前job就會被送到前台。

ian@attic4:~$ jobs -l[1]-  3878 Running                 xclock -d -update 1 &[2]+  4320 Running                 xclock -bg wheat -update 1 &

在我們解決與後台job有關的問題之前,先來構建一個窮人的數字時鐘。我們使用sleep命令來造就一個2秒的延遲,使用date命令來列印當前的時間。我們使用while構造的迴圈來包圍這兩個命令。然後在後台運行這個組合體。

ian@attic4:~$ (while sleep 2; do date;done)&[2] 4856ian@attic4:~$ Tue Jan 19 09:23:30 EST 2010Tue Jan 19 09:23:32 EST 2010Tue Jan 19 09:23:34 EST 2010fTue Jan 19 09:23:36 EST 2010Tue Jan 19 09:23:38 EST 2010gTue Jan 19 09:23:40 EST 2010( while sleep 2; do    date;done )Tue Jan 19 09:23:42 EST 2010Tue Jan 19 09:23:44 EST 2010Tue Jan 19 09:23:46 EST 2010^C

這個Job的PID是4856。每隔2秒鐘,date命令輸出目前時間。當我們輸入fg命令後,這個時鐘就進入了前台,它依然沒兩秒輸出一次,不過由於在前台運行,我們再無法在bash輸入命令,只能通過Ctrl+c來停止這個程式了。

2.2 標準IO和後台進程

前面例子中,date命令的輸出與fg命令的輸入混在了一起。這導致了一個有趣的問題。如果一個後台進程需要從標準輸入擷取資料,將會發生什嗎?(譯者註:因為bash也從stdin擷取資料)。

我們用來啟動後台進程的終端進程成為控制終端。除非重新導向,否則後台進程的stdout和stderr都定向到控制終端。同樣,後台進程也期望從控制終端獲得輸入。但是控制終端無法把你鍵入的字元重新導向到後台進程的stdin。這種情況下,bash就會掛起進程,這樣也就不再運行。你可以會把它放入前台然後提供給它一些輸入資料。

ian@attic4:~$ (date; cat - > bginput.txt;date)&[2] 5070ian@attic4:~$ Tue Jan 19 10:33:13 EST 2010[2]+  Stopped                 ( date; cat - > bginput.txt; date )ian@attic4:~$ ian@attic4:~$ fg( date; cat - > bginput.txt; date )some textmore textTue Jan 19 10:33:31 EST 2010ian@attic4:~$ cat bginput.txt some textmore text
3 退出登陸後運行一個進程

實踐中,你可能想把後台進程的標準IO流重新定向到檔案。即便這樣還存在另外一個問題:如果控制終端關閉了,或者使用者登出系統了,將會發生什嗎?答案是不同的shell結果不同。如果shell發送一個SIGHUP訊號,那麼背景程式可能會關閉。現在我們考慮一個解決這個問題的方法。

3.1 nohup

nohup命令用來啟動一個程式,從而導致這個程式會忽略掉hangup訊號,並且把stdout和stderr重新導向到一個檔案。這個檔案預設是nohup.out或者$HOME/nohup.out。如果這個檔案不可寫,那麼程式就不會運行。如果你想輸出到其他地方,就重新導向stdout,stderr。

nohup不能執行一個管線或者命令列表。解決方式是把管線和列表寫入一個檔案,然後用bash來執行它。如下所示。

ian@attic4:~$ echo "while sleep 30; do date;done">pmc.sh ian@attic4:~$ nohup sh pmc.sh&[2] 5485ian@attic4:~$ nohup: ignoring input and appending output to `nohup.out'ian@attic4:~$ nohup bash pmc.sh&[3] 5487ian@attic4:~$ nohup: ignoring input and appending output to `nohup.out'

老版本的nohup不會把狀態資訊寫到控制終端上,所以可能不會看到錯誤的狀態。

ian@attic4:~$ nohup . pmc.sh >mynohup.out 2>&1 &[4] 5853ian@attic4:~$ [4]+  Exit 126                nohup . pmc.sh > mynohup.out 2>&1
4 監視進程狀態

前面我們使用了jobs命令來查看job的ID。

4.1 ps

另外有一個命令ps用來顯示進程狀態資訊。請記住,ps是process status的縮寫。ps可以接受0或者多個PID作為參數,從而顯示這些進程的狀態資訊。如果我們使用jobs命令的-p選項,輸出就只剩下了進程ID。我們可以使用這個結果作為ps的參數。

ian@attic4:~$ jobs -p387854855487ian@attic4:~$ ps $(jobs -p)  PID TTY      STAT   TIME COMMAND 3878 pts/1    S      0:06 xclock -d -update 1 5485 pts/1    S      0:00 sh pmc.sh 5487 pts/1    S      0:00 bash pmc.sh

如果沒有給ps提供選項,只有控制終端是當前終端的進程才會被顯示出來。許多其他的選項,比如-f(ull), -j(obs), -l(ong)用來控制輸出的資訊量。如果你沒有提供參數,那麼--forest選項將會顯示出進程的樹形關係,如下。

ian@attic4:~$ ps -fUID        PID  PPID  C STIME TTY          TIME CMDian       2643  2093  0 Jan18 pts/1    00:00:00 bashian       3878  2643  0 09:17 pts/1    00:00:06 xclock -d -update 1ian       5485  2643  0 15:00 pts/1    00:00:00 sh pmc.shian       5487  2643  0 15:01 pts/1    00:00:00 bash pmc.shian       6635  5485  0 15:41 pts/1    00:00:00 sleep 30ian       6645  5487  0 15:42 pts/1    00:00:00 sleep 30ian       6647  2643  0 15:42 pts/1    00:00:00 ps -fian@attic4:~$ ps -j --forest  PID  PGID   SID TTY          TIME CMD 2643  2643  2643 pts/1    00:00:00 bash 3878  3878  2643 pts/1    00:00:06  \_ xclock 5485  5485  2643 pts/1    00:00:00  \_ sh 6657  5485  2643 pts/1    00:00:00  |   \_ sleep 5487  5487  2643 pts/1    00:00:00  \_ bash 6651  5487  2643 pts/1    00:00:00  |   \_ sleep 6658  6658  2643 pts/1    00:00:00  \_ ps
4.2 free

free用來查看系統的記憶體使用量情況。預設的大小單位是KB,選項-b表示位元組,-k表示KB,-m表示MB,-g表示GB。-t顯示一個合計列,-s則指定重新整理顯示的間隔,單位為秒,可以是小數。(譯者註:-/+這行表示把緩衝作用的記憶體空間排除後)

[root@centos192 work]# free             total       used       free     shared    buffers     cachedMem:       3924872    3216928     707944          0     521896    1744736-/+ buffers/cache:     950296    2974576Swap:      7574520          0    7574520[root@centos192 work]# free -mt             total       used       free     shared    buffers     cachedMem:          3832       3141        691          0        509       1703-/+ buffers/cache:        928       2904Swap:         7396          0       7396Total:       11229       3141       8088
4.3 uptime

uptime命令在一行中顯示出如下資訊:當前系統時間、自開機系統已耗用時間、登陸使用者數、最近1,5,15分鐘內的CPU平均負載。

[root@centos192 work]# uptime 16:16:51 up 99 days,  7:06,  1 user,  load average: 0.00, 0.00, 0.00
5 選擇和排序要顯示的進程5.1 使用ps

前面我們使用ps命令只列出了控制終端是當前終端的進程,注意前面例子中的SID列。-a選項用來顯示所有擁有控制終端的進程,-x顯示所有沒有控制終端的進程,-e則顯示所有進程。

ian@attic4:~$ ps -af # 顯示所有擁有控制終端的進程的全部資訊UID        PID  PPID  C STIME TTY          TIME CMDian       3878  2643  0 09:17 pts/1    00:00:06 xclock -d -update 1ian       5485  2643  0 15:00 pts/1    00:00:00 sh pmc.shian       5487  2643  0 15:01 pts/1    00:00:00 bash pmc.shian       7192  5485  0 16:00 pts/1    00:00:00 sleep 30ian       7201  5487  0 16:00 pts/1    00:00:00 sleep 30ian       7202  2095  0 16:00 pts/0    00:00:00 ps -af

注意,TTY這一列表示的就是進程的控制終端。ps還有很多其他的選項,很多是控制顯示哪些資訊以及如何顯示。也有一些選項用來選擇特定的進程,如-u選擇特定使用者的進程,-C選擇特定命令的進程。

#用來顯示命令getty的進程,並顯示使用者,PID,控制終端,和命令列狀態列ian@attic4:~$ ps -C getty -o user,pid,tty,time,commUSER       PID TT           TIME COMMANDroot      1192 tty4     00:00:00 gettyroot      1196 tty5     00:00:00 gettyroot      1209 tty2     00:00:00 gettyroot      1219 tty3     00:00:00 gettyroot      1229 tty6     00:00:00 gettyroot      1731 tty1     00:00:00 getty

有時候,你需要對資料結果進行某種排序。這可以通過--sort選項來指定。預設是按照升序排列。

ian@attic4:~$ ps -aj --sort -sid,+comm# 按照sid降序,comm升序排列所有擁有控制終端的進程  PID  PGID   SID TTY          TIME CMD 5487  5487  2643 pts/1    00:00:00 bash 9434  9434  2643 pts/1    00:00:00 ps 5485  5485  2643 pts/1    00:00:00 sh 9430  5485  2643 pts/1    00:00:00 sleep 9433  5487  2643 pts/1    00:00:00 sleep 3878  3878  2643 pts/1    00:00:10 xclock 8019  8019  2095 pts/0    00:00:00 man 8033  8019  2095 pts/0    00:00:00 pagerian@attic4:~$ ps -aj --sort sid,comm # 按照sid升序,comm升序排列  PID  PGID   SID TTY          TIME CMD 8019  8019  2095 pts/0    00:00:00 man 8033  8019  2095 pts/0    00:00:00 pager 5487  5487  2643 pts/1    00:00:00 bash 9435  9435  2643 pts/1    00:00:00 ps 5485  5485  2643 pts/1    00:00:00 sh 9430  5485  2643 pts/1    00:00:00 sleep 9433  5487  2643 pts/1    00:00:00 sleep 3878  3878  2643 pts/1    00:00:10 xclock

更多的ps選項,參考man手冊頁以及ps --help。

5.2 使用top

如果需要動態顯示進程資訊,要使用top命令。它用來即時顯示最新的進程資訊,而且還提供了有用的匯總。使用q命令可以退出。

top - 16:07:22 up 18:29,  5 users,  load average: 0.03, 0.02, 0.00Tasks: 170 total,   1 running, 169 sleeping,   0 stopped,   0 zombieCpu(s):  2.1%us,  0.5%sy,  0.0%ni, 97.4%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%stMem:   4057976k total,  1543616k used,  2514360k free,   194648k buffersSwap: 10241428k total,        0k used, 10241428k free,   613000k cached  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND 6820 ian       20   0  506m  78m  26m S    1  2.0   0:23.97 firefox 1381 root      20   0  634m  40m  18m S    1  1.0   2:06.74 Xorg 2093 ian       20   0  212m  15m  10m S    1  0.4   0:13.53 gnome-terminal 6925 ian       20   0 1118m 298m  19m S    1  7.5   1:07.04 java 6855 ian       20   0 73416  11m 8808 S    1  0.3   0:05.01 npviewer.bin 7351 ian       20   0 19132 1364  980 R    0  0.0   0:00.07 top    1 root      20   0 19584 1888 1196 S    0  0.0   0:00.74 init    2 root      15  -5     0    0    0 S    0  0.0   0:00.01 kthreadd

top命令本身提供了一些子命令:

  • (1) h 獲得線上協助
  • (2) q 退出
  • (3) f 從顯示中增加或者刪除列
  • (4) o 排序
  • (5) F 選擇排序的根據列
  • (6) P 按照CPU佔用排序
  • (7) M 按照記憶體佔用排序
top - 16:21:48 up 18:43,  5 users,  load average: 0.16, 0.06, 0.01Tasks: 170 total,   3 running, 167 sleeping,   0 stopped,   0 zombieCpu(s):  2.1%us,  0.8%sy,  0.0%ni, 96.6%id,  0.0%wa,  0.0%hi,  0.5%si,  0.0%stMem:   4057976k total,  1588940k used,  2469036k free,   195412k buffersSwap: 10241428k total,        0k used, 10241428k free,   613056k cached  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND             6925 ian       20   0 1171m 338m  21m S    0  8.5   1:44.10 java                1381 root      20   0  634m  40m  18m S    0  1.0   2:13.63 Xorg                 6820 ian       20   0  506m  83m  26m S    3  2.1   0:51.28 firefox             2004 ian       20   0  436m  23m  15m S    0  0.6   0:01.55 nautilus            2031 ian       20   0  419m  13m  10m S    0  0.3   0:00.11 evolution-alarm     2118 ian       20   0  372m  10m 7856 S    0  0.3   0:00.06 evolution-data-     2122 ian       20   0  344m  13m  10m S    0  0.3   0:00.10 evolution-excha     2001 ian       20   0  331m  22m  14m S    0  0.6   0:13.61 gnome-panel         1971 ian       20   0  299m 9.9m 7244 S    0  0.3   0:05.00 gnome-settings-     1989 ian       20   0  288m  15m  11m S    0  0.4   0:11.95 metacity            1954 ian       20   0  265m 5460 3412 S    0  0.1   0:00.28 pulseaudio  
6 向進程發送訊號

現在讓我們來看看Linux中的訊號。這是進程間非同步通訊的機制。我們已經提到過SIGHUP這個訊號,我們也使用了Ctrl-c和Ctrl-z來發送訊號。通用的發送訊號的命令是kill。

6.1 使用kill發送訊號

kill用來向指定的job或者進程發送訊號。下面顯示了使用SIGSTP和SIGCONT訊號來停止和重啟一個後台Job。使用SIGSTP的作用等同於先使用fg把Job帶入前台然後使用Ctrl-z來暫停它。SIGCONT訊號則等同於bg命令。

ian@attic4:~$ kill -s SIGTSTP %1[1]+  Stopped                 xclock -d -update 1ian@attic4:~$ jobs -l[1]+  3878 Stopped                 xclock -d -update 1[2]   5485 Running                 nohup sh pmc.sh &[3]-  5487 Running                 nohup bash pmc.sh &ian@attic4:~$ kill -s SIGCONT 3878ian@attic4:~$ jobs -l[1]   3878 Running                 xclock -d -update 1 &[2]-  5485 Running                 nohup sh pmc.sh &[3]+  5487 Running                 nohup bash pmc.sh &

我們使用了%1來指定job,然後使用了PID來重啟它。

還有很多其他的訊號,可以使用kill-l來查看它們。有些訊號用來報告一些錯誤:非法操作符、浮點異常、非法訪問記憶體等。訊號不僅有名字,還有一個對應的數字值,如SIGSTP對應的值是20。可以使用-s 名字或者-數字。比如kill -20與kill -s SIGSTP是一樣的。在使用數字前,一定要先確認在你的系統上訊號和名字的對應情況,因為這並不是POSIX一致要求的。

6.2 訊號處理常式和進程終止

你已經知道了Ctrl-c會終止一個進程。實際上,它是向進程發送了SIGINT訊號。如果不帶任何訊號名,kill會發送SIGTERM訊號。很多情況下,這兩個訊號是等價的。

你也知道了,nohup命令會讓一個進程對SIGHUP失效。通常情況下,一個進程可以實現一個訊號處理常式來捕獲訊號。因為訊號處理常式能夠知道接收到的是什麼訊號,所以可以做出忽略SIGINT訊號,而在接受到SIGERM訊號時終止當前進程。下面例子中,我們想job2所在的進程發送了SIGTERM訊號,然後這個Job終止了。

ian@attic4:~$ kill -s SIGTERM %2ian@attic4:~$ [2]-  Terminated              nohup sh pmc.shian@attic4:~$ jobs -l[1]-  3878 Running                 xclock -d -update 1 &[3]+  5487 Running                 nohup bash pmc.sh &

訊號處理常式讓進程有了很大的靈活性。一個進程在自己工作的時候,亦可以被訊號打斷去做一些特殊的事情。訊號除了可以用來提醒進程關閉資源外,還用來通知一些服務進程重新讀取設定檔初始化。當你改變網路設定後,可能需要發送訊號給inetd進程;當你增加一個印表機後,可能需要發送訊號給lpd進程。

6.3 強制無條件地結束進程

有些訊號是無法被捕獲到的,比如一些硬體異常。SIGKILL,這個訊號是你最可能使用的,它就不能被訊號處理常式捕獲,用來無條件的強制結束一個進程。這個訊號通常是在其他方法無法結束進程的時候最後的一種方式。

7 登出並且不掛起

我們看到了,nohup命令可以讓一個命令在使用者登出後繼續運行。現在我們先登出然後再登入來看看。重新登入以後,使用jobs和ps來查看繼續啟動並執行窮人鐘錶進程。

ian@attic4:~$ jobs -lian@attic4:~$ ps -a  PID TTY          TIME CMD10995 pts/0    00:00:00 ps

我們沒有發現我們的job,這可不是我們期望的。但是,一切並沒有丟失。只是這個進程失去了控制終端了,所以看不到。我們可以先找到bash命令對應的SID,然後看看。

ian@attic4:~$ ps -C bash -C sh -o pid,sid,tname,cmd  PID   SID TTY      CMD 5487  2643 ?        bash pmc.sh 7050  7050 pts/3    -bash10851 10851 pts/0    bashian@attic4:~$ ps -js 2643  PID  PGID   SID TTY          TIME CMD 5487  5487  2643 ?        00:00:00 bash11197  5487  2643 ?        00:00:00 sleep

注意,pmc.sh依舊在運行,只是它的控制終端顯示為?。考慮到你已經學習了如何結束一個進程,你應該能夠使用kill來結束這個pmc了。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.