OS/Linux

find를 이용한 log 정리법

아르비스 2016. 8. 30. 15:49

관리하는 서버에..

간혹 로그가 쌓여서 서비스가 안되는 경우가 있다.

해서.. 주기적으로 일정기간이 지난 로그파일은 삭제를 하고 싶은데..

이럴때 자주 사용하는 명령어가  find 명령어다. 이걸 사용해서 삭제하는 스크립트를 작성하고.. crontab에 등록해놓으면.. 주기적으로 로그파일 정리를 하게 된다.

 

find 의 원래 용도는.. 단어 뜻 그대로.. 일정요건의 파일을 찾아주는 명령어.

기본 사용법은...

$ find . -name *.php

이런식으로.. find 경로명 [조건] 식으로 하면 된다..

여기에.. [조건] 항목에 여러가지 옵션을 쓸 수 있는데... 그중 mtime 를 사용하면.. 일정시간이 지난 파일을 찾을 수 있다..

몇가지 예를 통해서.. 간단한 사용법을 익혀보자.

 

첫번째 예로.. apache 로그중에..  30일이 지난 로그를 찾고자 한다면..

=======

$ find /usr/local/apache/logs -mtime +30

=======

이렇게 하면 된다.

 

두번째 예로.. 30일 넘은 로그들을 삭제하고 싶다면..?

crontab에 넣으려고.. 스크립트 파일로 만들었다.

=======

#!/bin/sh

cd /usr/local/apache/logs

find ./*.log -mtime +30 -exec rm -f {} \;

=======

(find에 경로명을 바로 써주어도 되나.. 디렉토리가 여러개이고, 해당 디렉토리에서 여러 명령어를 실행할 수 있으므로 cd로 해당 디렉토리로 이동해서 실행하도록 했다. 그리고, 경로명에는 경로뿐 아니라, 파일명까지 포함되도 된다.. 다른파일은 안건드리도록 log파일만 find하도록 했다.)

옵션을 좀 설명하자면..

find 옵션중 -exec 옵션을 사용해서 특정 명령어를 실행시킬수 있다. 사용법은 -exec [명령어] \; 의 형태이며..

명령어 내용중에 {}를 넣어주면 해당위치에 find에서 찾은 파일이 들어간다. 그리고.. exec 옵션의 마지막을 알리기 위해 끝엔 \; 를 붙여준다.

 

조금.. 응용해서.. 30일 넘은건 삭제하고...

5일이 넘은건 압축하고 싶다.. 물론 쉽게 가능하다.

한데..삭제를 할때.. *.log뿐만 아니라 압축파일(*.log.Z)도 삭제해야하므로... 삭제시 조건은 *.log* 가 된다.

=======

#!/bin/sh

cd /usr/local/apache/logs

find ./*.log* -mtime +30 -exec rm -f {} \;

find ./*.log -mtime +5 -exec compress {} \;

=======

 

한가지 문제가 발생했다.

다른곳을 봤더니 로그파일이.. access_log.20091217 이런식으로 쌓인다.. (rotatelogs를 사용할 경우 이렇게 생길수있다.)

find조건을 달려고보니.. 삭제를 할때도 *_log.* 으로 찾아야되고.. 압축할때도 *_log.* 로 해야한다..

문제는.. 압축할때 *_log.*로 찾으면 이미 압축항 파일도 찾아진다는것..

물론 compress가 이미 압축된 파일이라고 skip할테지만.. 맘에 걸린다.

이럴때 쓸 수 있는 옵션이.. -name 옵션과.. not을 뜻하는 ! 옵션..

원하는 바는 다음과 같이 하면 된다.

=======

#!/bin/sh

cd /usr/local/apache/logs

find ./*_log.* -mtime +30 -exec rm -f {} \;

find ./*_log.* ! -name '*.Z' -mtime +5 -exec compress {} \;

=======

원래 -name 옵션은.. 파일명이 맞는걸 찾는 옵션인다... 앞에 ! 가 붙어서 반대의 의미를 갖는다.

즉 파일명이 *.Z를 만족하지 않는 파일을 찾겠다는 것이다.

-name 옵션은 자주 쓰이는데... 한가지 주의해야할것이.. 이상하게 평소대로 하면 오류가 나면서 잘 작동하지 않는 경우가 있다.

이럴때는.. -name 의 값을 작은따옴표로 묶어주면 정상적으로 작동한다.(이것땜시.. 삽질했었다..)

 

마지막으로 하나 더 예를 들자면...

로그가 여러종류가 쌓아는데..

그중에 access_log 와 error_log 만 골라서 압축,삭제를 하고 싶다..

이럴때는 위에 나왔던 -name 옵션과... or 을 뜻하는 -o 옵션을 이용하면 된다. 그리고 조건을 \(, \) 로 묶어준다.

=======

#!/bin/sh

cd /usr/local/apache/logs

find ./* \( -name 'access_log*' -o -name 'error_log*' \) -mtime +30 -exec rm -f {} \;

find ./* \( -name 'access_log*' -o -name 'error_log*' \) ! -name '*.Z' -mtime +5 -exec compress {} \;

=======


log 압축시키기 

#!/bin/bash

for file in $(find /ccdata/logs/platform/apache/*/* -type f -not -name '*.gz')

do

    lsof | grep $file

    if [ $? -eq 1 ]

    then

        tempfile=`echo $file | sed 's/logs/logs_arch/g'`

        tempfilepath=`echo ${tempfile%/*}`


        if [ ! -d $tempfilepath ]

        then

            mkdir -vp $tempfilepath

            chown ioffice.ioffice $tempfilepath

        fi


        echo 'cp '$file' '$tempfile | sh -x

        rm -f $file


        gzip $tempfile

    fi

done