用 grep 恢复误删的文本文件

作为长期的电脑使用者,肯定会有误删文件的经历,在 Mac OS X 和 Windows 上删除的文件都会默认进 “回收站”。在 Linux 上如果事先没有用别名(alias)修改默认的 rm 功能,rm 后文件就会丢失,幸运的是,在一般的删除文件操作中,Linux 并不会立即清空存储该文件的 block 内容,而只会释放该文件所占用的 inode 和 data block,Linux 上 rm 的过程其实就是将 inode bitmap 和 data block bitmap 中的相应标识设为空闲状态的过程,并不涉及到真正的数据,这也是为什么在 Linux 下删除大文件这么快速的原因,因为大文件所占的磁盘根本就没有清空。所以,如果我们能找到文件对应的 inode,由此查到相应的 data block,就可能从磁盘上把已删除的文件恢复出来,很多文件/磁盘恢复工具都是这么做的。

一般来说二进制文件、库文件等删除后都可以从其他 Linux 拷贝恢复,不是很要紧,如果自己辛苦写的脚本或者配置文件误删了就杯具了。误删这种蠢事经常在 VPSee 身上发生,最近一次是在今年年初的时候,开了 screen 多次 ssh 到不同服务器上,在前后切换的过程中删除了一个很肯定的配置文件,后来发现删的文件是对的,可惜在一台错误的服务器上,本来应该在 A 服务器上删除 file.txt 结果在 B 服务器上删除了 file.txt,多个 screen 和 ssh 把自己搞晕了,而且主机名没有安排好,多台机器都是用的 localhost,不利于识别当时的环境。如果使用 Linux 的时候不幸误删了一个文本文件怎么办呢?

先临时建一个文本文件 vpsee.log 做测试,然后删除这个文件:

$ echo "important log file for vpsee.com" > vpsee.log

$ cat vpsee.log 
important log file for vpsee.com

$ rm vpsee.log

如果能记住刚才删除文件中的某个关键字的话可以用 grep 搜索整个 /dev/sda1,-a 标志位的意思是把 /dev/sda1 这个分区看成是文本形式的(分区本身是二进制形式的),-B 10 -A 100 的意思是如果找到关键字就打印出其前10行和后100行的内容:

# grep -a -B 10 -A 100 'vpsee.com' /dev/sda1 > tmp.txt

在一堆 @ 之间可以找到我们刚才删除的内容:

$ vi tmp.txt
...
@$^@^@^@^@^@^@^@^@^@^@^@^A^@^@^@^@^@^@^@Ç^@^@^@^A^@^@^@^@^@^@^@^@^@^@^@È^K^@^@^@
^@^@^@^@^@^@^@^@^@^@^@^A^@^@^@^@^@^@^@^Q^@^@^@^C^@^@^@^@^@^@^@^@^@^@^@È^K^@^@×^@
^@^@important log file for vpsee.com
@                                                                               
@            
...

当然,如果误删了二进制、doc、png/jpg/gif 之类的文件,可以用一些第三方 ext2/ext3 文件恢复工具帮助恢复文件,比如 TestDisk, PhotoRec 等。

Linux 遇到 kernel panic 后可自动重启

现在的 Linux 比10年前要成熟的多,但有时候还是会出现莫名其妙、无法解释的 kernel panic 情况。对于大部分 Linux 用户来说出现 kernel panic 重启一下就可以了,但是对于系统管理员和那些做虚拟主机、共享主机、OpenVZ VPS 主机的 hosting 服务商来说出现未知的 kernel panic、导致系统挂掉可能就不太友好,如果没有 KVM over IP 的话,系统挂掉后 hosting 服务商需要自己先反馈到上一级的独立服务器提供商,比如提交 ticket 或者打电话,然后独立服务器供应商还要时间验证你的资料、处理你的 ticket,最后才到真正的数据中心,一般晚上(中国的白天)数据中心只有几个人值班,到最后处理完你的重启请求可能已经过了20多分钟了,这20分钟的 downtime 时间你还要给你自己的客户写信解释情况,问题是这20分钟还是理想情况,如果你碰到一个很烂的独立服务器提供商或数据中心,处理 ticket 要以小时或天为单位来计,或者如果你是 one man、晚上正在睡觉没有收到 kernel panic 报警,这样的话花的时间就会更多。那么有没有办法让 Linux 服务器遇到 kernel panic 情况自动重启呢?VPSee 在这里介绍一个简单有效的小技巧:

