쉘 스크립트에 다음이 있습니다.
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"
물론 이는 수행해야 할 작업에 대한 간단한 개요일 뿐입니다.
그런데 이 작업은 배치 파일을 생성하고 기본 스크립트를 실행하는 것 외에는 아무것도 수행하지 않는 래퍼 스크립트에서도 수행할 수 있습니다.