2

有没有一种快速的方法(即最小化回答时间)来确定文件是否在 Linux 上打开?

假设我有一个进程在目录中写入大量文件,另一个进程在完成写入后读取这些文件,一个进程能否知道前一个进程是否仍在写入文件?

如果可能的话,基于 Python 的解决方案将是理想的。

注意:我知道我可以使用基于 FIFO / 队列的解决方案,但我正在寻找其他东西。

4

11 回答 11

10

你当然可以使用 Linux 的 INOTIFY 功能,但避免这种情况更安全:让写入过程创建读取过程肯定会忽略的文件(比如 data.tmp)。当作者完成时,它应该为读者重命名文件(比如.dat)。重命名操作保证不会有误会。

于 2012-07-10T10:35:53.947 回答
4

如果您知道写入过程的 PID,则在 Linux 中您可以简单地查询 /proc/{PID}/fd/ 并查看在那里找到的链接之一是否指向您的文件之一。

你要做的是,扫描目录,归档 fd 5(比如说)指向 /var/data/whatever/file1.log 的事实。然后将指向的文件存储到一个数组中。

此时,如果文件名在数组中,则该进程正在使用它。

所以:

import os
# Here I use PID = 31824
path="/proc/%d/fd" % 31824
openfiles   = [ os.readlink("%s/%s" % (path, fname)) for fname in os.listdir(path) ]

if whatever in openfiles:
    # whatever is used by pid 31824.
于 2012-07-10T10:36:21.457 回答
2

lsof | grep filename立刻浮现在脑海。

于 2012-07-10T10:38:39.973 回答
1

我会使用 psutil ( https://github.com/giampaolo/psutil ),它还具有跨平台的优势并提供许多其他有用的系统功能。

于 2012-07-10T10:36:35.163 回答
1

如果您可以更改“第一个”流程逻辑,那么简单的解决方案是将数据写入临时文件并在写入所有数据后重命名该文件。

于 2012-07-10T10:36:40.443 回答
1

您有多种选择:

  • Inotify是一项允许您监视文件操作的功能
  • 写入过程在完成写入后重命名文件
  • 程序fuser将让您查询文件是否正在使用
  • 知道 writer 的 PID 可以让您查询/proc/PID/fd打开的文件描述符。
于 2012-07-10T10:41:11.860 回答
1

如果您知道(或可以找到)编写进程的进程 ID,则可以使用 psutil 库。sudo pip install psutil去图书馆。文档在这里: http: //pythonhosted.org/psutil/

>>> import psutil
>>> import os
>>> p = psutil.Process(os.getpid())
>>> p.open_files()
[]
>>> f = open('foo.txt', 'w')
>>> p.open_files()
[openfile(path='/Users/mariaz/Downloads/foo.txt', fd=3)]

如果您无权访问编写过程,则需要以 root 身份运行 lsof 并自己解析输出。

于 2012-07-10T10:45:25.927 回答
1

这是使用 inotify 的解决方案。在写入操作后,您将收到关于目录中每个文件被关闭的通知。

import os
import pyinotify

def Monitor(path):
    class PClose(pyinotify.ProcessEvent):
        def process_IN_CLOSE(self, event):
            f = event.name and os.path.join(event.path, event.name) or event.path
            print 'close event: ' + f

    wm = pyinotify.WatchManager()
    notifier = pyinotify.Notifier(wm, PClose())
    wm.add_watch(path, pyinotify.IN_CLOSE_WRITE)

    try:
        while 1:
            notifier.process_events()
            if notifier.check_events():
                notifier.read_events()
    except KeyboardInterrupt:
        notifier.stop()
        return

if __name__ == '__main__':
    path = "."
    Monitor(path)

但是,由于您是控制编写文件的进程的人,因此我会投票支持涉及进程之间某种通信的不同解决方案。

于 2012-07-10T10:50:32.873 回答
0

可以查看文件的修改时间,看看是否有一段时间没有被修改。由于文件可以在更新模式下打开并随时修改,因此您不能 100% 确定它永远不会被修改。

于 2012-07-10T10:36:01.687 回答
0

您可以将lsof子进程一起使用

(output,error) = subprocess.Popen("lsof #absolute_file_path").communicate()
于 2012-07-10T10:40:23.820 回答
0

您可以使用 fcntl 模块,afaik,它具有与 C 函数相同的 fcntl 函数,所以类似的东西fcntl(fd, F_GETFL)可能有用,但我不确定。您可以通过以写入模式打开目标文件来检查目标文件是否被阻止写入?

于 2012-07-10T11:00:44.457 回答