다음을 호출하여 100만 개의 필드 라인이 포함된 파일을 처리해야 합니다.
1m.txt
이제 내 스크립트는 1m.txt에 포함된 줄의 유효성을 검사합니다.
cat out.txt > advance.txt 2> /dev/null
cat 1m.txt | xargs -I {} -P 100 sh -c "if ! grep --quiet {} advance.txt; then if host {} >/dev/null; then echo OK {}; else echo DIE {}; fi; fi" >> out.txt
이 스크립트가 하는 일은 중단(ctrl+c)되었다가 다시 시작되면 처리된 마지막 줄부터 시작된다는 것입니다. 행이 1,000개라면 200개 행에서 중단된 프로세스가 빠르게 다시 시작됩니다. 그러나 100만 행의 경우 500,000행에 대한 프로세스를 중단하는 데 몇 시간이 걸립니다.
좀 더 효율적으로 만들 수 있는 방법이 있나요?
답변1
따라서 현재 논리는 "1m.txt의 각 행에 대해 이미 advance.txt가 있는지 확인하십시오. 그렇지 않은 경우 이를 처리하여 out.txt에 추가하십시오. 작업이 시작되면 advance.txt가 있는 모든 행으로 업데이트하십시오. out.txt'.
문제는 advance.txt에 더 많은 행이 추가될수록 각각을 비교해야 하는 행이 더 많아진다는 것입니다. 최악의 시나리오는 모든 줄이 처리되는 경우 1m.txt의 백만 줄을 모두 확인하여 advance.txt인지 확인해야 합니다. 평균적으로 advance.txt 행의 절반을 비교해야 하므로 1,000,000*500,000 또는 500,000,000,000(5000억) 번의 비교가 필요합니다.
병렬로 처리하지 않는 경우 이를 처리하는 간단한 방법은 out.txt에서 마지막 줄을 찾아 1m.txt에서 해당 지점까지의 모든 줄을 건너뛰는 것입니다. 예를 들어
# Pipe the output of the if/then/else/fi construct to xargs.
# use the if/then/else/fi to select the input.
# Use '-s' to see if the file exists and has non zero size.
if [ -s out.txt ] ; then
# we have some existing data
# Get the host from the last line
# delete anything that is not the last line
# remove the DIE/OK. quote anything not alphabetic with a backslash.
lasthost="$(sed '$!d;s/^\(DIE\|OK\) //;s/[^0-9a-zA-Z]/\\&/g' out.txt)"
# get the lines from 1m.txt from after the matched host
# uses GNU sed extension to start at line "0"
sed "0,/^$lasthost\$/d" 1m.txt
else
# no existing data, so just copy the 1m.txt using cat
cat 1m.txt
fi | xargs -I {} sh -c "if host {} >/dev/null; then echo OK {}; else echo DIE {}; fi" >> out.txt
그러나 작업을 병렬로 처리하고 있습니다. host
반환 값은 서로 다른 시간이 걸릴 수 있으므로 입력을 크게 재배열할 수 있습니다 . 호스트가 확인되었는지 확인하는 더 빠른 방법이 필요합니다. 표준 접근 방식은 일종의 해시 테이블을 사용하는 것입니다. 한 가지 방법은 을 사용하는 것입니다 awk
.
if [ -s out.txt ] ; then
# we have some existing data. Process the two files given
# for the first file set the entries of the seen array to 1
# for the second file print out the hosts which have not been seen.
awk 'FNR==NR {seen[$2]=1;next} seen[$1]!=1' out.txt 1m.txt
else
cat 1m.txt
fi | xargs -I {} -P 100 sh -c "if host {} >/dev/null; then echo OK {}; else echo DIE {}; fi" >> out.txt