如何确定在Linux中打开文件的进程?


124

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

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

Answers:


55

您也可以使用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

很棒,但是要在脚本中使用它,我必须检查输出长度。
chovy

输出长度是什么意思?
内森·菲尔曼

if [ 热熔器“ $ file”`]; 然后退出`
chovy

1
热熔器的退出代码行为异常。它返回1个退出代码,并具有两种状态:A /一些内部错误,未找到检查的文件等,B /没有进程打开指定的文件。在情况A /中,一些错误消息被打印到其输出。不幸的是,当文件可用并通过某种方式打开时,将生成输出,但退出代码为0。如果热熔器将退出时使用三个代码(而不是当前的两个代码)会更好。lsoft的解决方法较差,因为它的运行速度较慢。
Znik

这基本上是相同的模式ls-如果出现错误(例如,指定了无效的选项)找不到文件(如果成功报告信息,则返回0 ),它将返回退出代码2 。
斯科特

144

在大多数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:~$

4
如果没有lsof,该怎么办?
JoseLSegura

3
@JoseLSegura:我假设您足够机智,回答“然后安装lsof”对您毫无用处。您能详细说明您的问题吗?如果您没有root用户,则可能没有priv来查找其他用户是否以任何方式打开了文件。
Michael Scheper 2015年

这似乎不适用于文件,仅适用于目录
Jason,

@Jason:它确实适用于文件,但是cwd行(报告用作进程的当前工作目录)仅报告目录。
reinierpost

9

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

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

如果锁定过程是将作为守护程序运行的Shell脚本,则可以通过使用umask逐个进程设置来设置设置新文件的权限,从而获得这种效果:

oldumask = $(umask)
umask 222#创建也对所有者不可写的文件
如果echo $$> / 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$'


ls -l方法适用于Linux,但似乎不适用于CygWin:那里没有有关文件锁定的信息。你不知道该怎么解决吗?谢谢。
Sopalajo de Arrierez 2014年

不,您不会为锁定创建只读文件,因为当您的应用崩溃时,该文件仍将存在。在您崩溃的应用后,强迫用户清除这些废话。
polkovnikov.ph

6

如果您想知道哪个确切的进程的文件描述符链接到您的文件,而无需lsoffuser-通过/proc以下方式搜索:

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

$1您要搜索的打开的文件名替换。您可以修改显示-printf的内容,或egrep -o '[0-9]+' | head -1将其用于该流程的信息。ps -Fp <pid>

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


2

我发现使用接受的答案未列出正在使用我的目录(ubuntu 14.04)的进程。

最后,我使用了lsof(列出打开的文件)并对其输出进行grep查找,以找出令人讨厌的过程:

lsof | egrep "<regexp-for-your-file>"

一种更清洁,更快的使用方法lsof是它的选择-R。例如: lsof -R [filename]
tron5
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.