用lsof列出當前正在被打開的文件

用lsof列出當前正在被打開的文件

一,lsof有什麼用?
   lsof可以找出被特定進程所打開的文件,目錄,套接字,設備.
   例子:比如有時我們不能umount掉一個分區時,我們會需要檢查,是哪些進程在使用當前的分區
        以便找出進程後將它關閉
   一個與腳本相關的例子:
        我們使用ftp接收別人上傳的文件,有程序被放到crond中定時進行處理,
        此時就有一個問題;我們如何得知當前被處理的文件是否上傳完了,
        比如:如果上傳的是一張圖片,且正在傳輸中我們就進行了處理,則我們會得到一張殘缺不全的圖片
        解決方法:用lsof對文件進行檢查,如果有進程在訪問,就表示還未上傳完成,可以先跳過當前文件
        
二,lsof的用法舉例
   1,檢查目錄和文件
     [root@localhost cdrom]# umount /mnt/cdrom
        umount: /mnt/cdrom: device is busy.
        (In some cases useful info about processes that use
         the device is found by lsof(8) or fuser(1))
     在做umount設備時, device is busy是令人頭痛的提示
     大家看,我使用的是fedora 10,umount會自動給出讓大家用lsof或fuser進行檢測的信息
     [root@localhost cdrom]# lsof /mnt/cdrom
     COMMAND  PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
     bash    2705 root  cwd    DIR    8,1     8192    1 /mnt/cdrom
     lsof    2756 root  cwd    DIR    8,1     8192    1 /mnt/cdrom
     lsof    2757 root  cwd    DIR    8,1     8192    1 /mnt/cdrom

    可以看到,有3個進程在訪問/mnt/cdrom,程序分別是 bash和lsof,
    lsof給出的信息很全,還列出了進程的id及用戶

    因爲我們當前就處在cdrom目錄下,所以bash也是其中打開cdrom目錄的一個進程
    下面我們從目錄下退出:

     [root@localhost winc]# cd
     [root@localhost ~]# umount /mnt/cdrom

    這個例子提醒大家:如果umount一個分區時,lsof列出的進程中有bash,
    通常是有用戶登錄在此目錄下,通知用戶讓他從目錄下cd出來就可以了

    還有一種情況:如果是apache在訪問當前分區怎麼辦?
    象apache或其他daemon在訪問分區,很簡單,
    只需要停止daemon就可以了

   2,有沒有這種可能:我們用lsof看不到進程,但是在做umount時系統仍然提示 device is busy?
     有這種可能,
     一個例子:
     [root@search root]# umount /store2
     umount: /store2: device is busy
     [root@search root]# lsof /store2

     很奇怪,我們用lsof看不到訪問/store2的進程,但umount時系統卻告訴我們說:
     device is busy
     爲什麼會這樣?
     是因爲有可能nfs正在使用此進程
     查看/etc/exports,此目錄便位於其中
     
      [root@search root]# cat /etc/exports
      /store2 201.103.105.37(rw,sync,no_root_squash)
      /store2 201.103.105.36(rw,sync,no_root_squash)
    
     此時如何處理?
      把/etc/exports中的nfs出去的目錄註釋掉,用#加在每一行前面即可
      然後無需重啓 nfs,執行 exportfs -rv即可

   3,根據進程id得到其打開的文件列表:
     我們查看一個apache進程所打開的文件列表:

     [root@www ~]# lsof -p 2759
     COMMAND  PID   USER   FD   TYPE    DEVICE      SIZE      NODE NAME
     httpd   2759 nobody  cwd    DIR     253,0      4096         2 /
     httpd   2759 nobody  rtd    DIR     253,0      4096         2 /
     httpd   2759 nobody  txt    REG     253,0   1885982   4622117 /usr/local/apache2/bin/httpd
     httpd   2759 nobody  mem    REG     253,0    334391   4621269 /usr/local/apache2/lib/libaprutil-0.so.0.9.12
     httpd   2759 nobody  mem    REG     253,0    374273   4621265 /usr/local/apache2/lib/libexpat.so.0.1.0
     httpd   2759 nobody  mem    REG     253,0    578133   4621251 /usr/local/apache2/lib/libapr-0.so.0.9.12
     httpd   2759 nobody  mem    REG     253,0     21546   4407507 /usr/lib64/gconv/gconv-modules.cache
     httpd   2759 nobody  mem    REG     253,0     30070   9519340 /lib64/libcrypt-2.3.4.so
     httpd   2759 nobody  mem    REG     253,0  18848742   4622118 /usr/local/apache2/modules/libphp5.so

     ......
     它打開的文件很多,我不再全列出

   4,列出某個終端上的用戶正在做什麼?
     例如:
     我們先登錄到一個終端上面:(先用tty得到當前終端)
     [root@search root]# tty       
     /dev/pts/2
     [root@search root]# cat
    
     然後登錄到另一終端:
     [root@search root]# lsof /dev/pts/2
     COMMAND   PID USER   FD   TYPE DEVICE SIZE NODE NAME
     cat       514 root    0u   CHR  136,2         4 /dev/pts/2
     cat       514 root    1u   CHR  136,2         4 /dev/pts/2
     cat       514 root    2u   CHR  136,2         4 /dev/pts/2
     bash    32551 root    0u   CHR  136,2         4 /dev/pts/2
     bash    32551 root    1u   CHR  136,2         4 /dev/pts/2
     bash    32551 root    2u   CHR  136,2         4 /dev/pts/2
     bash    32551 root  255u   CHR  136,2         4 /dev/pts/2

   5,列出所有命令名字相同的進程所打開的全部文件
     例如:apache的進程名命令全部都是httpd
     我們列出apache打開的所有進程時,可以使用 -c參數,
     [root@search yc]# lsof -c httpd
     COMMAND   PID   USER   FD   TYPE     DEVICE       SIZE       NODE NAME
     httpd   15722   root  cwd    DIR        8,8       4096          2 /
     httpd   15722   root  rtd    DIR        8,8       4096          2 /
     httpd   15722   root  txt    REG        8,2    1701872    1087581 /usr/local/apache/bin/httpd
     httpd   15722   root  mem    REG        8,8     103044      31946 /lib/ld-2.3.2.so
     httpd   15722   root  mem    REG        8,8      23668      31955 /lib/libcrypt-2.3.2.so
     httpd   15722   root  mem    REG        8,2     877128      69041 /usr/lib/libsablot.so.0.100.1
     httpd   15722   root  mem    REG        8,2     442752      69039 /usr/lib/libjs.so
     httpd   15722   root  mem    REG        8,2     130104      64938 /usr/lib/libexpat.so.0.4.0
     httpd   15722   root  mem    REG        8,2      52616      64985 /usr/lib/libz.so.1.1.4
     httpd   15722   root  mem    REG        8,2     136068      66295 /usr/lib/libcurl.so.2.0.2
     httpd   15722   root  mem    REG        8,8      76552      31977 /lib/libresolv-2.3.2.so
     httpd   15722   root  mem    REG        8,8     211948      95819 /lib/tls/libm-2.3.2.so
     ......
     進程太多,不一一列舉

   6,根據目錄,列出指定目錄下被進程打開的文件或目錄
    先看兩個參數:
    +d,只搜索當前目錄下被打開的文件或目錄
    +D,遞歸搜索當前目錄下被打開的文件或目錄
    (注意此參數會導至速度變慢)
    例子:
    [root@search yc]# mkdir abc
    [root@search yc]# cd abc/

    在另一終端執行lsof
    [root@search root]# lsof +d /store2/yc/
    COMMAND   PID USER   FD   TYPE DEVICE SIZE      NODE NAME
    bash    32473 root  cwd    DIR   8,16 4096 111329281 /store2/yc/abc

    下面我們再深入一層目錄
    [root@search abc]# mkdir def
    [root@search abc]# cd def

    還是到另一終端執行lsof
    [root@search root]# lsof +d /store2/yc/
    [root@search root]#
    看不到進程了,因爲def不再是直接在/store2/yc目錄下,而是更下一層,則此時需要+D
    [root@search root]# lsof +D /store2/yc/
    COMMAND   PID USER   FD   TYPE DEVICE SIZE      NODE NAME
    bash    32473 root  cwd    DIR   8,16 4096 111345665 /store2/yc/abc/def

   7,查看打開某個端口的所有進程
    [root@search root]# lsof -i :80
    COMMAND   PID   USER   FD   TYPE      DEVICE SIZE NODE NAME
    httpd   15722   root   22u  IPv4  1863715557       TCP *:http (LISTEN)
    httpd   28161 nobody   22u  IPv4  1863715557       TCP *:http (LISTEN)
    httpd   28162 nobody   22u  IPv4  1863715557       TCP *:http (LISTEN)
    httpd   28163 nobody   22u  IPv4  1863715557       TCP *:http (LISTEN)
    .......
    [root@search root]# lsof -i :21
    COMMAND  PID USER   FD   TYPE      DEVICE SIZE NODE NAME
    xinetd  9362 root    6u  IPv4 -1253197382       TCP *:ftp (LISTEN)

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章