Chinaunix首页 | 论坛 | 博客
  • 博客访问: 105857
  • 博文数量: 34
  • 博客积分: 791
  • 博客等级: 军士长
  • 技术积分: 250
  • 用 户 组: 普通用户
  • 注册时间: 2010-01-25 14:36
文章分类

全部博文(34)

文章存档

2012年(33)

2011年(1)

我的朋友
最近访客

分类: LINUX

2012-01-31 12:04:33

用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)


原文地址:http://blog.chinaunix.net/u2/82938/showart_1832073.html
阅读(1475) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~