루프 스크립트에 대한 쿼리가 병렬로 다시 실행 중입니다.

루프 스크립트에 대한 쿼리가 병렬로 다시 실행 중입니다.

쉘 스크립트에 다음이 있습니다.

for file in $local_dir/myfile.log.*; 
    do 
        file_name=$(basename $file); 
        server_name=$(echo $file_name | cut -f 3 -d '.');
        file_location=$(echo $file);

        mv $file_location $local_dir/in_progress1.log

        mysql -hxxx -P3306 -uxxx -pxxx -e "set @server_name='${server_name}'; source ${sql_script};"

        rm $local_dir/in_progress1.log
    done

기본적으로 기준과 일치하는 디렉터리의 모든 파일을 가져오고, 처리를 위해 MySQL 스크립트에 전달하기 전에 파일 이름에서 서버 이름을 추출합니다.

내가 궁금한 것은 완료하는 데 각각 60초가 걸리는 10개의 파일이 있고 5분 후에 쉘 스크립트의 두 번째 인스턴스를 시작하는 것입니다.

  • a) 두 번째 스크립트는 아직 처리되지 않은 파일을 볼 수 있습니까?
  • b) 파일을 삭제하면 첫 번째 인스턴스에 문제가 발생합니까?

아니면 문제 없이 병렬로 실행할 수 있나요?

답변1

"60초"(그리고 심지어 "5분")도 좋은 추정치일 뿐이며, 두 번째 배치가 시작될 때 첫 번째 배치가 여전히 진행 중일 위험이 있다고 가정합니다. 배치를 분리하려는 경우(그리고 가끔씩 겹치는 로그 파일을 제외하고 문제가 없는 경우) 진행 중인 파일 명명 규칙의 일부로 배치 번호를 만드는 것이 더 나은 접근 방식입니다.

이 같은:

[[ -s ]] $local_dir/batch || echo 0 > $local_dir/batch
batch=$(echo $local_dir/batch)
expr $batch + 1 >$local_dir/batch

for 루프 이전과 루프 시작 시 패턴이 실제 파일과 일치하는지 확인하십시오.

[[ -f "$file" ]] || continue

파일 이름에 배치 번호를 사용하십시오.

mv $file_location $local_dir/in_progress$batch.log

그리고 앞으로. 그러면 충돌 위험이 줄어듭니다.

답변2

위에 문제에 대한 좋은 해결책을 제공하는 답변이 있지만 이에 대해 약간의 설명을 제공해야 한다고 생각했습니다.문제가 무엇인지.

대부분의 경우: 이름을 바꾼 로그 파일(진행 중인 파일)이 기준을 충족하지 않는 한,아마이것을 실행하는 것이 안전합니다최소한의위험. 그래도 여전히 약간의 오류가 발생합니다 ...

파일 목록은 스크립트 실행 시 생성됩니다. 그래서 결국 일어날 일은 다음과 같습니다.

Script A의 목록을 가져옵니다 10 files. 처리를 시작합니다. 5 files(남은 5개)에서 script B의 목록을 가져오고 5 remaining files처리를 시작합니다. Script a그런 다음 목록의 다음 파일을 처리합니다(파일이 script B처리를 시작한 것과 동일함). 파일 이름이 바뀌었기 때문에 오류가 발생합니다. 따라서 오류 처리를 사용하면 이론적으로 문제 없이 목록과 기능의 다음 항목으로 이동할 수 있습니다. 그러나 분명히 별표가 정렬될 가능성은 항상 존재하지만 스크립트가 동시에 동일한 파일에 도달하여 예상치 못한 일이 발생합니다. 원하는대로 위험을 측정하십시오.

잠재적으로 더 우아한 해결책은 이것을 스크립트로 변환 python하고 parallel for loops단일 for 루프를 생성하고 이를 병렬로 실행하여 하나의 스크립트가 둘 이상의 작업을 수행할 수 있도록 하는 것입니다.

답변3

또 다른 방법은 스크립트에 간단한 배치 대기열을 구현하는 것입니다.

스크립트 시작 부분에서 다음과 같이 할 수 있습니다.

mkdir -p $localdir/batch
BATCHTMP=$(mktemp batch.XXXXXXXXXX)
MYBATCH="$localdir/batch/batch.$$"

# get list of current log files
find $local_dir/ -name 'myfile.log.*' > "$BATCHTMP"

# exclude any log files already in other batches
grep -vF -f <(sort -u $localdir/batch/batch.*) < "$BATCHTMP" > "$MYBATCH"

rm -f "$BATCHTMP"

# only process log files that are in my batch
for lf in $(cat "$MYBATCH") ; do
....
# somewhere in here, mv or rm the logfile being processed
# so it doesn't get processed again in a later batch run
done

rm -f "$MYBATCH"

물론 이는 수행해야 할 작업에 대한 간단한 개요일 뿐입니다.

그런데 이 작업은 배치 파일을 생성하고 기본 스크립트를 실행하는 것 외에는 아무것도 수행하지 않는 래퍼 스크립트에서도 수행할 수 있습니다.

관련 정보