파일 이동(닫혀 있는 경우에만)

파일 이동(닫혀 있는 경우에만)

외부 프로세스에서 생성된 대용량 파일을 외부 프로세스가 종료되는 즉시 이동하고 싶습니다.

이 테스트 명령이 맞나요?

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조건이 결코 시행되지 않음을 나타냅니다.

외부 프로세스에서 파일이 열려 있는 동안 파일을 이동해 보셨나요? 대상 디렉터리가 동일한 파일 시스템에 있는 경우 세 번째 프로세스의 원래 경로에서 액세스해야 하는 경우를 제외하고는 기본 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.

답변2

대안으로 이것은 완벽한 사례입니다관로- 두 번째 프로세스는 전체 프로세스가 완료될 때까지 기다리지 않고 첫 번째 프로세스의 출력이 사용 가능해지면 즉시 처리합니다.

process1 input_file.dat | process2 > output_file.dat

이점:

  • 일반적으로 훨씬 빠릅니다.
    • 디스크에 쓰고 읽을 필요가 없습니다(램디스크를 사용하면 이를 피할 수 있습니다).
    • 기계 자원을 더욱 완벽하게 활용해야 합니다.
  • 완료되면 중간 파일을 삭제할 필요가 없습니다.
  • OP처럼 복잡한 잠금이 필요하지 않습니다.

파이프라인을 직접 생성할 수는 없지만GNU 핵심 도구다음을 사용할 수 있습니다.

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

입력 파일을 처음부터 읽습니다.아무리 멀리 있어도첫 번째 프로세스는 파일에 쓰는 것입니다(아직 시작되지 않았거나 완료된 경우에도 마찬가지).

관련 정보