本页内容

  • Linux fuser 命令
  • 如何使用 fuser 终止进程
  • fuser – 其他细节
  • 结论

假设给你一个任务:找出正在使用某个特定文件的进程,然后逐个将它们终止——而且这一切都要在命令行中完成。你会怎么做?如果你是命令行新手,我相信你会一头雾水,四处求助。

但命令行老手大概会知道,Linux 中有一个命令行工具可以根据进程所访问的文件(目录或 sockets)来识别它们。不仅如此,该工具还允许你终止这些进程,因此你无需单独使用 kill 或 killall 命令。我们所说的这个命令行工具就是 fuser。

如果你还不了解这个工具,并想弄清楚如何使用它,那么不用再四处寻找了,因为在本文中,我们将通过一些通俗易懂的示例详细讲解 fuser。

但在继续之前,请记住,本教程中提到的所有示例、命令和说明均已在 Ubuntu 22.04 LTS 上测试过。

Linux fuser 命令

正如我上面已经提到的,fuser 命令主要用于识别正在使用文件、目录或 sockets 的进程。该工具会显示正在使用某个文件的进程的 PID,而该文件名是作为参数传递给命令的。

以下是 fuser 命令最基本的用法示例:

在 Linux 系统中使用 fuser 命令识别占用进程

从上面截图可以清楚看到,我们尝试使用 fuser 来查看哪些进程正在使用 /home/himanshu 目录,而命令在其输出中给出了一列进程 ID。到目前为止一切正常,但这里存在几个问题。

首先,每个 PID 后面附加的 'c' 是什么意思?快速查阅该命令的 man page 就会发现,在默认显示模式下,fuser 命令不仅显示正在访问该文件或目录的进程 PID,还会显示访问类型。

每种访问类型都用字母表示:

  • c - 当前目录。
  • e - 正在运行的可执行文件。
  • f - 打开的文件。在默认显示模式下 f 会被省略。
  • F - 为写入而打开的文件。在默认显示模式下 F 会被省略。
  • r - 根目录。
  • m - 通过 mmap 映射的文件或共享库。

现在回到我们讨论的示例,输出中的字母 'c' 表示,输出中列出的所有 PID 对应的进程都在以 /home/himanshu 目录作为它们的当前目录进行访问。

请记住,一个进程对某个文件或目录可以拥有多种访问类型。例如,以下输出显示,许多进程正在以当前目录和根目录的方式访问 root(/)目录。

在 Linux 系统中使用 fuser 命令识别占用进程

到目前为止,我们看到的 fuser 输出只包含进程 ID,仅此而已。如果能够同时显示进程名称,岂不是更好?为此,你需要使用 -v 命令行选项。下面是一个示例:

在 Linux 系统中使用 fuser 命令识别占用进程

接下来,若要为每个 PID 附加进程所有者的用户名,请使用 -u 命令行选项。示例如下:

在 Linux 系统中使用 fuser 命令识别占用进程

注意:如果所讨论的文件或目录位于已挂载的文件系统或块设备上,那么请使用 -m 命令行选项。man page 中这样写道:"会列出所有访问该文件系统上文件的进程。" "如果指定的是目录文件,它会自动更改为 NAME/,以使用可能挂载在该目录上的任何文件系统。"

如何使用 fuser 终止进程

既然我们已经讨论了 fuser 的基础知识,现在来谈谈我在开头提到的任务——如何使用 fuser 终止进程?我们就用一个更简单的例子来说明。我将运行一个可执行文件,并在它运行期间尝试用 fuser 终止该进程。

那么,下面是已经启动的可执行文件:

在 Linux 系统中使用 fuser 命令识别占用进程

而下面这条 fuser 命令应该能够终止由 test-fuser 可执行文件启动的进程。

fuser -v -k test-fuser

哦,在执行这条命令之前,我先说明一下:-k 命令行选项会告诉 fuser 终止正在使用该文件或目录的进程(或多个进程)。

以下是执行上述命令后发生的情况:

在 Linux 系统中使用 fuser 命令识别占用进程

从上面截图可以清楚看到,将 -k 命令行选项与 fuser 配合使用,终止了 test-fuser 进程。若要确保 fuser 命令在终止进程前先征求用户确认,请使用 -i 选项。请参见下面的示例:

在 Linux 系统中使用 fuser 命令识别占用进程

以下是使用 -k 选项时应当了解的几个重要的 fuser 相关细节:

  • 使用 -k 时,fuser 命令默认发送 SIGKILL 信号。但你可以通过 -SIGNAL 选项改变这一行为。
  • fuser 进程绝不会终止自身,但可能会终止其他 fuser 进程。

fuser – 其他细节

除了目前已提到的信息之外,还有若干其他细节值得留意。所有这些信息都可以通过查阅该命令的 man page 获得。例如,以下是 fuser 的 man page 在“Restrictions”一节中列出的内容:

       Processes accessing the same file or file system several times  in  the
       same way are only shown once.
       If the same object is specified several times on the command line, some
       of those entries may be ignored.
       fuser may only be able to gather partial information  unless  run  with
       privileges.   As  a consequence, files opened by processes belonging to
       other users may not be listed and  executables  may  be  classified  as
       mapped only.
       Installing  fuser SUID root will avoid problems associated with partial
       information, but may be undesirable for security and privacy reasons.
       udp and tcp name spaces, and UNIX domain sockets can't be searched with
       kernels older than 1.3.78.
       Accesses by the kernel are only shown with the -v option.
       The  -k  option  only  works  on processes.  If the user is the kernel,
       fuser will print an advice, but take no action beyond that.

结论

正如你现在应该已经理解的那样,fuser 是 Linux 中一个极为实用的命令行工具。好在其既不难理解,也不难使用,因此即便是新手也能轻松上手。本文没有涉及的一个方面是,该命令还能识别甚至终止运行在特定端口上的进程,这使它成为网络管理员难以忽视的工具。