编辑 /etc/sysctl.conf 文件,并定义遇到 kernel panic 20秒后自动重启 Linux:

# vi /etc/sysctl.conf
kernel.panic = 20

Linux 这么神奇?遇到 kernel panic 自己都挂了还能自己重启?来看看 Linux 内核里面这部分代码是怎么工作的,最好最权威的资料永远来自内核源代码:

# vi linux-2.6.31.8/kernel/panic.c

...
 if (panic_timeout > 0) {
                /*
                 * Delay timeout seconds before rebooting the machine.
                 * We can't use the "normal" timers since we just panicked.
                 */
                printk(KERN_EMERG "Rebooting in %d seconds..", panic_timeout);

                for (i = 0; i < panic_timeout*1000; ) {
                        touch_nmi_watchdog();
                        i += panic_blink(i);
                        mdelay(1);
                        i++;
                }
                /*
                 * This will not be a clean reboot, with everything
                 * shutting down.  But if there is a chance of
                 * rebooting the system it will be rebooted.
                 */
                emergency_restart();
        }
...

什么吃掉了我的硬盘?

经常收到我们的 VPS 用户询问,“我的 VPS 没装新东西,为什么硬盘越用越少了?”,这多半是因为系统上的各种日志长期积累下来的结果,比如 nginx, apache 等留下来的访问日志信息长时间不清理、而且访问量大的话会很容易就膨胀到 GB;有时候某种应用程序的日志藏在文件系统的深处,不易发觉;有时候自己拷贝了一些大文件放在某个地方时间长了就忘了。那么如何在 Linux 系统上找到这些占用硬盘空间的文件呢?

首先我们可以统计一下根目录下各个目录占用硬盘的情况,找出最占用硬盘的那个目录:

# du -sh /*
6.2M	/bin
17M	/boot
136K	/dev
97M	/etc
147G	/home
584M	/lib
16M	/lib64
16K	/lost+found
8.0K	/media
12K	/mnt
252K	/opt
0	/proc
1.7G	/root
28M	/sbin
8.0K	/selinux
3.1M	/srv
0	/sys
20K	/tmp
1.9G	/usr
748M	/var

从上面可看出 /home 占用了最多的硬盘,我们去看看 /home 下哪些用户占用了最多的空间:

# du -sh /home/*
4.0K	/home/bak
106M	/home/cos
28K	/home/guest
16K	/home/lost+found
105G	/home/vpsee
33G	/home/somebody
8.2G	/home/abc

可以看到 vpsee 这个用户和他的 home 目录 /home/vpsee 用掉了最多的硬盘(105GB),我们再看看 /home/vpsee 下究竟哪些文件占用了空间,用下面的一行命令找出某个目录下(这里是 /home/vpsee)大小超过 500MB 的文件(打印前40行并按照 MB 从小到大排列):

# find /home/vpsee -printf "%k %p\n" | sort -g -k 1,1 | \
awk '{if($1 > 500000) print $1/1024 "MB" " " $2 }' |tail -n 40

647.68MB  /home/vpsee/linux/debian-504-amd64-CD-1.iso
675.664MB /home/vpsee/linux/Fedora-13-i686-Live.iso
677.656MB /home/vpsee/unix/osol-0906-x86.iso
678.172MB /home/vpsee/linux/ubuntu-10.04-server-amd64.iso
700.133MB /home/vpsee/linux/ubuntu-10.04-desktop-i386.iso
1304.64MB /home/vpsee/mac/MacTeX.mpkg.zip

