curl을 사용한 분할 다운로드

By | 2016/10/24

오늘 알아볼 팁은 curl으로 분할 다운로드 하는 방법에 대한 것이다.
간단한 팁이긴 하지만, 경우에 따라서는 유용할 수도 있을것 같아서 글로 남긴다.

chef-server를 설치해야할 일이 생겼다.
chef-server의 설치파일은 551메가 가량 되는데, 그 녀석은 이링크에서 받아온다.

눌러보면 알겠지만, 겁~~~~~~~나 느리다.
저거 받는다고 30분씩 기다리는 경우가 태반인데,
여기서 생각한게 이런거다.

예전에 flashget이라는 윈도우 유틸을 사용했던 것처럼 분할해서 다운로드 한다음에 합치면 좋지 않을까?

위의 아이디어에서 출발했고, 30분을 3분정도로 줄이는데에 성공했다.

물론…여러가지 꼼수를 써서 가능하게 된것이다.

일단 분할해서 받아오는 방법을 알아보자.

curl의 --range 옵션을 사용하면 받아올 파일의 구간을 설정할 수 있다.

curl로 쪼개서 받아오는 코드는 아래와 같다.

#!/bin/bash
curl –range 0-99999999 -s -o chef-server_12.9.1-1.part1 https://packages.chef.io/files/stable/chef-server/12.9.1/ubuntu/14.04/chef-server-core_12.9.1-1_amd64.deb
curl -s –range 100000000-199999999 -s -o chef-server_12.9.1-1.part2 https://packages.chef.io/files/stable/chef-server/12.9.1/ubuntu/14.04/chef-server-core_12.9.1-1_amd64.deb && echo “done2” &
curl -s –range 200000000-299999999 -s -o chef-server_12.9.1-1.part3 https://packages.chef.io/files/stable/chef-server/12.9.1/ubuntu/14.04/chef-server-core_12.9.1-1_amd64.deb && echo “done3” &
curl -s –range 300000000-399999999 -s -o chef-server_12.9.1-1.part4 https://packages.chef.io/files/stable/chef-server/12.9.1/ubuntu/14.04/chef-server-core_12.9.1-1_amd64.deb && echo “done4” &
curl -s –range 400000000-499999999 -s -o chef-server_12.9.1-1.part5 https://packages.chef.io/files/stable/chef-server/12.9.1/ubuntu/14.04/chef-server-core_12.9.1-1_amd64.deb echo “done5” &
curl -s –range 500000000- -s -o chef-server_12.9.1-1.part6 https://packages.chef.io/files/stable/chef-server/12.9.1/ubuntu/14.04/chef-server-core_12.9.1-1_amd64.deb && echo “done6” &
wait
cat chef-server_12.9.1-1.part? > chef-server-core_12.9.1-1_amd64.deb
rm chef-server_12.9.1-1.part?

curl의 -s 옵션과 -o 옵션을 사용했는데, -s는 slient이고, -o는 분할해서 다운로드 받는 파일의 파일명을 지정해주는 옵션이다. 분할된 각 파일들을 보면 아래와 같다.

-rw-rw-r– 1 vagrant vagrant 100000000 Oct 24 05:48 chef-server_12.9.1-1.part1
-rw-rw-r– 1 vagrant vagrant 100000000 Oct 24 05:48 chef-server_12.9.1-1.part2
-rw-rw-r– 1 vagrant vagrant 100000000 Oct 24 05:48 chef-server_12.9.1-1.part3
-rw-rw-r– 1 vagrant vagrant 100000000 Oct 24 05:49 chef-server_12.9.1-1.part4
-rw-rw-r– 1 vagrant vagrant 100000000 Oct 24 05:48 chef-server_12.9.1-1.part5
-rw-rw-r– 1 vagrant vagrant 77422441 Oct 24 05:48 chef-server_12.9.1-1.part6

wait 명령으로 각 프로세스가 종료될때까지 기다리고 다 끝나면, chef-server-core_12.9.1-1_amd64.deb 파일로 합친다.

저 방법으로 30분 걸리던게 15분 정도로 줄어들었다. 1/6로 줄어야 될것 같긴한데, 코어수가 1개이기 때문인 것 같다.
프로세스 자체는 curl 6개가 열심히 다운로드를 받고 있다. 코어가 여러개인 머신에서 실행하면 훨씬 빠릿하게 받을 것 같다.

parallel_ing

& 로 프로세스를 백드라운드로 실행시키는 녀석을 제거해 보려고 parallel 이라는 녀석으로도 시도를 해보았다.

참고로 parallel의 –link라는 옵션을 사용하는데, 최신버전에서 사용할 수 있다. 기본설치버전에는 없다.

parallel을 추가로 사용한 분할 다운로드 코드를 보자

#!/bin/bash

URL=”https://s3.ap-northeast-2.amazonaws.com/chef-download/chef-server-core_12.9.1-1_amd64.deb”

parallel –jobs 6 –link curl –range {1}{2} -s -o chef-server_12.9.1-1.part{3} $URL ::: 0 100000000 200000000 300000000 400000000 500000000 ::: -99999999 -199999999 -299999999 -399999999 -499999999 – ::: 1 2 3 4 5 6
wait
cat chef-server_12.9.1-1.part? > chef-server-core_12.9.1-1_amd64.deb

위의 코드를 간단히 설명하면 :::뒤에 오는 숫자들이 파라메터들이다. 위의 코드가 어떻게 동작 하는지는 아래의 코드가 어떻게 실행되는지를 보는게 더욱 빠를 것 같다.

parallel –jobs 6 –link echo {1} {2} {3} ::: 1 2 3 ::: 4 5 6 ::: 7 8 9

[output]
1 4 7
2 5 8
3 6 9

{1} {2} {3}에 해당하는 곳에 각각의 :::으로 구분된 파라메터의 값들을 하나씩 치환해서 넣어주게 된다.

위의 parallel을 사용한 curl코드는 사실 curl로 처음 분할 다운로드를 하던 코드에 병렬실행 만 양념으로 넣어준것 뿐이다.
나머지는 같다. 위 코드를 사용해도 다운로드 속도가 그리 빠르지는 않았다.

다 받았으면, checksum으로 같은 파일인지 확인을 해보도록 하자.
md5나 sha1, sha256으로 체크하는데 sha1로 체크를 해보자.
하는 방법은 웹사이트에 올려져 있는 sha1 checksum과 분할해서 받았다가 합쳐진 녀석의 checksum이 일치하면, 같은 파일이라고 봐도 좋다는 것이다. 체크섬을 체크하는법(?!)은 아래와 같다.

sha1sum chef-server-core_12.9.1-1_amd64.deb

위의 코드를 실행시켜서 나오는 hash값이 원본파일의 sha1 hash와 동일한지 보면된다.

한가지 더 꼼수를 쓴 것은 그냥 국내의 클라우드 서비스 저장소에 chef-server-core_12.9.1-1_amd64.deb 올려놓고 그녀석을 분할 다운로드 하니, 속도가 많이 빨라졌다.

그냥 국내 클라우드에 올려놓으면 될 것을 이라는 마음이 들기도 하지만, 간단한 것도 고민해보고 만들어보고 하는건 참 재미있는것 같다.

아래는 위의 두가지를 모두 적용후 다운로드 시간을 측정해본 것이다. 2분 31초가 걸렸는데, 그전에는 30분정도 걸렸다.
적용전 split_download_before

적용후 parallel_download