- 출처 : 유닉스 리눅스 쉘스크립트 예제사전_한빛미디어
명령어: dd, time, ftp, bc
키워드: 전송 속도, 통신 속도, 네트워크 속도
사용처: 어떤 서버에 임시 파일을 전송해서 통신 속도를 측정하고 싶을 때
실행 예제
$ ./transfer-sec.sh
Filesize: 1024(KB)
FTP Server: 192.168.2.5
Transfer Speed: 978 (KB/sec)
스크립트
#!/bin/sh
# 전송 속도를 측정할 임시 파일 크기 지정. 단위는 킬로바이트(KB)
filesize=1024 # ------------------------------------------------------- 1
#전송 속도를 측정할 임시 파일명
tmpdata="tmpdata.tmp" # ----------------------------------------------- 2
timefile="timecount.tmp"
# 전송에 사용할 임시 파일 작성
dd if=/dev/zero of="$tmpdata" count=$filesize bs=1024 2> /dev/null # -- 3
# FTP 접속해서 파일을 PUT
server="192.168.2.5" # ------------------------------------------------ 4
user="user1"
password="xxxxxxxx"
echo "Filesize: $filesize (KB)"
echo "FTP Server: $server"
(time -p ftp -n "$server") << __EOT__ 2> "$timefile" # ---------------- 5
user "$user" "$password"
binary
put "$tmpdata"
__EOT__
# time 명령어 출력 결과에서 실제 시간을 얻은 후 나눠서 속도 계산
realtime=$(awk '/^real / {print $2}' "$timefile") # ------------------- 6
speed=$(echo "${filesize}/${realtime}"|bc) # -------------------------- 7
echo "Transfer Speed: $speed (KB/sec)"
# 임시파일 삭제
rm -f "$tmpdata" "$timefile"
해설
이 스크립트는 임시 파일을 만들어 FTP로 전송할 때 전송 속도를 측정합니다. 스크립트를 실행할 서버와 셸 변수 server로 지정한 서버 사이의 통신 속도를 조사하는 용도로 사용합니다.
예제처럼 서버 사이에 파일을 주고 받아서 전송 속도를 측정하는 것은 네트워크 운용에서 중요한 작업입니다. 그런 작업을 셸 스크립트로 자동화 할 수 있습니다.
우선 1
과 2
에서 속도 측정을 위한 임시 파일의 크기 및 파일명(tmpdata)을 설정합니다. 동시에 시간 측정을 위한 임시 파일명(timefile)도 설정합니다.
여기서 파일 크기는 1024KB(1MB)를 지정했는데 네트워크 상태에 따라서 적절한 겂이 다를 수 있습니다. 크기가 너무 작으면 순식간에 전송이 끝나서 제대로 속도를 계산 할 수 없고 크기가 너무 크면 서버와 네트워크에 부하가 걸릴 수도 있습니다. 환경에 따라 적절한 크기로 바꾸기 바랍니다.
3
에서 전송할 임시 파일을 dd 명령어로 작성합니다. dd 명령어는 지정한 입력에서 출력으로 복사하는 명령어입니다. 스크립트에서는 dd 명령어 경과 출력을 표시하지 않아도 되므로 /dev/null로 표준 에러 출력을 리다이렉트 합니다.
-
임시 파일 작성에 사용하는 옵션
옵션 설명 if=/dev/zero 입력으로 /dev/zero 라는 널 문자를 읽을 수 있는 스페셜 디바이스 지정 of=”$filename” 셸 변수 filename으로 정의된 파일명을 출력으로 지정 count=$filesize 셸 변수 filesize로 지정한 횟수만큼 복사 bs=1024 복사할 블록 크기, 1024바이트(1킬로바이트)
여기서 널 문자(ASCII 코드로 0x00)로 채운 1024(KB) x 1024(회) = 1MB 임시 파일이 만들어 집니다.
이렇게 /dev/zero로 임시 파일을 만들면 빨리 파일을 만들 수 있지만 내용물은 전부 같습니다. 전송 속도를 측정할 때 프로토콜에 따라서는 자동으로압축되므로 이런 내용물이 전부 같은 파일은 압축률이 무척 높아서 측정용으로 적합하지 않습니다.
따라서 용도에 따라서는 /dev/zero가 아닌 /dev/urandom에서 읽어들이면 파일 내용이 랜덤이 되어서 더 현실적인 파일이 만들어집니다.
dd if=/dev/urandom of=tmp.dat count=1024 bs=1024
예제에서는 FTP 프로토콜을 사용합니다. 자동 압축하는 프로토콜이 아니므로 빨리 만들 수 있는 /dev/zero로 파일을 만듭니다.
전송 파일이 만들어졌으므로 실제로 파일을 전송합니다. 4
에서 ftp로 파일을 전송하는 설정을 작성합니다.
ftp 전송 시 5
에서 time 명령어를 사용합니다. 초만 표시하는 -p 옵션을 써서 실제 시간 real을 얻습니다.
5
는 히어 도큐먼트와 리다이렉트가 섞인 좀 알기 어려운 코드이지만 “EOT“라는 히어 도큐먼트를 사용함과 동시에 time 명령어 출력을 셸 변수 timefile로 지정한 파일에 리다이렉트합니다.
또한 5
는 명령어 전체를 ()로 둘러싼 서브셸입니다. 명령어 전체를 통째로 리다이렉트하기 위한 처리로, 서브셸을 사용하지 않고 다음처럼 작성하면 ftp 명령어 결과만 리다이렉트되어서 time 명령어 결과를 얻을 수 없습니다.
time -p ftp -n "$server" << __EOT__ 2> "$timefile"
6
에서 전송 속도를 측정합니다. 우선 time 명령어 표시 결과를 출력한 파일 $timefile에서 명령어 실행에 걸린 시간 real을 취득합니다.
전송 속도는 “파일 크기 / 시간”이므로 7
에서 bc 명령어를 사용합니다. 셸 스크립트 계산에는 expr 명령어는 소수를 사용 못하므로 bc 명령어를 사용합니다. 나눗셈 식을 echo 명령어로 표시해서 파이프로 bc 명령어에 입력해서 계산 결과를 얻습니다.
예제에서는 파일 크기가 킬로바이트 단위이고, time 명령어 출력은 초 단위이므로 7
에서 계산한 속도 단위는 킬로바이트/초가 됩니다.
주의사항
-
ftp는 보안상 문제가 있지만 여기서는 일부러 ftp를 사용했습니다. scp 같은 ssh 기반 통신은 암호화에 의한 CPU 오버헤드가 커서 통신 속도 측정에 큰 영향을 끼치기 때문입니다. 따라서 서버 사이의 파일 전송 속도를 순수하게 측정하는데 ftp를 사용합니다.
-
이 스크립트로 측정한 속도에는 순수한 네트워크 통신 속도뿐만 아니라 임시 파일을 디스크에서 읽어들이는 시간도 들어갑니다 .따라서 디스크 속도가 느린 서버는 영향을 받게 됩니다.
-
wget 명령어나 curl 명령어 같은 도구는 명령어 종료 시 전송 속도가 표시됩니다. 따라서 내려받기 속도를 알고 싶으면 이런 도구를 사용해도 됩니다.
-
wget 명령어 내려받기
$ wget "ftp://park:xxxxxx@192.168.2.5/tmpdata.tmp" ... 생략 ... 2021-04-07 10:31:11 (2.9 MB/s) - "tmpdata.tmp" saved [44442068]
-
curl 명령어 내려받기
$ curl -u "user1:xxxxx: -o "ftp://192.168.2.5/tmpdata.tmp" % Total % Received % Xferd Average Dload Speed Upload Time Total Time Spent Time Left Current Speed 100 2238 0 2238 0 0 23034 0 --:--:-- --:--:-- --:--:-- 23072
이때 FTP ID와 암호는 다음처럼 지정합니다.
# wget 명령어 wget "ftp://<사용자명>:<암호>@<호스트명>/<파일경로>" # curl 명령어 curl -u "<사용자명>:<암호>" -O "ftp://<호스트명>/<파일경로>"