解决分区卸载问题

识别正在使用挂载的文件系统的进程

为了干净地关闭或热交换 UNIX® 或类 UNIX 系统上的存储硬件,必须能够卸载使用此设备上的存储的所有文件系统。但是,如果正在使用文件系统中的文件或目录,就无法卸载它。lsoffuser 命令可以帮助您识别并终止那些正在使用存储设备上的文件或从存储设备执行的进程。使用这些命令有助于寻找那些阻止存储设备卸载的进程,减少麻烦,让您能够继续处理更重要的系统管理任务。

William von Hagen, 系统管理员,作家, WordSmiths

William von Hagen 担任 UNIX 系统管理员已经超过 20 年,并从 1993 年开始成为 Linux 爱好者。Bill 是一些图书的作者或合著者,涉及的主题包括 Ubuntu Linux、Xen Virtualization、GNU Compiler Collection (GCC)、SuSE Linux、Mac OS X、Linux 文件系统和 SGML。他还为 Linux 和 Mac OS X 出版物和网站撰写了许多文章。



2009 年 11 月 30 日

所有计算机操作系统都在引导时检查它们挂载的文件系统是否是一致的,也就是说,确认它们的内部数据结构和映射到的相关存储没有错误。UNIX、Linux® 和其他类 UNIX 操作系统采用一种聪明的方法检查文件系统的一致性(通常使用 fast 命令)。当这些系统挂载文件系统时,它们在文件系统头中设置一个值,把文件系统标为 DIRTY,这意味着它正在使用,在向它写入更新时可能暂时处于不一致的状态。在系统关闭期间卸载文件系统时,把它们标为 CLEAN。在重新引导系统时,只需要检查仍然标为 DIRTY 的文件系统的一致性。

在系统关闭过程中,会自动地卸载文件系统,这通常在终止所有非系统进程之后进行。但是,卸载文件系统仍然可能失败并显示以下消息:

$ sudo umount /mnt/NAS
umount: /mnt/NAS: device is busy

在这里,busy 意味着一个进程正在写这个文件系统或者进程是从它运行的。在这两种情况下,都无法卸载文件系统,这是计算机系统的基本规则之一。如果不采用这个规则,可以在进程正在写文件系统包含的文件时卸载文件系统,就会让文件处于不一致的状态,而文件系统本身标为 CLEAN

umount 命令的标准 Linux 版本包含一个延迟卸载选项 -l,它有助于卸载正在使用的文件系统。这个命令需要 Linux 内核 2.4.11 或更高版本,目前这通常没问题。执行 umount -l /name/of/file system 可以让指定的文件系统与系统的目录层次结构脱离,让新进程不能使用这个文件系统,然后当正在访问它的所有进程都终止时卸载它。这很方便,但是当需要马上卸载文件系统时它并不合适。

如果需要马上卸载文件系统,而文件系统报告忙碌,还有其他办法。如果您是系统的惟一用户,那么只需终止阻止文件系统卸载的进程。这需要查看所有窗口,寻找并终止正在写这个分区或使用它作为当前工作目录的暂停的进程或后台进程。但是,在有许多本地用户和远程用户的多用户系统上,这种方法是不实际的。幸运的是,开放源码社区提供了一些命令,可以轻松地识别并终止这些进程。

lsof 寻找打开的文件

lsof (list open files) 命令列出特定的文件系统、目录或设备上所有打开的文件以及与它们相关联的进程。在大多数 UNIX 和类 UNIX 系统上都可以使用 lsof 命令,包括 IBM® AIX®、Berkeley Software Distribution (BSD®)、Hewlett Packard UNIX (HP-UX®)、Linux 和 Solaris®。关于获取适合自己系统的 lsof 的信息请参见 参考资料

在默认情况下,lsof 命令列出当前打开的所有文件、共享库和目录,并提供尽可能多的相关信息。即使在负载很轻的系统上,这个命令的输出也非常长,因此通常通过命令行参数指定一个目录名,或者使用管道筛选它的输出。例如,假设希望卸载挂载在 /opt2 目录上的文件系统。为了查看与 /opt2 目录相关联的所有进程,应该执行 清单 1 所示的命令。

清单 1. 与一个挂载的文件系统相关联的进程
$ lsof /opt2
COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
bash    23334  wvh  cwd    DIR   8,17     4096    2 /opt2
more    23402  wvh  cwd    DIR   8,17     4096    2 /opt2
more    23402  wvh    3r   REG   8,17    10095  264 /opt2/resume.txt

需要终止所有这些进程,然后才能卸载 /opt2 分区。因为这个列表中的进程都不能写任何文件,所以可以使用 kill 命令并指定第二列中列出的进程 ID (PID) 以终止它们,然后就可以顺利地卸载分区。注意,PID 23402 与最后两行相关联 — 第一行表示 more 命令以 /opt2 作为当前工作目录 (cwd),第二行表示 more 命令打开了 /opt2/resume.txt 文件。

