天天看點

Linux Shell常用技巧(九)

十九.  和系統運作程序相關的Shell指令:

   1.  程序監控指令(ps):

    要對程序進行監測和控制,首先必須要了解目前程序的情況,也就是需要檢視目前程序,而ps指令就是最基本同時也是非常強大的程序檢視指令。使用該指令可以确定有哪些程序正在運作和運作的狀态、程序是否結束、程序有沒有僵死、哪些程序占用了過多的資源等等。總之大部分資訊都是可以通過執行該指令得到的。

    ps指令存在很多的指令行選項和參數,然而我們最為常用隻有兩種形式,這裡先給出與它們相關的選項和參數的含義:

選項

說明

a

顯示終端上的所有程序,包括其他使用者的程序。

u

以使用者為主的格式來顯示程式狀況。

x

顯示所有程式,不以終端來區分。

-e

顯示所有程序。

o

其後指定要輸出的列,如user,pid等,多個列之間用逗号分隔。

-p

後面跟着一組pid的清單,用逗号分隔,該指令将隻是輸出這些pid的相關資料。

    /> ps aux

    root         1  0.0  0.1   2828  1400 ?        Ss   09:51   0:02 /sbin/init

    root         2  0.0  0.0      0          0 ?        S    09:51   0:00 [kthreadd]

    root         3  0.0  0.0      0          0 ?        S    09:51   0:00 [migration/0]

    ... ...   

    /> ps -eo user,pid,%cpu,%mem,start,time,command | head -n 4

    USER       PID %CPU %MEM  STARTED     TIME        COMMAND

    root         1         0.0    0.1   09:51:08     00:00:02  /sbin/init

    root         2         0.0    0.0   09:51:08     00:00:00  [kthreadd]

    root         3         0.0    0.0   09:51:08     00:00:00  [migration/0]

    這裡需要說明的是,ps中存在很多和程序性能相關的參數,它們均以輸出表格中的列的方式顯示出來,在這裡我們隻是給出了非常常用的幾個參數,至于更多參數,我們則需要根據自己應用的實際情況去看ps的man手冊。

    #以完整的格式顯示pid為1(init)的程序的相關資料

    /> ps -fp 1

    UID        PID  PPID  C STIME TTY          TIME   CMD

    root         1        0  0 05:16   ?        00:00:03 /sbin/init

    2.  改變程序優先級的指令(nice和renice):

    該Shell指令最常用的使用方式為:nice [-n <優先等級>][執行指令],其中優先等級的範圍從-20-19,其中-20最高,19最低,隻有系統管理者可以設定負數的等級。

    #背景執行sleep 100秒,同時在啟動時将其nice值置為19

    /> nice -n 19 sleep 100 &

    [1] 4661

    #背景執行sleep 100秒,同時在啟動時将其nice值置為-19

    /> nice -n -19 sleep 100 &

    [2] 4664

    #關注ps -l輸出中用黃色高亮的兩行,它們的NI值和我們執行是設定的值一緻。

    /> ps -l

    F S   UID   PID  PPID  C PRI  NI  ADDR  SZ    WCHAN  TTY       TIME        CMD

    4 S     0  2833  2829  0  80   0     -      1739     -         pts/2    00:00:00  bash

    0 S     0  4661  2833  0  99  19    -      1066     -         pts/2    00:00:00  sleep

    4 S     0  4664  2833  0  61 -19    -      1066     -         pts/2    00:00:00  sleep

    4 R     0  4665  2833  1  80   0     -      1231     -         pts/2    00:00:00  ps

    renice指令主要用于為已經執行的程序重新設定nice值,該指令包含以下幾個常用選項:

-g

使用程式群組名稱,修改所有隸屬于該程式群組的程式的優先權。

改變該程式的優先權等級,此參數為預設值。

-u

指定使用者名稱,修改所有隸屬于該使用者的程式的優先權。

    #切換到stephen使用者下執行一個背景程序,這裡sleep程序将在背景睡眠1000秒。

    /> su stephen

    /> sleep 1000&  

    [1] 4812

    /> exit   #退回到切換前的root使用者

    #檢視已經啟動的背景sleep程序,其ni值為0,宿主使用者為stephen

    /> ps -eo user,pid,ni,command | grep stephen

    stephen   4812   0 sleep 1000

    root        4821    0 grep  stephen

    #以指定使用者的方式修改該使用者下所有程序的nice值

    /> renice -n 5 -u stephen

    500: old priority 0, new priority 5

    #從再次執行ps的輸出結果可以看出,該sleep背景程序的nice值已經調成了5

    /> ps -eo user,pid,ni,command | grep stephen

    stephen   4812   5 sleep 1000

    root         4826   0 grep  stephen

    #以指定程序pid的方式修改該程序的nice值

    /> renice -n 10 -p 4812

    4812: old priority 5, new priority 10

    #再次執行ps,該sleep背景程序的nice值已經從5變成了10

    stephen   4812  10 sleep 1000

    root        4829   0 grep  stephen

    3.  列出目前系統打開檔案的工具(lsof):

    lsof(list opened files),其重要功能為列舉系統中已經被打開的檔案,如果沒有指定任何選項或參數,lsof則列出所有活動程序打開的所有檔案。衆所周知,linux環境中任何事物都是檔案,如裝置、目錄、sockets等。是以,用好lsof指令,對日常的linux管理非常有幫助。下面先給出該指令的常用選項:

