外部プロセスで作成された大きなファイルを閉じたらすぐに移動したい。
このテストコマンドは正しいですか?
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
manページから
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
ループを使用します(例本当に読み取り専用である必要があるときに、読み取り/書き込みフラグでファイルを開く、不十分に作成されたインデックス作成デーモンである可能性があります。ただし、スリープの代わりにinotifywait
を使用できます。スリープ行をinotifywait -e close /path/to/file
に置き換えてください。
代替アプローチとして、これはパイプの完璧なケースです。2番目のプロセスは最初のプロセスからの出力を次のように処理します。利用可能になり次第、プロセス全体が完了するのを待つのではなく、
process1 input_file.dat | process2 > output_file.dat
利点:
パイプを直接作成する方法はないがGNU coreutilsがある場合は、次のように使用できます。
tail -F -n +0 input_file.dat | process2 > output_file.dat
これにより、入力ファイルの読み取りが最初から開始されます最初のプロセスがファイルの書き込みを介して(たとえまだ開始されていないか、すでに完了していても)。