可以看到 /home/vpsee 是个 iso 收藏狂,收了一堆 Linxu ISO 安装文件,以前拨号上网时代大家都喜欢收集一些软件和工具存在硬盘里,现在网络这么发达,这些旧习惯已经没必要了,ISO 文件可有可无,需要的时候就去下一个最新的,用不着自己保留,网络就是我们的硬盘。

超级计算机6月数据统计

上次讨论 Linux 发行版的时候提到一些超级计算机的数据,Top500.org 每隔半年都会发布最新的全球500强超级计算机的统计报告。这次报告的亮点是中国,中国有24台超级计算机上榜,按照个数排名与德国并列第四,但是其中有2台进入10强,其中1台还排名第2,把所有上榜的超级计算机的处理能力加起来中国也是第一次在整体计算能力上仅次于美国排名第二。以下图片来自 BBC 的 In graphics: Supercomputing superpowers

supercomputer list by country

supercomputer list by os

毫无疑问 Linux 是超级计算机的主角,如果对比上次数据会发现 SUSE/SLES 系在下降,RedHat/RHEL/CentOS 系在上升。以下数据来自:Top 500 Super Computer Sites

操作系统版本 使用的个数 所占百分比 处理器个数
Linux(未知版本) 405 81.00 % 3186754
SLES 9 4 0.80 % 59504
CNK/SLES 9 15 3.00 % 1146880
SUSE Linux 1 0.20 % 26304
Redhat Linux 4 0.80 % 48800
RedHat Enterprise 4 3 0.60 % 14736
UNICOS/SUSE Linux 1 0.20 % 8192
SLES 10 4 0.80 % 20952
SLES10 + SGI ProPack 5 13 2.80 % 126720
RedHat Enterprise 5 2 0.40 % 11928
CentOS 7 1.40 % 96720

如何在 Xen VPS 上升级 Linux

有客户询问能否重新 rebuild 他的 Ubuntu 10.04 VPS 并升级到我们刚推出的 Ubuntu 12.04 LTS Server 版本,其实用户可以自己完成升级而不用我们 rebuild,不损失任何数据。和其他一些 Xen VPS 服务商不同,我们采用 PyGrub 来启动和管理 domU 的内核而不是在 dom0 范围内统一管理内核,这意味着用户可以在自己 VPS 上启动和使用自己的内核,这样做的好处是用户完全可以自己升级 VPS 的内核以及整个 Linux 系统(版本),完全不用我们的干预。升级办法很简单,就和在自己电脑上升级 Linux 一样,不过 OpenVZ VPS 是不能这样包括内核在内完整升级到新版本的。VPSee 建议在做任何升级之前做好备份。

Linode 和 SliceHost 两大 Xen VPS 服务商都相继发布了 Ubuntu 10.04 LTS 版本的 VPS. 我们上个星期安装和测试了 Ubuntu 10.04 LTS VPS,使用 8GB SUN V20z 服务器跑32个 128/256MB VPS 的混合,每个 VPS 上跑不同的应用和压力,测试结果在意料之中,Ubuntu 10.04 LTS 已经被我们加入到 VPS 计划之中并应用到了生产环境。

升级 Ubuntu 12.04 到 14.04(2014年4月17日更新)

我们的用户可以在自己的 VPS 上升级 Ubuntu 12.04 LTS Server 到 Ubuntu 14.04 LTS Server:

# apt-get update
# apt-get upgrade
# do-release-upgrade -d
# reboot

升级 Ubuntu 10.04 到 12.04

同样的,升级 Ubuntu 10.04 LTS Server 到 Ubuntu 12.04 LTS Server:

# apt-get update
# apt-get upgrade
# do-release-upgrade -d
# reboot

升级 CentOS 5.4/5.5 到 5.8

