변환 처리_10 명령어 출력 결과를 파일명에 포함해서 그 파일명을 대상으로 명령어를 실행할 때 보기 쉽게 하기

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

명령어: hostname, grep
키워드: 명령어 치환, 끼워넣기, 네스트
사용처: 명령어 치환 처리를 끼워 넣고(네스트) 싶을 때


실행예제

$ ./comsub.sh
Error counts: 2

스크립트

#!/bin/sh

err_count=$(grep -C "ERROR" /var/log/myapp/$(hostname).log)  #--- 1
echo "Error counts: $err_count"

   

해설

이 스크립트는 hostname 명령어로 파일명을 조합한 로그 파일에서 ERROR라는 문자열을 검색하여 일치한 줄을 표시합니다. 검색과 카운터에는 grep 명령어의 -c 옵션을 사용합니다.

예제에서 명령어 치환을 할 때 검색 대상 로그 파일이 다음과 같다고 가정합니다.

  • /var/log/myapp 디렉터리 안에 “(서버명).log”라는 로그 파일이 저장됨
  • 이 스크립트를 실행하는 서버 호스트명은 “server1”임(hostname 명령어를 실행하면 server1이 출력됨)
  • server1.log 라는 텍스트 파일 내용은 [파일1]과 같음

  • 파일1 예제에서 사용하는 server1.log 내용

    2013/11/13 21:10:22 [INFO] script start.
    2013/11/13 21:10:24 [ERROR] File does not exist: /var/tmp/foo.txt
    2013/11/13 21:10:24 [ERROR] File does not exist: /var/tmp/bar.txt
    2013/11/13 21:10:25 [INFO] script end.
    

셸 스크립트에서 어떤 명령어 출력 결과를 그대로 스크립트에서 셸 변수에 대입하고 싶을 때 `를 사용합니다. 이것을 명령어 치환(Command Substitution)이라고 합니다. 다음은 date 명령어 출력을 사용해서 오늘 날짜를 YYYYMMDD 형식으로 셸 변수 date_str에 대입하는 예제입니다.

date_str=`date +"%Y%m%d"`
echo $date_str

하지만 `를 쓴 명령어 치환은 네스트(끼워넣기)하여 처리하기가 번거롭습니다. 예제 1을 `를 쓴 방법으로 작성하면 다음처럼 내부에 있는 `(그레이브)를 \로 이스케이프해야 합니다.

err_count=`grep -c "ERROR" /var/log/myapp/\`hostname\`.log`

매번 이스케이프하는 것도 큰 일이고 기존 스크립트를 수정할 때 이 부분에 변경이 있다면 이스케이프를 빠트릴지도 모릅니다. 따라서 이 예제에서 쓰는 $() 표기법을 추천합니다.

이 방법의 장점은 처리를 네스트하더라도 기존 명령어 치환 부분을 이스케이프하지 않아도 된다 라는 점입니다. 따라서 기존 코드를 수정할 때에는 처리 내부 코드를 수정할 필요가 없으므로 보수성이 뛰어납니다.

또한, 괄호 대응이라는 알기 쉬운 표기법으로 명령어 치환 부분을 작성하므로 코드가 읽기 쉽다 라는 장점도 있습니다.

보통 vi나 이맥스 같은 에디터에서 프로그래밍 지원 기능으로 괄호 대응을 한눈에 알아보기 쉽도록 처리해줍니다(vi 라면 괄호 위에 커서를 두고 %키를 누르면 대응하는 괄호로 이동합니다). 이렇듯 셸 스크립트에서 네스트하는 명령어 치환을 할 때는 `(그레이브) 대신 $()를 쓰도록 합시다.