lsof
マニュアルページから
Lsofは、コマンド名、ファイル名、インターネットアドレスまたはファイル、ログイン名、NFSファイル、PID、PGID、または一覧表示を要求されたUIDの特定に失敗した場合など、エラーが検出された場合に1を返します。-Vオプションが指定されている場合、lsofはリストに失敗した検索項目を示します。
したがって、それはあなたのlsof failed for some other reason
節が決して実行されないことを示唆するでしょう。
外部プロセスがまだ開いている間にファイルを移動しようとしたことがありますか?宛先ディレクトリが同じファイルシステム上にある場合、基礎となるiノードは同じままであるため、3番目のプロセスからの元のパスでアクセスする必要がない限り、それを行うことで問題はありません。そうでなければ私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
ます。スリープラインをに置き換えてください。