正在使用 CentOS 5.4/5.5 VPS 的用户想要升级到刚发布的 CentOS 5.8 版本的话就更简单了,直接在命令行:

# yum update
# reboot

升级 CentOS 5.x 到 6.x

除了重装系统,没有办法从 5.x 直接升级到 6.x:

升级 Fedora 12, 13 到 14

使用 Fedora 12 VPS 的用户可以这样升级到 Fedora 14:

# rpm --import https://fedoraproject.org/static/97A1071F.txt

# yum update yum
# yum --releasever=14 distro-sync --skip-broken

升级 Debian 5 到 6

使用 Debian 5 VPS 的用户可以这样升级到 Debian 6:

# wget http://ftp-master.debian.org/keys/archive-key-6.0.asc
# apt-key add archive-key-6.0.asc
# aptitude update

# vi /etc/apt/sources.list
:%s/lenny/squeeze/g
:wq

# apt-get update
# apt-get install apt dpkg
# apt-get dist-upgrade

# reboot

升级 Debian 6 到 7

正在使用 Debian 6 的用户可以这样升级到 Debian 7:

# vi /etc/apt/sources.list
deb http://mirrors.kernel.org/debian/ wheezy main
deb-src http://mirrors.kernel.org/debian/ wheezy main

deb http://security.debian.org/ wheezy/updates main
deb-src http://security.debian.org/ wheezy/updates main

# apt-get update
# apt-get upgrade
# apt-get dist-upgrade

# reboot

需要同时设置 noatime 和 nodiratime 吗?

相信对性能、优化这些关键字有兴趣的朋友都知道在 Linux 下面挂载文件系统的时候设置 noatime 可以显著提高文件系统的性能。默认情况下,Linux ext2/ext3 文件系统在文件被访问、创建、修改等的时候记录下了文件的一些时间戳,比如:文件创建时间、最近一次修改时间和最近一次访问时间。因为系统运行的时候要访问大量文件,如果能减少一些动作(比如减少时间戳的记录次数等)将会显著提高磁盘 IO 的效率、提升文件系统的性能。Linux 提供了 noatime 这个参数来禁止记录最近一次访问时间戳。

给文件系统挂载的时候加上 noatime 参数能大幅提高文件系统性能:

# vi /etc/fstab

/dev/sda1        /             ext3     defaults,noatime,errors=remount-ro 0 0
devpts           /dev/pts      devpts   gid=5,mode=620             0 0
proc             /proc         proc     defaults                   0 0
/dev/sda2        swap          swap     defaults,noatime           0 0

修改设置后只需要重新挂载文件系统、不需要重启就可以应用新设置:

# mount -o remount /

# mount
/dev/sda1 on / type ext3 (rw,noatime,errors=remount-ro)
proc on /proc type proc (rw)
devpts on /dev/pts type devpts (rw,gid=5,mode=620)
none on /proc/sys/fs/binfmt_misc type binfmt_misc (rw)

网上很多资料都提到要同时设置 noatime 和 nodiratime,不知道这个结论来自哪里,其实不需要像设置 noatime 那样设置 nodiratime,最可靠的资料应该是源代码,VPSee 查了一下源代码,发现在内核源代码 linux-2.6.33/fs/inode.c 文件里有一个 touch_atime 函数,可以看出如果 inode 的标记位是 NOATIME 的话就直接返回了,根本就走不到 NODIRATIME 那里去,所以只设置 noatime 就可以了,不必再设置 nodiratime.

void touch_atime(struct vfsmount *mnt, struct dentry *dentry)
1405{
1406        struct inode *inode = dentry->d_inode;
1407        struct timespec now;
1408
1409        if (inode->i_flags & S_NOATIME)
1410                return;
1411        if (IS_NOATIME(inode))
1412                return;
1413        if ((inode->i_sb->s_flags & MS_NODIRATIME) && S_ISDIR(inode->i_mode))
1414                return;
1415
1416        if (mnt->mnt_flags & MNT_NOATIME)
1417                return;
1418        if ((mnt->mnt_flags & MNT_NODIRATIME) && S_ISDIR(inode->i_mode))
1419                return;
...
1435}