但是,假设 lsof 命令的输出像 清单 2 这样。

清单 2. 与一个挂载的文件系统相关联的另一组进程
$ lsof /opt2
COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
bash    23334  wvh  cwd    DIR   8,17     4096    2 /opt2
more    23402  wvh  cwd    DIR   8,17     4096    2 /opt2
more    23402  wvh    3r   REG   8,17    10095  264 /opt2/resume.txt
bash    21343  djf  cwd    DIR   8,17     4096    2 /opt2
emacs   21405  djf  cwd    DIR   8,17     4096    2 /opt2

前三个与 /opt2 目录相关联的命令与前面一样,但是后两个命令是由另一个用户运行的。其中的 emacs 命令用于编辑文件,所以可以让 USER 列中列出的用户保存文件并退出,然后终止这个进程。


定制 lsof 的输出

前一节演示了如何识别本地设备上打开的文件和目录,对于挂载的远程文件系统也很容易获得相同的信息。

为了让本文中的示例保持一致,所有命令和输出示例都引用 清单 3 所示的系统中的分区。

清单 3. 本文使用的文件系统
$ df
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/sda1            230528596 201462232  17356188  93% /
/dev/sdb1            240362656  12533532 215619324   6% /opt2
//nas.vonhagen.org/writing  
                     100790048  75945920 197241926  80% /mnt/NAS
192.168.6.166:/mnt/disk1
                     714854640 386972432 291569696  58% /mnt/yellowmachine

清单 3 所示,/mnt/NAS 是一个名为 writing 的 Samba 共享的挂载点,这个共享位于设备 nas.vonhagen.org 上。在 lsof 命令中作为参数指定这个挂载点的名称,就会产生与 清单 2 相似的输出,但是输出只针对这个设备和目录,见 清单 4

清单 4. 与远程文件系统相关联的进程
$ lsof /mnt/NAS
COMMAND   PID     USER   FD   TYPE DEVICE SIZE    NODE NAME
bash    23236 wvh  cwd  DIR   0,27 4096 6406145 /mnt/NAS/writing \
   (nas.vonhagen.org:/writing)

lsof 命令还提供其他选项,可以把输出限制为只报告在特定类型的设备上打开的文件和目录。例如,如 清单 3 所示,/mnt/yellowmachine 目录是 192.168.6.166 设备上的 /mnt/disk1 目录的 Network File System (NFS) 挂载点。可以在 lsof 命令中作为参数指定这个设备的挂载点名称,见 清单 5

清单 5. 与远程 NFS 文件系统相关联的进程
$ lsof /mnt/yellowmachine
COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
bash    23334  wvh  cwd    DIR   0,23     4096    2 /mnt/yellowmachine \
   (192.168.6.166:/mnt/disk1)

也可以使用 lsof 命令的 -N 选项只列出挂载的 NFS 设备上正在使用的文件和目录,见 清单 6

清单 6. 与挂载的所有 NFS 分区相关联的进程
$ lsof -N
COMMAND     PID USER   FD   TYPE DEVICE SIZE/OFF   NODE NAME
bash      23334  wvh  cwd    DIR   0,23     4096      2 /mnt/yellowmachine
  (192.168.6.166:/mnt/disk1)

lsof 命令还有许多选项,可以帮助您识别不同类型的文件系统上打开的文件和目录、打开了网络套接字的进程、正在使用特定的库的进程等等。lsof 命令的缺点是,必须联系用户并要求他们终止某些进程,或者自己手工终止它们。fuser 命令更复杂,但是更强大,在作为根用户运行时可以替您执行许多进程终止工作。


fuser 寻找用户进程

fuser (find user processes) 命令也是一个开放源码应用程序,可以帮助您识别阻止文件系统卸载的进程。fuser 命令寻找与作为命令行参数指定的文件、目录或文件系统相关联的进程。本文主要关注对文件系统挂载点使用 fuser。关于 fuser 命令的更多信息,请参见它的在线参考信息。fuser 命令要求系统支持 /proc 文件系统。因此,在所有 Linux 发行版和 FreeBSD 系统上都可以使用它。关于获得 fuser 命令的源代码的方法请参见 参考资料

lsof 命令一样,作为命令行参数提供文件系统挂载点名称是使用 fuser 命令识别阻止文件系统卸载的进程的最简单方法:

$ fuser /mnt/yellowmachine
/mnt/yellowmachine:  23334c 23697c

fuser 命令的输出指出正在使用指定挂载点的进程的 PID。每个 PID 后面有一个字母,它表示与 PID 相关联的进程以什么方式使用指定的挂载点。最常见的字母是前面示例所示的 c,这表示指定的进程使用此文件系统上的一个目录作为当前工作目录。

但是,fuser 命令的默认输出不便于最终用户使用,即使按 Linux 标准来看也是如此。fuser 命令提供一个 -v 选项,它在 fuser 命令的输出中增加一些与标准 ps 命令相似的输出,见 清单 7

