GNU/Linux >> Linux の 問題 >  >> Linux

ファイルを移動するが、それが閉じている場合のみ

lsof から マニュアルページ

<ブロック引用>

コマンド名、ファイル名、インターネットアドレスまたはファイル、ログイン名、NFS ファイル、PID、PGID、またはリストするように要求された UID を見つけられなかったなどのエラーが検出された場合、Lsof は 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 ただし、sleep の代わりに使用することはできますが、sleep 行を inotifywait -e close /path/to/file に置き換えるだけです。 .


別のアプローチとして、これは パイプ の完璧なケースです - 2 番目のプロセスは、プロセス全体が終了するのを待つのではなく、最初のプロセスからの出力が利用可能になるとすぐに処理します:

process1 input_file.dat | process2 > output_file.dat

利点:

  • 全般的に高速:
    • ディスクへの書き込みと読み取りを行う必要はありません (これは、RAM ディスクを使用すると回避できます)。
    • マシン リソースをより完全に使用する必要があります。
  • 終了後に削除する中間ファイルはありません。
  • OP のように複雑なロックは必要ありません。

パイプを直接作成する方法がないが、GNU coreutils がある場合 これを使用できます:

tail -F -n +0 input_file.dat | process2 > output_file.dat

これにより、入力ファイルの最初からの読み取りが開始されます。 どこまで 最初のプロセスはファイルの書き込みです (まだ開始されていない、または既に終了している場合でも)。


Linux
  1. 画面にStderrのみを表示しますが、StdoutとStderrの両方をファイルに書き込みますか?

  2. まだファイルにない場合にのみ、ファイルに行を追加します

  3. ファイルがシェルスクリプトに存在する場合にのみ移動する

  1. Linuxターミナルでファイルを移動する

  2. ファイルを作成しているプロセスを特定する方法は??

  3. Faclは「x」権限を無視しますが、ファイルのみですか?

  1. Linux –ファイルパーミッションは実行のみですか?

  2. .gzファイルを解凍してテキストファイルを取得しますが、バイナリファイルを取得しますか?

  3. Zshで、完了をキャンセルしますが、完了のみですか?