네트워크_05 IP 주소로 호스트명을 얻기

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

명령어: host, awk, sed
키워드: IP 주소, 호스트명, 변환, DNS
사용처: IP 주소가 적힌 파일을 읽어서 호스트명을 함께 표시하고 싶을 때

실행 예제

$ cat ip.txt         <--- IP 주소가 적힌 파일
198.51.100.43
203.0.113.1
203.0.113.198

$ ./revlookup.sh ip.txt
198.51.100.43,www.example.org
203.0.113.1,mail.example.com
203.0.113.198,

스크립트

#!/bin/sh

while read ipaddr # ------------------------------------------- 1
do
  # host 명령어로 IP 주소 변환
  revlookup=$(host "$ipaddr") # ------------------------------- 2

  # host 명령어가 성공했는지
  if [ $? -eq 0 ]; then # ------------------------------------- 3
    echo -n "$ipaddr," # -------------------------------------- 4
    # host 명령어 출력을 awk로 호스트명만 표시
    echo "$revlookup" | awk '{print $NF}' | sed 's/\.$//' # --- 5
  else
    echo "$ipaddr,"
  fi

  # DNS 서버 부하 경감을 위해 1초간 대기
  sleep 1
done < $1

   

해설

이 스크립트는 IP 주소가 적힌 파일(ip.txt)을 읽어서 각각의 IP 주소를 host 명령어로 호스트명으로 변환해서 ‘IP 주소, 호스트명’ 조합의 CSV 파일로 출력합니다.

아파치를 비롯한 서버 소프트웨어 로그 파일에는 접속한 IP 주소가 기록됩니다. 이런 로그를 분석할 때 IP 주소를 호스트명으로 바꾸면 상대방의 ISP나 회선을 알기 쉬우므로 이런 변환을 자주하게 됩니다.

IP 주소 변환은 다음처럼 IP 주소를 DNS 서버에 문의해서 호스트명을 취득합니다.

  • IP 주소 변환

DNS로 이름 해석을 할 때는 호스트명에서 IP 주소를 얻습니다. 이 경우는 반대로 IP 주소에서 호스트명을 얻으므로 변환이라고 합니다.

예제 1에서 while문으로 read 명령어를 실행해서 파일에서 IP 주소를 읽어 셸 변수 ipaddr에 저장합니다. 이 파일은 다음처럼 IP 주소가 나열되어 있다고 가정합니다.

198.51.100.43
203.0.113.1
203.0.113.198

2에서 IP 주소에서 호스트명을 변환하기 위해 host 명령어를 실행해서 그 결과를 명령어 치환 $()으로 셸 변수 revlookup에 대입합니다.

3에서 host 명령어 종료 스테이터스를 특수 변수 $?로 판별합니다. host 명령어가 정상적으로 변환했으면 종료 스테이터스인 $?는 0(정상 종료)이 됩니다. 만약 실패했다면 종료 스테이터스는 0이 아닌 값이 되므로 if 문으로 성공했는지 실패했는지에 따라 분기합니다.

정상적으로 변환했으면 [IP주소, 호스트명]을 출력하기 위해 ④에서 echo 명령어를 줄바꿈 없는 -n 옵션으로 실행해서 IP 주소를 표시합니다4. echo 명령어의 -n 옵션은 Mac에서 에러가 발생하므로 주의해야 합니다.

5에서는 호스트명을 표시합니다. 변환된 호스트명은 host 명령어 표시 결과 마지막에 있으므로 awk 명령어를 사용해서 마지막 컬럼 $NF를 출력합니다. NF란 awk 명령어에서 ‘마지막 컬럼’을 의미하는 변수입니다.

  • host 명령어 변환 출력 예
    $ host 198.51.100.43
    43.100.51.198.in-addr.arpa domain name pointer www.example.org.
    

host 명령어 출력을 보면 호스트명 뒤에 .이 붙어있습니다. 따라서 5에서 awk 명령어를 파이프로 이어서 sed 명령어에 넘겨 sed 명령어로 줄 끝에 있는 .을 삭제합니다. 줄 끝에 있는 점을 .$라는 패턴으로 일치시켜 이걸 빈 문자열로 치환하면 삭제할 수 있습니다.

6에서 1초간 기다립니다. DNS 서버에 부하가 걸리지 않도록 하는 처리입니다. host 명령어는 외부 DNS 서버에 문의하는 명령어이므로 이 예제처럼 IP주소를 파일에서 읽어서 순서대로 처리할 때 파일 크기가 크면 대량의 DNS 문의가 발생하게 됩니다. 이런 행동은 서버에 부하가 걸리므로 여기에서는 1초씩 기다려서 DNS 서버 부하를 제어합니다.

   

주의사항

  • 예제에서 사용하는 IP 주소는 RFC 6890에 정의된 것으로 실제 IP주소가 아닙니다. 예제를 실행할 때는 존재하는 IP 주소로 바꾸기 바랍니다.