ファイルが完全に作成されたかどうかはどうすればわかりますか?

ファイルが完全に作成されたかどうかはどうすればわかりますか?

リモートコンピュータからいくつかのファイルが到着するのを待って到着すると、そのファイルを新しいファイルとしてキャプチャするシェルスクリプトがあります。これを行うには、次のwhileループを使用します。

while true
do

    if [ $(find ../Test_Data/local_enc* | wc -l) -eq 2 ]
    then
            break
    else
            sleep 0.001

    fi
done
cat ../Test_Data/local_enc* > ../Test_Data/All_Enc_Coords.txt

問題は、All_Enc_Coordsファイルが書き込まれたり、書き込まれないことがあることです。ファイルにデータがない場合でも、 find 関数が何らかの値を返すためだと思います。

ファイルの書き込みが成功したことを確認するには?そして、whileループでこれを指定する方法です。つまり、すべてのファイルを完全に作成して処理したいですか? ..cat以前にsleep 1を使用していましたが、ファイルが完全に書き込まれたことがわかりましたが、これを確認する方法はありますか?

答え1

リモートコンピュータからファイルを作成し、アップロードを開始する前に削除するようにできますか?

たとえば、sshを使用している場合(ftpまたはHTTP PUTを使用して同様の操作を実行できます):

ssh yourhost touch ../Test_Data/upload-in-progress
scp local_enc* yourhost:../Test_Data/
ssh yourhost rm ../Test_Data/upload-in-progress

スクリプトが何をすべきかは、アップロードされたファイルが消えるのを待つことです。これはスリープループを介して実行することも、パッケージinotifywaitの内容を使用して実行することもできますinotify-tools

注:アップロードを完了する前にリモートホストが死亡した場合、またはスクリプトが終了すると、古いアップロードファイルが残ります。私の考えでは、これはアップロードがいつ完了するかを推測して競合状態を生成するリスクよりはるかに小さい問題です(ターゲットシステムでのみ実行されるすべてのソリューションは傾向があるため)。

最初は使用することを検討しましたが、lsof | grep local_enc | wc -lこれはあなたと同じように競争が起こりやすいですfind .. | wc -l

Test_Dataディレクトリへの変更についての通知を受け取るために、または同様の使用とは異なり、inotifyそのディレクトリでファイルが作成/変更される時期はわかりますが、アップロードセッションが完了する時期はわかりません...しかし、inotifyファイルを一緒に使えます。セマフォを使用すると動作します。 inotifyは、Test_Dataディレクトリが変更されるのを待ってから、進行中のアップロードが削除されるまで待機し続けます。

また、リモートホストのアップロードスクリプトがcronで実行されている場合、古いアップロードファイルは次回実行されると自動的に変更されます。または、アップロードされたファイルinotifywaitが次のより古いと仮定するようにスクリプトを作成することもできます-t--timeout

答え2

これを達成する方法は2つあります。

  1. ファイルを作成してから2〜3分以内にファイルに触れていないことを確認してください。これにより、ファイルが完全に作成されたことがわかります。ファイルが少なくとも3分前に作成されたことを確認するには、次の手順を実行します。

    find /testfolder/filename.* -type f -mmin +3
    

    ファイルが複数ある場合は、forループを使用できます。

    for f in $(find /testfolder/filename.* -type f -mmin +3)
    do
      mv filename.* to destination
    cat ../Test_Data/local_enc* > ../Test_Data/All_Enc_Coords.txt
    done
    
  2. ファイルに予告編がある場合は、予告編レコードを読み、ファイルをカタログするタイミングを決定できます。

答え3

テストケースを使用できます。

while [[ ! -e ../Test_Data/All_Enc_Coords.txt ]]; do
  if [ $(find ../Test_Data/local_enc* | wc -l) -eq 2 ]; then
    cat ../Test_Data/local_enc* > ../Test_Data/All_Enc_Coords.txt
  else
    sleep 0.001
  fi
done

コメントによると、書き込み前にデータを含むファイルを確認すると、次のようになります。

while [[ ! -s ../Test_Data/All_Enc_Coords.txt ]]; do
  if [ $(find ../Test_Data/local_enc* | wc -l) -eq 2 ]; then
    cat ../Test_Data/local_enc* > ../Test_Data/All_Enc_Coords.txt
  else
    sleep 0.001
  fi
done

答え4

以下のコードを使用して、データがまだファイルにあることを確認しています。そうでない場合は、完全に書いてください。ループが終了し、次のプロセスが開始されます。

for (( ; ; ))
do
    bfr=$(stat -c%s "$f")
    sleep 0.5
    aftr=$(stat -c%s "$f")
    if [ $bfr -eq $aftr ];
    then
        break;
    fi
done

関連情報