-a

該選項會使後面選項選出的結果清單進行and操作。

-c command_prefix

顯示以command_prefix開頭的程序打開的檔案。

-p PID

顯示指定PID已打開檔案的資訊

+d directory

從檔案夾directory來搜尋(不考慮子目錄),列出該目錄下打開的檔案資訊。

+D directory

從檔案夾directory來搜尋(考慮子目錄),列出該目錄下打開的檔案資訊。

-d num_of_fd

以File Descriptor的資訊進行比對,可使用3-10,表示範圍,3,10表示某些值。

-u user

顯示某使用者的已經打開的檔案,其中user可以使用正規表達式。

-i

監聽指定的協定、端口、主機等的網絡資訊,格式為:[proto][@host|addr][:svc_list|port_list]

    #檢視打開/dev/null檔案的程序。

    /> lsof /dev/null | head -n 5

    COMMAND    PID      USER   FD   TYPE DEVICE SIZE/OFF NODE NAME

    init         1      root    0u   CHR    1,3      0t0 3671 /dev/null

    init         1      root    1u   CHR    1,3      0t0 3671 /dev/null

    init         1      root    2u   CHR    1,3      0t0 3671 /dev/null

    udevd 397      root    0u   CHR    1,3      0t0 3671 /dev/null

    #檢視打開22端口的程序

    /> lsof -i:22

    COMMAND  PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME

    sshd    1582 root    3u  IPv4  11989      0t0  TCP *:ssh (LISTEN)

    sshd    1582 root    4u  IPv6  11991      0t0  TCP *:ssh (LISTEN)

    sshd    2829 root    3r   IPv4  19635      0t0  TCP bogon:ssh->bogon:15264 (ESTABLISHED)

    #檢視init程序打開的檔案

    />  lsof -c init

    COMMAND PID USER   FD   TYPE     DEVICE   SIZE/OFF   NODE    NAME

    init               1 root  cwd      DIR        8,2     4096              2        /

    init               1 root  rtd       DIR        8,2     4096              2        /

    init               1 root  txt       REG       8,2   136068       148567     /sbin/init

    init               1 root  mem    REG        8,2    58536      137507     /lib/libnss_files-2.12.so

    init               1 root  mem    REG        8,2   122232     186675     /lib/libgcc_s-4.4.4-20100726.so.1

    init               1 root  mem    REG        8,2   141492     186436     /lib/ld-2.12.so

    init               1 root  mem    REG        8,2  1855584    186631     /lib/libc-2.12.so

    init               1 root  mem    REG        8,2   133136     186632     /lib/libpthread-2.12.so

    init               1 root  mem    REG        8,2    99020      180422     /lib/libnih.so.1.0.0

    init               1 root  mem    REG        8,2    37304      186773     /lib/libnih-dbus.so.1.0.0

    init               1 root  mem    REG        8,2    41728      186633     /lib/librt-2.12.so

    init               1 root  mem    REG        8,2   286380     186634     /lib/libdbus-1.so.3.4.0

    init               1 root    0u     CHR        1,3      0t0           3671      /dev/null

    init               1 root    1u     CHR        1,3      0t0           3671      /dev/null

    init               1 root    2u     CHR        1,3      0t0           3671      /dev/null

    init               1 root    3r      FIFO       0,8      0t0           7969      pipe

    init               1 root    4w     FIFO       0,8      0t0           7969      pipe

    init               1 root    5r      DIR        0,10        0             1         inotify

    init               1 root    6r      DIR        0,10        0             1         inotify

    init               1 root    7u     unix   0xf61e3840  0t0       7970      socket

    init               1 root    9u     unix   0xf3bab280  0t0      11211     socket

    在上面輸出的FD列中,顯示的是檔案的File Descriptor number,或者如下的内容:

    cwd:  current working directory;

    mem:  memory-mapped file;

    mmap: memory-mapped device;

    pd:   parent directory;

    rtd:  root directory;

    txt:  program text (code and data);

    檔案的File Descriptor number顯示模式有:

    r for read access;

    w for write access;

    u for read and write access;

    在上面輸出的TYPE列中,顯示的是檔案類型,如:

    DIR:  目錄

    LINK: 連結檔案

    REG:  普通檔案

    #檢視pid為1的程序(init)打開的檔案,其輸出結果等同于上面的指令,他們都是init。

    /> lsof -p 1

    #檢視owner為root的程序打開的檔案。

    /> lsof -u root

    #檢視owner不為root的程序打開的檔案。

    /> lsof -u ^root

    #檢視打開協定為tcp,ip為192.168.220.134,端口為22的程序。

    /> lsof -i [email protected]:22

    sshd        2829 root     3r    IPv4  19635      0t0      TCP    bogon:ssh->bogon:15264 (ESTABLISHED)    

    #檢視打開/root檔案夾,但不考慮目錄搜尋

    /> lsof +d /root

    #檢視打開/root檔案夾以及其子目錄搜尋

    /> lsof +D /root

    #檢視打開FD(0-3)檔案的所有程序

    /> lsof -d 0-3

    #-a選項會将+d選項和-c選項的選擇結果進行and操作,并輸出合并後的結果。

    /> lsof +d .

    COMMAND  PID USER   FD   TYPE DEVICE SIZE/OFF  NODE NAME

    bash       9707  root  cwd    DIR    8,1     4096         39887 .

    lsof         9791  root  cwd    DIR    8,1     4096         39887 .

    lsof         9792  root  cwd    DIR    8,1     4096         39887 .

    /> lsof -a -c bash +d .

    bash        9707 root  cwd    DIR    8,1     4096         39887 .

    最後需要額外說明的是,如果在檔案名的末尾存在(delete),則說明該檔案已經被删除,隻是還存留在cache中。

    4.  程序查找/殺掉指令(pgrep/pkill):

    查找和殺死指定的程序, 他們的選項和參數完全相同, 這裡隻是介紹pgrep。下面是常用的指令行選項:

