Linux
移動文件,但僅當它已關閉時
我想在外部程序關閉後立即移動由外部程序創建的大文件。
這個測試命令正確嗎?
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
.