Linux

移動文件,但僅當它已關閉時

  • April 17, 2016

我想在外部程序關閉後立即移動由外部程序創建的大文件。

這個測試命令正確嗎?

if lsof "/file/name"
then
       # file is open, don't touch it!
else
       if [ 1 -eq $? ]
       then
               # file is closed
               mv /file/name /other/file/name
       else
               # lsof failed for some other reason
       fi
fi

編輯:該文件代表一個數據集,我必須等到它完成才能移動它,以便另一個程序可以對其進行操作。這就是為什麼我需要知道外部程序是否已完成文件的原因。

lsof手冊頁

如果檢測到任何錯誤,包括未能找到命令名稱、文件名、Internet 地址或文件、登錄名、NFS 文件、PID、PGID 或要求列出的 UID,Lsof 將返回一 (1)。如果指定了 -V 選項,lsof 將指示它未能列出的搜尋項。

所以這表明你的lsof failed for some other reason條款永遠不會被執行。

您是否嘗試過在外部程序仍然打開文件時移動文件?如果目標目錄在同一個文件系統上,那麼這樣做應該沒有問題,除非您需要在第三個程序的原始路徑下訪問它,因為底層 inode 將保持不變。否則我認為mv無論如何都會失敗。

如果你真的需要等到你的外部程序處理完文件,你最好使用阻塞命令而不是重複輪詢。在 Linux 上,您可以使用inotifywait它。例如:

inotifywait -e close_write /path/to/file

如果您必須使用lsof(也許是為了便攜性),您可以嘗試以下方法:

until err_str=$(lsof /path/to/file 2>&1 >/dev/null); do
 if [ -n "$err_str" ]; then
   # lsof printed an error string, file may or may not be open
   echo "lsof: $err_str" >&2

   # tricky to decide what to do here, you may want to retry a number of times,
   # but for this example just break
   break
 fi

 # lsof returned 1 but didn't print an error string, assume the file is open
 sleep 1
done

if [ -z "$err_str" ]; then
 # file has been closed, move it
 mv /path/to/file /destination/path
fi

更新

正如下面@JohnWHSmith所指出的,最安全的設計將始終使用上述lsof循環,因為有可能多個程序會打開文件以進行寫入(範例情況可能是編寫不佳的索引守護程序,它打開文件時讀取/write 標誌,當它真的應該是只讀的)。inotifywait仍然可以用來代替睡眠,只需將睡眠線替換為inotifywait -e close /path/to/file.

引用自:https://unix.stackexchange.com/questions/176387