2012-07-10 40 views
2

有沒有一種快速的方法(即最小化回答問題的時間)來確定文件是否在Linux上打開?知道文件是否在Linux上打開的快速方法?

比方說,我有一個寫入噸目錄中的文件的過程,而另一進程讀取這些一旦他們寫完的文件,可以在後面的過程中知道,如果一個文件仍在由前寫入處理?

如果可能,基於Python的解決方案將是理想的。

注:我知道我可以使用基於FIFO /隊列的解決方案,但我正在尋找別的東西。

+0

由於您想觀察文件系統的變化,因此inotify可能是答案。我沒有自己測試過,但也許這與你的問題有關http://ubuntuforums.org/showthread.php?t=663950 – pwuertz 2012-07-10 10:35:20

+0

很好的問題,很多不同的答案。有了更多的信息,選擇領跑者解決方案可能會更容易。 – MattH 2012-07-10 10:46:09

+0

我已經得到了每個階段生成的10,000個文件,我希望能夠快速找到已處理的文件,並將這些文件交給進程#2。 – jldupont 2012-07-10 10:51:15

回答

8

你當然可以使用Linux的INOTIFY特性,但避免這種情況比較安全:讓寫入過程創建讀取過程肯定會忽略的文件(比如data.tmp)。當作者完成時,它應該重命名讀者的文件(比如說.dat)。重命名操作保證不會有誤解。

+0

+1以提示inotify。 – tuxuday 2012-07-10 10:41:31

+0

+1用於提示tmpfiles和inotify – MattH 2012-07-10 11:00:30

0

您可以檢查文件的修改時間並查看它是否在一段時間內未被修改。由於文件可以在更新模式下打開並隨時修改,因此不能100%確定它永遠不會被修改。

+1

正如您所提到的,這不是一種可靠的方法。此外,在文件元數據被更新之前,有時可能會提交數據改變,例如, [fdatasync](http://linux.die.net/man/2/fdatasync)。 – MattH 2012-07-10 10:51:25

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. 
1

如果您可以更改「第一個」進程邏輯,那麼簡單的解決方案是將數據寫入臨時文件,並在寫入所有數據後重命名該文件。

1

lsof | grep filename立刻浮現在腦海。

0

可以使用lsof的

(output,error) = subprocess.Popen("lsof #absolute_file_path").communicate() 
1

您提供多種選擇:

  • Inotify是一種功能,可以讓你觀看的文件操作
  • 寫作過程在完成寫作時重命名文件
  • 程序fuser將讓您查詢文件是否正在使用
  • 瞭解作者的PID可能會讓您查詢打開文件描述符的/proc/PID/fd
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)] 

如果你沒有進入寫作過程中,你需要lsof的root運行,解析輸出自己。

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) 

但是,因爲你是一個在過程的控制是寫我會投票給涉及某種形式的進程間通信的不同的解決方案中的文件。

0

你可以使用fcntl模塊afaik,它具有與C函數相同的fcntl函數,所以類似fcntl(fd, F_GETFL)可能會有用,但我不確定。你可以通過在寫模式下打開目標文件來阻止寫入嗎?

相關問題