清单 7. 挂载的 NFS 文件系统上的用户进程
$ fuser -v /mnt/yellowmachine
                     USER        PID ACCESS COMMAND
/mnt/yellowmachine:  wvh       23334 ..c.. bash
                     wvh       23697 ..c.. emacs

这更方便,因为它至少指出了进程是什么程序。在通过 fuser 命令获得 PID 信息之后,可以在终止进程之前结合使用标准的 psegrep 命令了解尽可能详细的相关信息,见 清单 8

清单 8. 在系统上搜索特定的进程
# ps alxww |egrep '23334|23697'
4 1000 23334 23332 20 0 18148  2076 wait   Ss pts/13  0:00 -bash
0 1000 23697 23334 20 0 75964 12352 poll_s S+ pts/13  0:00 emacs -nw file2.txt
0    0 23703 23665 20 0  6060   632 -      R+ pts/16  0:00 egrep
23334|23697

然后,可以使用标准的 kill 命令手工终止指定的进程,或者像下一节中解释的,使用 fuser 命令的一些高级功能自动地终止它们。


fuser 终止进程

在通过参数指定挂载点时,fuser 命令的 -k 选项会自动地终止找到的进程。当然,必须作为根用户执行 fuser 命令,才能终止属于其他用户的进程,见 清单 9

清单 9. 终止与挂载的 NFS 文件系统相关联的进程
# fuser -k /mnt/yellowmachine
/mnt/yellowmachine:  23334c 23697c
Could not kill process 23697: No such process

在这里,第二个进程 (emacs) 是第一个进程 (bash shell) 的子进程,因此在 fuser 命令杀死第一个进程时它就会终止。

如果希望指定底层物理设备名,而不是它包含的文件系统的挂载点,那么还必须指定 -m 选项,见 清单 10

清单 10. 挂载点和设备的进程列表
# fuser -v /opt2
                     USER        PID ACCESS COMMAND
/opt2:               wvh       23712 ..c.. bash
                     wvh       23753 ..c.. emacs
# fuser -v /dev/sdb1
# fuser -vm /dev/sdb1
                     USER        PID ACCESS COMMAND
/dev/sdb1:           wvh       23712 ..c.. bash
                     wvh       23753 ..c.. emacs

第一个命令返回的输出符合预期,因为它引用文件系统的挂载点。第二个命令表明,不能使用标准的 fuser 选项直接查询底层设备。第三个命令说明,-m 选项允许直接指定设备。可以在第一个和第三个命令中添加 -k 选项,从而终止与 /dev/sdb1 设备上的文件系统相关联的进程。


结束语

有时候,为了应对一些紧急情况或者删除挂载的 CD-ROM 或 DVD 等设备,Linux 或 UNIX 系统管理员需要卸载分区。在由于设备忙系统不允许删除它的情况下,检查系统上的所有进程是一个很烦人、很缓慢的过程。lsoffuser 命令有助于识别阻止文件系统卸载的进程。如果情况非常紧急,fuser 命令甚至可以替您终止它们。

参考资料

学习

  • AIX and UNIX 专区:developerWorks 的“AIX and UNIX 专区”提供了大量与 AIX 系统管理的所有方面相关的信息,您可以利用它们来扩展自己的 UNIX 技能。
  • AIX and UNIX 新手入门:访问“AIX and UNIX 新手入门”页面可了解更多关于 AIX 和 UNIX 的内容。
  • AIX and UNIX 专题汇总:AIX and UNIX 专区已经为您推出了很多的技术专题,为您总结了很多热门的知识点。我们在后面还会继续推出很多相关的热门专题给您,为了方便您的访问,我们在这里为您把本专区的所有专题进行汇总,让您更方便的找到您需要的内容。
  • 技术书店 浏览关于这些主题和其他技术主题的图书。

获得产品和技术

  • 在大多数 Linux 系统上都默认安装了 lsof 命令,还可以从这些发行版使用的存储库获得 lsof 的源代码包。可以通过匿名 File Transfer Protocol (FTP) 协议从 lsof.itap.purdue.edu 的 pub/tools/unix/lsof 目录获得 lsof 的最新版本。可以从 FTP URL ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof 获得 lsof
  • fuser 命令是 PSmisc 包 的一部分,这个包还包含 pstreekillall 等命令。
  • Linux Foundation 提供一个称为 Forced Unmount(或 fumount)的简单脚本,它尝试自动地执行许多次 fuser 命令和适当的卸载命令,从而强制卸载指定的分区。

讨论

条评论

developerWorks: 登录

标有星(*)号的字段是必填字段。


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件

 


在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。

所有提交的信息确保安全。

选择您的昵称



当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

标有星(*)号的字段是必填字段。

(昵称长度在 3 至 31 个字符之间)

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

 


所有提交的信息确保安全。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=AIX and UNIX
ArticleID=450851
ArticleTitle=解决分区卸载问题
publish-date=11302009