처리할 파일이 수백 개 있는데 한 번에 10개의 프로세스만 실행하고 싶습니다. "doSomething" 프로세스를 완료하는 데 20초가 걸린다고 가정해 보겠습니다. 다음은 작동하지만 거의 동시에 10개의 프로세스를 시작합니다. 약 20초 후에 첫 번째 10개 세트가 완료되고, 다음 10개 세트가 거의 동시에 시작되어 시리즈가 반복됩니다. 동시에 시작하지 않고 시차를 두고 시작하려면 어떻게 해야 합니까?
find ./someFiles* | xargs --max-args=1 --max-procs=10 ./doSomething
프로세스가 거의 동시에 10초가 아닌 최소 2초 간격으로 시작되기를 원합니다.
답변1
따라서 이는 여러 인스턴스가 동시에 시작될 때 디스크/네트워크 또는 기타 리소스 사용량 급증을 방지하기 위해 수행됩니다. 최소한 처음 N개에 대해서는 X초의 고정 간격을 원합니다.
간단한 해결 방법은 추가 값을 삽입하여 xargs
매개변수를 연기하는 것입니다. 이와 같이:
find . -type f -print0 |
xargs -0 -n1 -P1 sh -c 'sleep 2; printf "%s\0" "$0"' |
xargs -0 -n1 -P4 sh do_something.sh
위에서는 N=4이고 간격은 2초입니다. 처음 N개의 매개변수에 대해서는 간격이 유지됩니다. 그런 다음 일부 실행이 거의 끝나가는 경우 시간에 맞춰 더 가까운 실행을 시작할 수 있으며 이것이 바로 이에 대한 요청입니다.논평.
또한 실행 시간도 짧지 않고 몇 초 이상이 될 것이라고 가정하고 있습니다. 다음 실행 시 여전히 스파이크가 나타나는 경우 지연을 약간 더 높게 설정할 수도 있습니다. 처음에는 큰 병목 현상이 방지됩니다.
시험
다음은 몇 가지 기본 테스트입니다. 스크립트를 do_something.sh
처리하는 데 무작위로 10~20초가 걸립니다.
> cat do_something.sh
printf "%s START processing %s\n" "$(date +"%H:%M:%S")" "$1"
sleep $(shuf -i10-20 -n1)
printf "%s END processing %s\n" "$(date +"%H:%M:%S")" "$1"
> touch file{1..10}
> find . -type f -name 'file*' -print0 |
> xargs -0 -n1 -P1 sh -c 'sleep 2; printf "%s\0" "$0"' |
> xargs -0 -n1 -P4 sh do_something.sh
02:03:22 START processing ./file6
02:03:24 START processing ./file9
02:03:26 START processing ./file8
02:03:28 START processing ./file2
02:03:38 END processing ./file8
02:03:38 START processing ./file7
02:03:40 END processing ./file6
02:03:40 START processing ./file1
02:03:41 END processing ./file9
02:03:41 START processing ./file3
02:03:45 END processing ./file2
02:03:45 START processing ./file4
02:03:55 END processing ./file3
02:03:55 END processing ./file7
02:03:55 START processing ./file10
02:03:55 START processing ./file5
02:04:00 END processing ./file1
02:04:02 END processing ./file4
02:04:05 END processing ./file10
02:04:13 END processing ./file5
답변2
일종의 쉘 스크립트라고 가정하고 다음을 맨 위에 넣으십시오.
export MYPID=$$
(
flock 9
mkdir -p .started-pids
find .started-pids/ -type f ! -newermt '-2 seconds' -delete
n=`find .started-pids/ -type f | wc -l`
sleep $n
sleep $n
touch .started-pids/$MYPID
) 9> .lockfile
그렇지 않다상당히정확함 - 때때로 약간 지연됨더필요한 것보다 더 많이, 그러나 그 이상으로 스파이크가 발생하지 않도록 하세요.
물론 잠금 파일과 pid 카운트 디렉터리 이름을 원하는 대로 변경하세요.