쉘기능을 자유자재로 다루기_10 여러 URL 파일을 동시에 병렬로 내려받기

 
  • 출처 : 유닉스 리눅스 쉘스크립트 예제사전_한빛미디어

명령어: curl
키워드: 백그라운드, 병렬 처리, 내려받기
사용처: 대기 시간이 있는 명령어가 많아서 병렬로 실행해 전체 실행 시간을 줄이고 싶을 때


실행예제

$ ./background-download.sh
$    <-------------------------- 파일 내려받기 완료를 기다리지 않고 바로 셸에 제어가 들어옴

스크립트

#!/bin/sh

# 병렬로 여러 사이트에서 내려받기
# 각각 백그라운드에서 처리
curl -sO http://www.example.org/download/bigfile.dat &  #--- 1
curl -sO http://www.example.com/files/samplw.pdf &  #------- 1
curl -sO http://jp.example.net/images/large.jpg &  #-------- 1

   

해설

이 스크립트는 여러 웹 사이트에서 파일을 병렬로 내려받습니다. curl 명령어는 웹 사이트에서 파일을 내려받는 명령어로 여기서는 진행 상황을 표시하지 않는 -s(silent) 옵션과 표준 출력이 아니라 파일로 저장하는 -O 옵션을 사용합니다.

예제에서는 curl 명령어를 백그라운드로 실행하므로 내려받기가 병렬로 실행됩니다. 1처럼 명령행 마지막에 &를 쓰면 셸은 명령어 종료를 기다리지 않고 다음 처리로 넘어갑니다. 따라서 예제에서는 첫 번째 파일 bigfile.dat 내려받기가 끝나는 걸 기다리지 않고 다음 파일인 sample.pdf와 그 다음 파일인 large.jpg도 동시에 내려받습니다.

세 명령어는 모두 백그라운드로 처리되므로 스크립트를 실행하면 바로 셸에 제어가 돌아옵니다. 이렇게 해서 효율적으로 파일을 내려받을 수 있습니다.

표준 에러 출력을 표준 출력으로 리다이렉트하는 2>&1을 같이 사용할 때는 &를 어디에 위치시켜야 할까요? 다음처럼 백그라운드 실행을 위한 &를 제일 끝에 붙이는 것이 정답입니다.

  • 파일1 백그라운드 실행과 리다이렉트를 동시에 지정하기

    #!/bin/sh
    
    # 시간이 걸리는 명령어 long_time_program 표시 결과를
    # result.log에 리다이렉트하고 백그라운드로 실행
    long_time_program > result.log 2>&1 &
    

하지만 병렬로 프로세스를 실행하면 서버에 부담이 됩니다. 따라서 많은 처리를 백그라운드로 동시에 실행할 때는 미리 성능 확인을 하는 것이 좋습니다. 그리고 디스크 접근이 많은 프로그램이라면 여러 명령어를 동시에 실행해도 각각 디스크 대기 시간이 길어져서 병렬 처리가 큰 효과를 못 볼 수 있습니다. 백그라운드로 실행했다고 언제나 좋은것이 아니므로 주의해야 합니다.

   

주의사항

  • 동일한 웹 사이트에서 병렬로 대량으로 내려받으면 서버에 부담을 주고 지나치면 디도스 공격으로 보일 수도 있습니다.

  • 이 스크립트를 실행하면 각 명령어가 백그라운드로 실행되어 실행과 동시에 셸에 제어가 돌아옵니다. 따라서 모든 명령어가 종료됐는지는 출력된 파일별로 확인해야 합니다.

  • 각 명령어를 백그라운드로 실행하더라도 스크립트 자체는 모든 명령어의 종료를 기다려서 종료하고 싶다면 wait 명령어를 사용합니다.

  • FreeBSD는 curl이 기본 설치 대상이 아니므로 대신에 fetch 명령어를 사용하면 됩니다.

    fetch "http://www.example.org/download/bigfile.dat"