병렬 쿼리 재실행 루프 스크립트

병렬 쿼리 재실행 루프 스크립트

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

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 스크립트에 전달합니다.

10개의 파일이 있는지 알고 싶습니다. 각 파일을 완료하는 데 60초가 걸리며, 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"

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

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

관련 정보