[Linux 셸 스크립트] 파일처리 - 032 로그 파일이 엄청 많은 디렉터리에서 파일들에 명령어를 일괄 실행하기
본문 바로가기
IT 이야기/Linux 셸 스크립트

[Linux 셸 스크립트] 파일처리 - 032 로그 파일이 엄청 많은 디렉터리에서 파일들에 명령어를 일괄 실행하기

by 찬찬이 아빠 2021. 3. 18.
반응형
  1. 사용 명령어

(1) find

(2) xargs

(3) grep

 

 

  2. 키워드 & 사용처

(1) 키워드

인수, 명령행 인수, 대량 파일

 

(2) 사용처

파일이 너무 많아 단순히 *로 파일을 지정하면 에러가 발생하는 상황에서 grep 명령어 등을 실행하고 싶을 때 사용합니다.

 

  3. 실행 예제
$ ./xargs-grep.sh
/var/log/myapp/a.log:2021-03-14 12:13:15 [ERROR] File Not Found.
/var/log/myapp/b.log:2021-03-15 01:11:34 [ERROR] I/O Error.
/var/log/myapp/c.log:2021-03-16 21:31:45 [ERROR] File Not Found.

 

 

  4. 스크립트

#!/bin/sh

 

logdir="/var/log/myapp"

 

# 확장자 .log 파일에서 "ERROR" 문자열 검색

find $logdir -name "*.log" -print | xargs grep "ERROR" /dev/null         

 

 

  5. 해설

이 스크립트는 수 많은 파일이 존재하는 디렉터리 /var/log/myapp에 대해 "ERROR" 라는 문자열을 포함한 파일을 grep 명령어로 검색합니다. 여기서 디렉터리 /var/log/myapp에는 단순히 grep 명령어를 실행하면 에러가 발생할 만큼 많은 로그 파일이 존재한다고 가정합니다.

 

$ grep 'ERROR' *.log
-bash: /bin/grep: Argument list too long

여기서 "Argument list too long"(OS에 따라 메시지는 다소 다름)이라는 에러가 발생한 원인은 *(애스터리스크)가 셸에 따라 확장될 때 무척 긴 문자열이 되므로 명령행 인수가 시스템이 다룰 수 있는 한계를 넘었기 때문입니다.

 

유닉스에서는 명령행 인수 상한값이 ARG_MAX 상수로 정해져 있습니다. 따라서 많은 파일이 있을 때 *로 파일 목록을 넘기면 ARG_MAX 이상의 문자열 길이가 되어서 에러가 발생합니다. ARG_MAX 값은 리눅스라면 getconf 명령어로 확인할 수 있습니다.

$ getconf ARG_MAX
2621440

 

 

이 제한을 회피하려면 예제처럼 find 명령어로 우선 파일 목록을 출력해서 그것을 xargs 명령어로 받아서 grep을 실행합니다.

 

xargs 명령어는 ARG_MAX 값을 넘지 않도록 인수를 적당히 나눠서 지정한 명령어를 실행합니다. 따라서 명령행 인수가 얼마나 길든지 상관없이 ARG_MAX 제한에 걸리지 않도록 제대로 처리할 수 있습니다.

 

이 스크립트에서는 특별한 처리를 위해 대상 파일에 /dev/null을 추가합니다. 이것은 grep 명령어 출력에 반드시 파일명을 포함하기 위한 처리입니다. grep 명령어에서는 여러 파일을 대상으로 할 때 다음처럼 앞부분에 파일명을 출력해 일치한 줄을 출력합니다.

$ grep "ERROR" *
<파일명>:<일치한 줄>
<파일명>:<일치한 줄>
<파일명>:<일치한 줄>
... 생략 ...

 

 

예제에서는 /var/log/myapp에 수많은 파일이 있다고 가정합니다. 하지만 만약 대상 파일이 하나뿐이라면 grep 명령어는 결과에 파일명을 출력하지 않습니다.

$ grep "ERROR" *
<일치한 줄>

 

이러면 대상 파일 수에 따라 결과 출력이 달라지므로 처리를 할 때 불편합니다. 따라서 이 예제에서는 대상 파일에 정해진 /dev/null도 추가해서 grep 명령어가 늘 복수 개의 파일을 대상으로 실행되도록 해서 결과에 파일명이 표시되도록 합니다.

 

/dev/null은 어떤 문자열도 포함되어 있지 않으므로 grep되지 않고 검색 결과에는 영향이 없습니다.

 

 

<주의사항>

이 예제에서는 파일에 공백문자(스페이스)가 포함되면 에러가 발생합니다. 공백문자를 다루려면 find 명령어에서 -print0 옵션을 이용해야 합니다.

 

 

 

참고서적 : 유닉스 리눅스 셸 스크립트 예제 사전

반응형

댓글