在 Debian 上安装和配置 Xen

SUN 每隔一段时间都会有一些服务器捐给大学、实验室、研究机构等。我们项目组就刚 “骗” 了几台免费的 Sun Fire 服务器,当然也和我们是 SUN(也许现在应该叫 Oracle)的长期客户有关,我们的服务器基本都是 SUN 的。现在只要新机器一进来就先虚拟化,虚拟化后才能上机柜,技术变化太快了,记得几年前我们买机器一上来首先装的是操作系统,现在 hypervisor 代替了操作系统。

首先最小化安装64位的 Debian,下面的安装步骤和配置过程基于 Debian 5.04 版本,CentOS 版本可以参看:在 CentOS 上安装和配置 Xen,Ubuntu 版本可以参看:在 Ubuntu 上安装和配置 Xen,OpenSolaris 版本参看:在 OpenSolaris 上安装和配置 Xen,NetBSD 版本参看:在 NetBSD 上安装和配置 Xen.

安装 Xen

检查一下 source list:

# vi /etc/apt/sources.list

deb http://http.us.debian.org/debian stable main contrib non-free
#deb http://non-us.debian.org/debian-non-US stable/non-US main contrib non-free
deb http://security.debian.org stable/updates main contrib non-free

安装 Xen 及相关工具:

# apt-get install xen-hypervisor-3.2-1-amd64 \
xen-linux-system-2.6.26-2-xen-amd64 xen-utils-3.2-1 \
xenstore-utils xenwatch xen-shell xen-tools

我们需要很多 loop devices 来挂载基于文件的虚拟机,所以需要把 loop device 的数目限制设成最大

# vi /etc/modules

loop max_loop=64

安装完 Xen 后,Debian 上的 Xen 的默认网络配置用的是 network-dummy,和 CentOS 上有点不一样,我们需要修改成 bridge 以便每个虚拟机都像一个独立机器一样运行在网络上:

# vi /etc/xen/xend-config.sxp

#(network-script network-dummy)
(network-script network-bridge)

安装成功后,检查 Xen 内核是否已经装好,并给内核加上 dom0_mem=256M 限制 Xen Dom0 的内存,防止 dom0 把内存耗光:

# vi /boot/grub/menu.lst

...
title           Xen 3.2-1-amd64 / Debian GNU/Linux, kernel 2.6.26-2-xen-amd64
root            (hd0,0)
kernel          /xen-3.2-1-amd64.gz dom0_mem=256M
module          /vmlinuz-2.6.26-2-xen-amd64 root=/dev/mapper/vpsee-root ro console=tty0
module          /initrd.img-2.6.26-2-xen-amd64
...

重启系统后检查一下是否是 Xen 的内核以及 Xen 是否启动:

# reboot

# uname -r
2.6.26-2-xen-amd64

# xm list
Name                                        ID   Mem VCPUs      State   Time(s)
Domain-0                                     0   256     2     r-----      9.3

创建和安装 guest

如果把正在运行的 Xen 内核的操作系统看成 host 的话,那么运行在 host 上面的操作系统就可以看成 guest。先建一个目录用来存放所有的 guest 操作系统的 image,vm01.img,vm02.img 等,1个 guest 对应1个 image。

# mkdir /vm

# xen-create-image --hostname=vm01 --size=10Gb --swap=512Mb --ide \
--ip=172.16.39.121 --netmask=255.255.254.0 --gateway=172.16.38.1 --force \
--dir=/vm --memory=512Mb --arch=i386 \
--kernel=/boot/vmlinuz-2.6.26-2-xen-amd64 \
--debootstrap --dist=etch --mirror=http://ftp2.de.debian.org/debian/ --password

