如何确定哪个进程在 Linux 中打开了文件?

Dan*_*nny 138 linux

我想确定哪个进程拥有锁定文件的所有权。锁定文件只是一个已创建的具有特定名称的文件。

那么,如何确定哪个进程在 Linux 中打开了特定文件?最好是单行类型或特定的 Linux 工具解决方案是最佳的。

小智 147

在大多数 Linux 系统上可以lsof NAME完成这项工作:

fin@r2d2:~$ lsof /home/fin
COMMAND   PID USER   FD   TYPE DEVICE SIZE    NODE NAME
bash    21310  fin  cwd    DIR    8,1 4096 5054467 /home/fin
lsof    21320  fin  cwd    DIR    8,1 4096 5054467 /home/fin
lsof    21321  fin  cwd    DIR    8,1 4096 5054467 /home/fin
fin@r2d2:~$
Run Code Online (Sandbox Code Playgroud)

  • 如果你没有 lsof 怎么办? (4认同)
  • @JoseLSegura:我假设您足智多谋,答案“然后安装 lsof”对您毫无用处。你能详细说明你的问题吗?如果您没有 root 用户,您可能没有权限查看其他用户是否打开了该文件。 (3认同)

Nat*_*man 63

您也可以fuser为此使用:

~> less .vimrc
# put in background
~> fuser .vimrc
.vimrc:              28135
~> ps 28135
  PID TTY      STAT   TIME COMMAND
28135 pts/36   T      0:00 less .vimrc
Run Code Online (Sandbox Code Playgroud)

  • 热熔器有退出代码的奇怪行为。它返回 1 个有两种状态的退出代码:A/ 一些内部错误,未找到检查的文件等,B/ 没有进程打开指定的文件。在情况 A/ 中,一些错误消息会打印到其输出中。不幸的是,当文件可用并被某些东西打开时,会生成输出但退出代码为 0。如果 fuser 以三个代码退出会更好,而不是像当前那样两个。lsoft 是一个更糟糕的解决方案,因为它的工作速度更慢。 (2认同)

mar*_*guy 9

打开文件不是锁,因为如果每个进程都必须先检查文件是否打开,如果是,则不继续,如果不是,则创建/打开它,那么两个进程可以很好地同时检查,都可以找到它没有打开,然后创建或打开它。

要将文件用作锁,检查和锁定操作必须是一个不可中断的操作。您可以在 Unix 文件系统中通过创建一个只读模式的文件并将其删除以解锁来实现这一点。如果文件存在(并且是只读的),则文件创建将失败,因此您可以在单个原子操作中获得检查和锁定。

如果您的锁定进程是一个将作为守护进程运行的 shell 脚本,您可以通过使用 来获得此效果,这是umask一个每进程设置,用于设置创建新文件的权限:

oldumask=$(umask)
umask 222 # 也创建所有者不可写的文件
如果回声 $$ > /var/lock/foo
然后
    : 锁定成功
别的
    : 锁定失败
菲
umask $oldumask
这也会将拥有进程的 PID 写入文件,从而解决您的其他问题: cat /var/lock/foo
至于具体问题“哪个进程打开了这个文件?”,当您想卸载文件系统但不能因为某些进程在其中打开文件而无法卸载时,这可能很有用。如果您没有这些命令可用,您可以/proc以 root 身份询问:

ls -l /proc/*/cwd | grep '/var/lock/foo$'

或者,作为凡人用户:

ls -l /proc/*/cwd 2>/dev/null | grep '/var/lock/foo$'


小智 7

如果您想知道哪个确切进程的文件描述符链接到您的文件,而无需使用lsoffuser— 搜索/proc

$ find /proc -regex '\/proc\/[0-9]+\/fd\/.*' -type l -lname "*$1*" -printf "%p -> %l\n" 2> /dev/null
Run Code Online (Sandbox Code Playgroud)

替换$1为您正在搜索的打开文件名。您可以修改-printf任何您想查看的内容,或输入egrep -o '[0-9]+' | head -1以用于该进程的信息。ps -Fp <pid>

在通过@fin答案是最好的答案,很明显,但答案@ JoseLSegura的评论,如果这是不可用,解决以上是我的响应。$ lsof <filename>