ファイルの移動(閉じている場合のみ)

ファイルの移動(閉じている場合のみ)

外部プロセスによって生成された大容量ファイルを、外部プロセスが終了したらすぐに移動したいと思います。

このテストコマンドは正しいですか?

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

編集:ファイルはデータセットを表し、他のプログラムで作業できるようにファイルを移動するには完了するまで待つ必要があります。そのため、外部プロセスがファイルを完了したかどうかを知る必要があります。

ベストアンサー1

lsofマニュアルページから

Lsofは、リストするように要求されたコマンド名、ファイル名、インターネットアドレス、またはファイル、ログイン名、NFSファイル、PID、PGID、またはUIDが見つからないなど、エラーが検出された場合は1を返します。 -V オプションが指定されている場合、lsof はリストに失敗した検索語を示します。

したがって、これはあなたのlsof failed for some other reason条件が決して実施されないことを示します。

外部プロセスでファイルが開いている間にファイルを移動してみましたか?ターゲットディレクトリが同じファイルシステム上にある場合は、3番目のプロセスの元のパスからアクセスする必要がある場合を除き、デフォルトの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

修正する

指摘したとおり@JohnWHSSmith以下の最も安全な設計は、常に上記のようにループを使用することですlsof。これは、書き込み用にファイルを開くプロセスが複数ある可能性があるためです。たとえば、読み取り/書き込みフラグを使用してファイルを開く間違って作成されたインデックスデーモンは、実際には読み取り専用です。inotifywaitしかし、まだ睡眠の代わりに使用することができます。睡眠ラインをinotifywait -e close /path/to/file

おすすめ記事