파일이 완전히 작성되었는지 어떻게 알 수 있나요?

파일이 완전히 작성되었는지 어떻게 알 수 있나요?

원격 컴퓨터에서 일부 파일이 도착할 때까지 기다리고 도착하면 해당 파일을 새 파일로 캡처하는 쉘 스크립트가 있습니다. 이를 위해 다음과 같은 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

이를 달성하는 방법에는 두 가지가 있습니다.

  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

관련 정보