ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Crontab과 Shell Script를 이용해 오래된 log 지우기
    🎁 토이 프로젝트/오분 (2020년 첫 토이 프로젝트) 2020. 6. 7. 22:32

    안녕하세요! Jay입니다! 오늘은 Shell Script의 기본적인 명령어와 Crontab 사용 방법에 대해 정리해 보도록 하겠습니다.

    제가 CrontabShell Script를 글로 정리하려는 이유 몇가지를 말씀드릴게요!

     

    🔹 반복적인 작업에 대해 스크립트를 이용해 처리할 수 있다, (= 실수를 줄일 수 있다.)

    제가 회사에서 급하게 서버를 10개정도 증설하는 일을 했던 적이 있는데, 인스턴스 생성부터 환경세팅  배포까지 진행했었습니다.

    휴먼에러? 개발자가? 미쳤습니까 휴먼?

    mysql config 파일을 추가하는걸 일일이 수동으로 ...;;  crtl+c.,v로 하다가 vi에서 i를 안누르고 복사를 해서 몇개가 잘못 입력이 되었던 적이 있습니다. (이때 생각하면 참으로 바보같았다는...생각이 드네요ㅎㅎ)

    근데 잘 못 작성된 서버에서 실서버 작업들을 처리해서 큰일이 날 뻔했던 적이 있습니다 ㅎㅎ

    다행히 상태값이 있어서 다시 처리했지만... 

    이처럼 휴먼에러를 방지하기 위해서, 여러 반복적인 작업을할때는 검증된 스크립트를 통해 처리하면 실수를 방지할 수 있습니다.



    🔹 주기적인 작업을 매번 할 필요가 없다.

    귀찮은건 하기 싫다...

    저희 회사는 서버에 접근할때 권한을 체크하는데, 오래 접속을 하지 않으면 권한이 만료가 됩니다. 그래서 자주 쓰지는 않지만 가끔이라도 접속해야하는 서버들이 있는데, 매번 서버에 접속하기에는 귀찮기도 하고 생각도 안납니다 ㅠ

    그래서 매월 초 각 서버에 접속만 하는 스크립트를 작성해서 Crontab에 등록해 두면 알아서 권한이 갱신 되기 때문에 따로 신경쓰지 않아도 됩니다.

     

    제가 이글을 작성하게 된 일은 크게 이 두가지 정도가 되네요. 위 이유 뿐만아니라 Shell Script를 작성할줄 알면 여러가지 좋은점이 있다고 생각합니다.

     

    1. 기본적인 Shell 명령어 


    일단 vi로 스크립트 작성을 합니다 (꼭 vi로 하지 않으셔도 되요)

    vi XXXXsh

    스크립트를 생성후 실행할 때는 chmod로 권한을 바꿔줘야 실행이 될 거에요. 간단히 테스트 할거라 777로 바꿔서 실행했습니다

    권한 변경 관련 글 : https://jay-ji.tistory.com/20?category=732899

     

    [chmod] 파일 및 디렉토리의 퍼미션(권한) 변경

    안녕하세요~!! JAY입니다. 오늘은 chmod(퍼미션 변경)에 대해서 알아보려고 합니다. 리눅스는 서버용으로 만들어진 OS이기 때문에 여러사용자가 들어와 사용한 멀티유저 시스템입니다. 그렇기 때��

    jay-ji.tistory.com

    그리고 Shell Script에서는 최 상단에 아래와 같이 써주셔야 동작이 됩니다.

    #!/bin/bash

    의미는 정확히는 모르지만, /bin/bash로 스크립트를 실행하겠다? 이정도가 될것 같네요 (자세히 아시는분 댓글로좀..)

     

    📌 echo : 화면에 문자열을 출력

    $# : 스크립트에서 전달되는 인자들의 수

    $0: 스크립트 파일 명

    $1, $2 ~ : 스크립트로 전달되는 인자들



    📌 변수 선언

    다른 프로그래밍 언어처럼 = 으로 선언하고, 사용시에는 $로 사용합니다.
    $로 사용시 {}를 감싸주는데, parameter substitution 라고 하네요.

    {}를 사용하지 않아도 동작은 되는데, {}가 없으면 동작이 안되는 경우가 있어서 사용해주는게 좋다고 하는것 같아요!

    1
    2
    3
    4
    5
    str="this is scripts"
    number=123123
     
    echo "${str}"
    echo "${number}"
     

    추가로  parameter substitution 은 이런것도 가능합니다.

     

    ${value-default_str} : value가 선언되지 않았으면 default_str을 출력

    ${value=default_str}: value가 선언되지 않았으면 기본값으로 셋

    ${#value} : value의 길이를 반환

     

    📌 조건문

    • if [ 조건 ]; then ~ elif [ 조건 ]; then ~ else ~ fi

    • if (( 산술 연산 )); then ~ elif (( 산술 연산 )); then ~ else ~ fi

    1
    2
    3
    4
    5
    6
    a=1
    if ((${a} > 1)); then
        echo bigger
    else
        echo lowewr
    fi
     

    if로 시작해서 fi 로 끝맺음..흠 뭔가 신기 방기한 문법인것 같네요 ㅋㅋ 


    📌
    배열 선언

    1
    2
    3
    4
    5
    6
    7
    8
    test_list=("1" "2" "3")
     
    echo ${test_list[0]}
     
    echo ${test_list[@]} # @는 모든 원소를 뜻합니다
     
    test_list+=("4"# 배열에 원소 추가
     
     
     

    특이하게 ,(콤마)로 구분하지 않고 공백으로 index를 구분하네요.

    "1" or 1 둘다 숫자로 인식하네요. 이거 체크해보는 코드는 아래와 같습니다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    test_list=("dfas1" 2 "3")
    echo "${test_list[0]}"
    re="^[0-9]+$"
     
    if [[ ${test_list[0]} =~ $re ]]; then
            echo "$test_list[2] is number."
    else
            echo "$test_list[2] is not number."
    fi
     
     


    📌
     반복문

    1
    2
    3
    4
    5
    6
    7
    8
    9
    test_list=("test" 2 "3")
    echo "${test_list[0]}"
     
    if [[ ${test_list[0]} =~ $re ]]; then
            echo "$test_list[2] is number."
    else
            echo "$test_list[2] is not number."
    fi
     
     
     

    연산자 관련:  https://wiki.kldp.org/HOWTO/html/Adv-Bash-Scr-HOWTO/comparison-ops.html

     


    📌
     함수 선언

    1
    2
    3
    4
    5
    6
    7
    8
    function test() {
        local str="local" # 지역변수 선언
     
        echo "${str}"
     
    }
     
    return_val=$(test) # 함수 리턴
     

    function 키워드는 없어도 동일하게 함수로 인식해요! 함수의 리턴은 ( ) 소괄호로 사용해야 합니다.

     

    이 외에도 여러가지가 있습니다만...pass
    PS. 개인적으로 python과 비슷하면서도 다른 것 같네요:D

    2. Crontab 기본 설명


    📌 Crontab(크론탭) 이란?

    이 글을 쓰기 전에는 그냥 Crontab 자체가 어떤 작업들을 주기적으로 실행하는 프로그램(?) 이라고 알고 있었는데, 정확히는 Crontab 파일들에 의해 Cron이라는 잡 스케줄러가 실행되는 것입니다.

    CrontabCron table의 줄임말이며, 사용자가 주기적으로 실행할 스케줄 등을 정의 해놓은 파일들(?) 정도라 볼 수 있을 것 같습니다.

     

    📌 Crontab 사용 방법

    먼저 크론탭 명령어들을 한번 확인해보겠습니다.

    crontab 명령어 옵션

    -h 하면 help 명령어  인줄 알았는데, 아니였네요 ㅎㅎ 무튼 친절하게 이러이러한 옵션들이 있다고 말해줍니다.

    일단 crontab 등록을 해야하니 corntab -e 명령어를 치면 되겠네요. 

    crontab -e 실행결과

    crontab을 등록할 수 있는 에디터(?) 같은 화면이 나옵니다.

    여기서 주기와 실행할 명령어를 적고 Write Out하고 엔터, 그리고 Exit로 나오면 저장이 되네요.

    설명에 예제까지 아주 친절하게 나와있네요 ㅎㅎ 간단히 요약하자면

    *                    *                     *                  *                    *   
    분(0-59)  시간(0-23)  일(1-31)  월(1-12)   요일(0-7)

    주기는 위와같이 설정하고 그다음에 실행할 명령어를 적으면 되네요. (*는 any 매분, 매시간 의 의미)

    한번 테스트로 매분 hello jay 라는 문자열을 출력하는 crontab을 등록해보겠습니다.

    매분 실행하도록 하고, "hello jay"를  cron.log 에 저장하도록 했습니다.

    실제로 1분이 지난후 cron.log파일이 생성되고 그 안에 "hello jay"가 저장된것을 확인 할 수  있었습니다.

    다만 ehco, wall 로 메시지를 출력했는데 커멘드창에서 실제로 출력이 왜 안되는지는 잘 모르겠네요..;;

    그래서 log 파일에 저장해서 확인해봤습니다.


    📌 Cron이 참조하는 crontab 파일 위치

    var/spool/cron/
    etc/cron.d
    etc/crontab (파일)

    위 폴더 or 파일에 가서 면 실제로 일정한 주기로 실행되도록 설정된 것들이 있습니다. 제 서버에 현재 등록되어 있는 crontab파일 중 하나를 살펴 보도록 하겠습니다.

    cerbot 관련 crontab

    SSL 인증서를 발급할떄, cerbot을 사용한적이 있는데, cerbot은 ssl 인증서를 자동으로 발급 및 갱신을 해주는 봇 프로그램 입니다.

    0분 */12는 24시간을 12로 나눈거니까 하루 두번 실행 되겠네요.

    자세한 내용은 모르지만 하루 두번 인증날짜를 확인해서 renew해주는 것 같습니다.

     

     

    3. Script 작성후, crontab에 등록하기


    자, 이제 앞서 shll script와 crontab 에 대한 기본적인 것 들을 살펴봤으니, 실제로 하려고 했던 작업을 해야겠죠?

    저는 한달이 지난 nginx로그는 과감히 삭제하도록 하겠습니다.

    사실 log를 너무 많이 쌓아두면 별로 좋지 않을 것 같기도 하고, ELK Stack을 따로 구성하게 된다면 그때, 다시한번 어떻게 할지 고민해봐야 겠습니다.

     

    📌 생성 혹은 수정된지 30일 된, log 파일을 찾은 후 삭제

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    #!/bin/bash
    #-----------------------------------
    # 삭제 주기 : 매일 오전
    # 삭제일 : 30일이 지난 압축된 로그
    #-----------------------------------
    delete_file=$(find /var/log/nginx -name '*.log.*' -mtime +30)
    time_stamp=`date +%Y/%m/%d/%H:%M`
     
    if [ ${#delete_file} != 0 ]; then
        find /var/log/nginx -name '*.log.*' -mtime +30 -exec rm -f {} \;
        echo "(${time_stamp})Delete old nginx log : ${delete_file}" >> /home/{{user이름}}/cron.log
    else
        echo "(${time_stamp})Delete old nginx log : None" >> /home/{{user이름}}/cron.log
    fi
     
     

    저는 일단 이렇게 작성했습니다.

    생성된지 30일이 지난 로그(정확히는 압축된 로그)찾고 삭제, 조건문은 find로 찾은 결과값인 문자열의 길이가 0보다 큰경우 로그가 있는 경우로 인식하고, 찾은 파일들을 삭제합니다.

    그리고 cron 로그를 체킹하기 위해 따로 로그에 print를 했습니다.

     

    📌 Crontab 등록

    1
    2
    # m h  dom mon dow   command
    0 6 * * * /home/{{user이름}} /scripts/delete_old_nginx_log.sh
     

    crontab -e 명령어를 실행하여, 이렇게 등록을 했습니다. 전 매일 오전 6:00 에 실행하도록 했습니다.

    두근두근한 마음을 가지고 오전 6시가 될때 까지 기다려봤습니다!!! (새벽에 작성..ㅋㅋ)

    로그파일에 찍힌 스크립트 결과

    두둥!! 진짜로 로그가 찍혔습니다. 30일이 지난 Nginx로그가 없기때문에 파일이 삭제되지는 않았지만, 스크립트가 Cron에 의해 제대로 실행되는걸 확인했습니다. 시간도 보면 정확히 6:00죠? ㅋㅋㅋ

     

    📌꿀팁

    이건 다른 작업하다가 알게된 사실인데, 크론탭은 유저의 환경변수를 가져오지 않네요. 크론탭 내부에 환경변수를 등록하거나, 쉘스크립트 내부에서 따로 등록을 해야합니다.


    4. 마치며


    오늘은 이렇게 간단하게 Shell script 문법과 작성 방법, Crontab에 주기적인 스케줄링 등록하는 방법을 정리 해봤습니다. 실제로 서버에 적용해놓으니 뭔가 대단한거 한거 같은 기분이 드네요 ㅋㅋㅋ 별거 없지만, 하면서 재밌었던 내용이었던 것 같습니다.

    오늘도 즐거운 하루 되시고, 즐거운 코딩 하세요!!

    댓글

운동하는 개발자 JAY-JI