-d

定義多個程序之間的分隔符, 如果不定義則使用換行符。

-n

表示如果該程式有多個程序正在運作,則僅查找最新的,即最後啟動的。

-o

表示如果該程式有多個程序正在運作,則僅查找最老的,即最先啟動的。

-G

其後跟着一組group id,該指令在搜尋時,僅考慮group清單中的程序。

其後跟着一組有效使用者ID(effetive user id),該指令在搜尋時,僅考慮該effective user清單中的程序。

-U

其後跟着一組實際使用者ID(real user id),該指令在搜尋時,僅考慮該real user清單中的程序。

-x

表示程序的名字必須完全比對, 以上的選項均可以部分比對。

-l

将不僅列印pid,也列印程序名。

-f

一般與-l合用, 将列印程序的參數。

    #手工建立兩個背景程序

    /> sleep 1000&

    3456

    /> sleep 1000&

    3457

    #查找程序名為sleep的程序,同時輸出所有找到的pid

    /> pgrep sleep

    #查找程序名為sleep的程序pid,如果存在多個,他們之間使用:分隔,而不是換行符分隔。

    /> pgrep -d: sleep

    3456:3457

    #查找程序名為sleep的程序pid,如果存在多個,這裡隻是輸出最後啟動的那一個。

    /> pgrep -n sleep

    #查找程序名為sleep的程序pid,如果存在多個,這裡隻是輸出最先啟動的那一個。

    /> pgrep -o  sleep

    #查找程序名為sleep,同時這個正在運作的程序的組為root和stephen。

    /> pgrep -G root,stephen sleep

    #查找有效使用者ID為root和oracle,程序名為sleep的程序。

    /> pgrep -u root,oracle sleep

    #查找實際使用者ID為root和oracle,程序名為sleep的程序。

    /> pgrep -U root,oracle sleep

    #查找程序名為sleep的程序,注意這裡找到的程序名必須和參數中的完全比對。

    /> pgrep -x sleep

    #-x不支援部分比對,sleep程序将不會被查出,是以下面的指令沒有結果。

    /> pgrep -x sle

    #查找程序名為sleep的程序,同時輸出所有找到的pid和程序名。    

    /> pgrep -l sleep

    3456 sleep

    3457 sleep

    #查找程序名為sleep的程序,同時輸出所有找到的pid、程序名和啟動時的參數。

    /> pgrep -lf sleep

    3456 sleep 1000

    3457 sleep 1000

    #查找程序名為sleep的程序,同時以逗号為分隔符輸出他們的pid,在将結果傳給ps指令,-f表示顯示完整格式,-p顯示pid清單,ps将隻是輸出該清單内的程序資料。

    /> pgrep -f sleep -d, | xargs ps -fp

    UID        PID  PPID  C STIME TTY          TIME CMD

    root      3456  2138  0 06:11 pts/5    00:00:00 sleep 1000

    root      3457  2138  0 06:11 pts/5    00:00:00 sleep 1000