可以根据需要调整 /etc/xen-tools/xen-tools.conf

进入 guest

安装成功后需要增加给对应的虚拟机器增加一个 Xen 配置文件以便 Xen 能启动这个虚拟机:

# vi /etc/xen/vm01

kernel      = '/boot/vmlinuz-2.6.26-2-xen-amd64'
ramdisk     = '/boot/initrd.img-2.6.26-2-xen-amd64'
memory      = '512'
root        = '/dev/xvda2 ro'
disk        = [
                  'file:/vm/domains/vm01/swap.img,xvda1,w',
                  'file:/vm/domains/vm01/disk.img,xvda2,w',
              ]
name        = 'vm01'
vif         = [ 'ip=172.16.39.121,mac=00:16:3E:C0:21:DE' ]
on_poweroff = 'destroy'
on_reboot   = 'restart'
on_crash    = 'restart'

启动刚安装的 Debian 虚拟机后就可以登录了,

# xm create vm01
# xm console vm01

如果要退出 guest 的话,用 Ctrl + ],就会回到 host。

如果想每次启动 host 时自动启动 guest 的话:

# ln -s /etc/xen/vm01 /etc/xen/auto

更懒的办法

如果觉得安装 guest 操作系统太麻烦,可以到 http://stacklet.com/ 下载一个已经装好的镜像文件,调整 Xen guest 的配置文件,然后在 host 下启动 guest 镜像就可以了,这里这里有更详细的介绍。

增加 swap

如何给 guest 系统(domU)增加 swap,这里有介绍。

配置 Squid 服务器的硬件要求

去年有台 Squid 主服务器的主板坏了,因为有备份服务器所以不碍事,这台备份服务器是一台很老的 Pentium III 级别的 PC,平时不怎么用,只有主服务器 down 掉的时候才临时应付一下。VPSee 现在要抓紧时间把那台 Squid 主服务器换掉(在备份服务器坏掉之前~~),不考虑买新机器了,去年升级留下了很多老机器,以及一些内存、硬盘等配件,相互搭配一下应该可以配出几台好机器。

Squid 服务器的性能对内存和硬盘的要求比较敏感,硬盘缓存多少数据和需要多大内存之间有某种关系,这是因为每个缓存过的 object 在内存里都保留相应的 metadata,方便 Squid 能迅速查询 cache,这些 metadata 是由 StoreEntry 数据结构来保存的,每个 StoreEntry 占用 56 Bytes,加上每个 StoreEntry 都有1个 16-byte 的 cache key,所以保存在 cache 里面的每个 object 在内存中都对应占用 72 Bytes(metadata),这是在32位机器上的情况,如果是64位机器会占用更多(104 Bytes)。算下来在硬盘上缓存 1,000,000 个 objects 的话相应需要占用 72MB 内存用来做 metadata,而实际情况则比这个要多得多。这篇 Wiki 也解释了为什么 Squid 需要大量内存。如何来决定到底需要多少内存呢?能不能有某个公式可以直接套用呢? Squid: The Definitive Guide 这本书给出了这样一个建议,每缓存 1GB 需要 32MB 内存,这样的话一台 1GB 内存的机器可以在硬盘上缓存 32GB 的数据(object)。

As rule of thumb, you need 32 MB of memory for each GB of disk space.

除了知道以上内存和硬盘的关系以外,我们还需要通过实际需求来决定什么样配置的机器能满足用户需求并且取得最佳性价比。那么如何判断需要用多大的硬盘来缓存用户的记录呢?根据去年一年使用 LightSquid 对用户的日志统计和分析,VPSee 发现绝大部分用户每天消耗都不到 100MB 带宽(平均起来才 50MB 每用户每工作日),这样如果算每人每天平均消耗 50MB,每个月算20个工作日,那么每人每月就是消耗 1GB,算下来100人每月应该消耗 100GB 带宽,也就是要缓存每个月的用户记录的话需要 100GB 硬盘空间,根据上面 1GB/32GB 的公式,一台 4GB 内存的服务器就可以完全满足要求。幸运的是,Squid 服务器对 CPU 要求不高,只需要在老机器上加点内存就可以了。

