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