Bash: 병렬 컬 및 변수

Bash: 병렬 컬 및 변수

나는 이 스크립트를 bash에서 실행하여 이해하고 나중에 Python(나는 훨씬 덜 알고 있음)으로 작성할 수 있기를 원합니다.

내 데이터에 일부 파일이 있습니다. 3. 그게 다야.

https://www.example.com/data/file27-1.jpg
https://www.example.com/data/file51-2.jpg
https://www.example.com/data/file2576-3.jpg
URL='https://www.example.com/data/file'
i=1 ; j=1
for i in {1..3000} ; do
  curl -I ${URL}file${i}-{j}.jpg
  # here, pipe result into grep,
  ### if !200 ((i++)) (so do nothing) ;
  ### if 200 wget $URL$i$j and ((j++)), and i=i-1 so I can have the same $i at the next loop, for a incremented $j
  " and go on into the the for loop
done

하지만 curl3000개의 링크를 얻는 것만으로도 시간이 좀 걸립니다. 어떻게든 병렬화하고 싶은데 curl -I URL, 200 응답을 받으면 동일한 $j 값을 가진 두 개의 파일이 없기 때문에 모든 프로세스 요청을 중지하고 $j에 1을 추가한 다음 모든 것을 적절한 값으로 복원합니다. $i와 $j를 누르고 계속하세요.

나는 병렬화(그러나 많은 스레드를 찾는 것)에 갇혀 있지만 실제로 나를 방해하는 부분은 200이 모든 컬 프로세스를 종료한 다음 $i 및 $j 값에 대해 200 OK로 되돌아간다는 것입니다.

나는 이해하기를 바랍니다. 아직 샘플 스크립트를 작성하지 않았으며 이를 구현하는 방법을 연구 중입니다.

감사해요


편집하다

#ps -ax | grep "curl" | grep -v "grep" | awk '{print $1}'| xargs kill -9 나는 이 명령을 사용하여 조건부에서 사용할 수 있는 모든 컬 요청을 종료한 if 200다음 $i 값을 i=i-1로 재설정하고 $j를 증가시키며 루프를 계속할 수 있다는 것을 알았습니다.

하지만 이 단계에서는 아무것도 병렬화되지 않습니다. xargs를 사용하여 컬 요청을 병렬화하는 방법을 알아낼 수 있지만 그렇게 하여 그 가치를 높일 수는 없습니다.

URL이 생성되는 임시 파일을 생각했는데 스크립트가 실행될 때 생성되기를 원합니다.

답변1

다음은 원하는 작업을 수행하는 데 도움이 되는 작은 조각입니다. 논리가 정확하길 바랍니다.

#!/bin/bash
i=0
j=0
pid=0
ppid=0
#Enable job control; It's not used here but it can be usefull if you need to do more job control
set -m 
for i in {1..3000} ; do
    #Execute each curl in the background to have a sort of multi-threading and get get the HEAD response status and put it in file descriptor 3 to be gathered later
    exec 3< <(curl -I ${URL}file${i}-{j}.jpg | head -n 1 | cut -d$' ' -f2)
    #Get the pid of the background job
    pid="$!"
    #Get the parent pid of the background job
    ppid="$(ps -o ppid= -p $pid)"
    #Gather the HTTP Response code
    status="$(cat <&3)"
    #Check
    if [ "$status" -eq 200 ] ; then
        i="$(($i - 1))"
        j="$(($j + 1))" 
        echo "kill all previous background process by their parent"
        pkill -P $ppid
    else 
      i="$(($i + 1))"
    fi 
    echo " status : $status"
    echo " parent : $ppid"
    echo " child : $pid"
done

답변2

GNU Parallel을 사용하는 경우 다음과 같이 작동합니다(i=1..3000; j=1..1000).

do_j() {
  j=$1
  URL='https://www.example.com/data/file'
  seq 3000 |
    parallel --halt soon,success=1 -j100 "curl -I ${URL}file{}-${j}.jpg | grep 'HTTP.* 200 OK'"
}
export -f do_j
seq 1000 | parallel -j1 do_j

더 많거나 적은 병렬성을 얻으려면 -j1 및 -j100을 조정하십시오.

관련 정보