还需要注意的是,一定要再配一台 Squid 服务器作为备份服务器以应付突发事件,cache 的数据不是很重要,所以不必做 RAID,不必花钱在一些昂贵的存储设备上,但是要保证至少有一台备份 Squid 服务器 stand by,在主服务器不能工作的时候能随时替换。Squid: The Definitive Guide 的作者推荐使用 FreeBSD 作为 Squid 服务器的操作系统。

Linux 文件系统从 ext3 升级到 ext4

尽管 ext4 出来已经有一段时间了,由于有一些 bug 还没被大量应用到服务器生产环境中,不过对于桌面用户来说 ext4 已经足够成熟了。去年发布的最新 RHEL 5.4 版本默认文件系统依然是 ext3。 最近 Linux 内核开发人员、ext4 文件系统的维护者 Ted Ts’o 跳槽到 Google,并在 Google 继续从事 ext4 的研发和 Linux kernel 方面的工作。在一篇 mailing list 里,Google 工程师 Michael Rubin 也提到了一些 Google 内部使用 ext4 的情况。经过 Google 内部测试,ext4 和高性能的 xfs 文件系统性能很接近,Google 选择 ext4 而不是 xfs 的主要原因是因为他们的现有系统是 ext2,这样升级到 ext4 会更容易一些。还有一个有意思的地方是,大多数人对 dbench 很信任,选用 dbench 来做文件系统的测试工具。

如何从 ext3 升级到 ext4?首先需要确保 Linux kernel 是支持 ext4 的,其次要注意 /boot 分区最好使用 ext3,因为现在系统上的 grub 很可能不支持 ext4,需要有这个 commit 的特别版本 grub 才能支持 ext4. 用下面的命令转换:

# cd /; umount /dev/sda1
# tune2fs -O extents,uninit_bg,dir_index /dev/sda1

记住,转换成 ext4 后必须用 fsck 扫描,否则不能 mount,-p 参数说明 “自动修复” 文件系统:

# fsck -pf /dev/sda1

挂载 ext4 文件系统:

# mount -t ext4 /dev/sda1 /path/to/

Unix/Linux 下的小工具:lsof

lsof 本来是一个很普通的小工具,用来显示被进程打开的文件信息,因为在 Unix/Linux 下任何东西都是文件,所以 lsof 这个 “小” 工具就显得非常强大,常被称作 “Unix debugging 的瑞士军刀”。lsof 很好的遵循了 Unix 的哲学 “只做一件事,并把事情做好”。来看看 Unix/Linux 下被看作文件的有哪些:普通文件,目录,NFS 文件,特殊块文件,字符文件,管道,连接,各种 socket,共享文件库等,所有都是文件,所以 lsof 用途非常广泛。

列出所有进程打开的所有文件:

# lsof

列出某个程序打开的所有文件:

# lsof -c vim
# lsof -c vim -c python

列出某个用户打开的所有文件:

# lsof -u vpsee
# lsof -u vpsee, root

列出某个组(group id)打开的所有文件:

# lsof -g 1

列出某个进程(PID)打开的所有文件:

# lsof -p 1
# lsof -p 1,2,3

列出某个目录下被打开的所有文件:

# lsof +D /usr/lib

列出所有网络连接:

# lsof -i

列出所有 TCP 连接或 UDP 连接:

# lsof -i tcp
# lsof -i udp

列出谁在使用某个网络端口:

# lsof -i :22
# lsof -i :ssh

列出某个用户所有的网络连接:

# lsof -a -u vpsee -i

列出所有 NFS 文件、Unix domain socket 文件:

# lsof -N
# lsof -U