네트워크_10 지정한 크기의 파일을 만들어서 전송 속도를 측정하기

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

명령어: 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로 지정한 서버 사이의 통신 속도를 조사하는 용도로 사용합니다.

예제처럼 서버 사이에 파일을 주고 받아서 전송 속도를 측정하는 것은 네트워크 운용에서 중요한 작업입니다. 그런 작업을 셸 스크립트로 자동화 할 수 있습니다.

우선 12에서 속도 측정을 위한 임시 파일의 크기 및 파일명(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://<호스트명>/<파일경로>"