크론 작업: 모범 사례

크론 작업: 모범 사례

cron앞으로 직업으로 설정할 bash 스크립트를 작성했습니다.

echo스크립트 개발 중에 다음 코드 조각과 같이 코드를 추적하고 디버그하는 데 도움이 되는 몇 가지 줄을 추가했습니다 .

#!/bin/bash

# Check to see if a LOG file exists
if [ -f $LOGDIR/$LOG_FILE ]; then
  echo "LOG file exists"
  # Clear the contents of the LOG file if already present
  echo -n "" > $LOGDIR/$LOG_FILE
elif [ ! -f $LOGDIR/$LOG_FILE ]; then
  echo "LOG file does not exist. Creating now..."
  touch $LOGDIR/$LOG_FILE
  if [ $? -eq 0 ]; then
    echo "LOG file created successfully"
    elif [ ! $? -eq 0 ]; then
    echo "Unable to create file. Logging disabled"
  fi
fi

echocron job사용자가 해당 줄을 볼 수 없으므로 설정한 후에 이 줄을 주석 처리해야 하는지 궁금합니다 . 또한 라인 cron job으로 실행할 때 echo성능에 영향이 있는지 잘 모르겠습니다 .

이것을 구현할 때 몇 가지 좋은 사례를 알고 싶습니다 cron jobs. 감사합니다.

답변1

실행 여부에 관계없이 표준 코딩 방법을 여기에 적용해야 합니다 cron. 예를 들어,

  • 변수를 사용할 때 큰따옴표를 사용하면 쉘이 단어 분할이나 와일드카드를 수행할 기회가 없습니다.
  • 일반적인 대문자 환경 변수와 충돌하지 않도록 전체 대문자 대신 소문자 변수 이름을 사용하는 것을 목표로 합니다.
  • 디버깅 문 작성표준 에러, 정상적인 프로그램 흐름을 자유롭게 사용할 수 있습니다.표준 출력

다음과 같이 스니펫을 작성할 수 있습니다.

#!/bin/bash
logDir=...
logFile=...
DBG=false    # or "true"

# Check to see if a LOG file exists
if [ -f "$logDir/$logFile" ]
then
    $DBG && echo "Log file exists: $logDir/$logFile" >&2
    > "$logDir/$logFile"
else
    echo "Log file does not exist. Creating: $logDir/$logFile" >&2
    if touch "$logDir/$logFile"
    then
        echo "Log file created successfully" >&2
    else
        echo "Unable to create file. Logging disabled" >&2
    fi
fi

개인적으로는 테스트되지 않은 이 버전과 비슷하게 로깅 함수로 래핑하겠습니다.

#!/bin/bash

log() {
    local dt=$(date +'%Y%m%d_%H%M%S') toTerm=false msg=

    # "+" prefix mandates writing to stderr
    [ "$1" = + ] && toTerm=true && shift

    msg=$(
        if [ $# -gt 0 ] then
            printf '%s: %s\n' "$dt" "$*"
        else
            sed "s/^/$dt: /"
        fi
    )

    # write to stderr if mandated or enabled
    if ${logTerm:-false} || $toTerm; then printf '%s' "$msg" >&2; fi

    # write to logfile if enabled and it exists
    [ -n "$logPath" ] && [ -f "$logPath" ] && { printf '%s' "$msg" >>"$logPath"; } 2>/dev/null
}

logPath=/path/to/logfile        # Enable all logging to file
logTerm=false                   # Do not copy logging to terminal (stderr)

log + 'Logging is enabled'      # Write a message to logfile and terminal
log 'Written to the logfile'    # Write a message just to the logfile
who | log                       # Write a block of text to the terminal

logPath=/path/to/logfile        # Enable all logging to file
logTerm=true                    # Copy all logging to terminal (stderr)

log + 'Logging is enabled'      # Write a message to logfile and terminal
log 'Written to the logfile'    # Write a message to both the logfile and terminal
who | log                       # Write a block of text to both the logfile and terminal

답변2

취향에 따라 자르는 방법도 다양하지만..

내 접근 방식:

  • 로컬 "bin" 디렉터리에 스크립트를 저장합니다.
  • 스크립트는 <script_name>.log로컬 "logs" 디렉터리에 있는 자체 파일 에 씁니다.
  • crontab 항목은 모든 출력을 <script_name>.cronlog로컬 "logs" 디렉터리의 파일 에 추가합니다.
  • 나는 또한 파일에서 각각의 새로운 호출이 시작되는 위치를 date알 수 있도록 모든 crontab 항목에 호출을 추가하는 경향이 있습니다.*.cronlog

내 것은 crontab다음과 같습니다.

bindir=/path/to/bin
logdir=/path/to/logs

00,15,30,45 * * * * { date; ${bindir}/script_1; } >> ${logdir}/script_1.cronlog 2>&1
00          * * * * { date; ${bindir}/script_2; } >> ${logdir}/script_2.cronlog 2>&1

스크립트(예: script_1)에는 출력을 생성하는 두 가지 방법이 있습니다.

  • (또는 스크립트에서) 명시적으로 직접 echo출력script_1.log$LOGDIR/$LOG_FILE
  • 암시적 echo으로 stdout으로 직접 출력합니다(즉, 출력을 리디렉션하지 않음 echo). 이 경우 출력은 파일 echo에 캡처됩니다.script_1.cronlog

개인적으로 선호하는 것은 명시적으로 지시하는 스크립트를 작성하는 것입니다.모두<script_name>.log파일 로 출력 하고 런타임 오류/메시지 포착()을 <script_name>.cronlog유지 합니다.cron

답변3

내 크론 작업 원칙:

  1. 진행 메시지를 stdout으로 출력
  2. 진행 메시지는 스크립트가 수행하는 작업을 설명합니다.곧 출시 예정스크립트가 방금 수행한 작업 대신 실행
  3. stdout 및 stderr을 /dev/null로 리디렉션하는 crontab 항목을 작성합니다(예: * * * * * /path/to/my/script >/dev/null 2>&1)

많은 사람들(특히 Ruby/Python/Java 프로그래머)은 침묵을 유지하는 코드를 선호합니다. 이것은 cron 작업에 대한 버그(IMO)입니다. 누구나 취하는 첫 번째 문제 해결 단계는 스크립트/프로그램을 수동으로 호출하여 오류 메시지를 확인하는 것입니다. 터미널에서 진행 메시지를 볼 수 있으며 스크립트/프로그램이 실패했을 때 무엇을 하려고 했는지 정확히 알 수 있습니다. 스크립트/프로그램이 침묵되면 이 유용한 문제 해결 정보가 손실됩니다. crontab 항목은 출력을 삭제하므로(/dev/null로의 리디렉션으로 인해) 스크립트/프로그램 출력으로 인해 cron이 누구에게도 상태 이메일을 보내지 않습니다.

기본적으로 상태 메시지를 출력하는 것에 대해 심각한 공포증을 갖고 있는 스크립트/프로그램 작성자의 경우 또 다른 옵션은 -v/ --verbose옵션을 구현하여 이를 켜는 것입니다. 그러나 간단한 스크립트의 경우 이는 일반적으로 항상 상태 메시지를 출력하고 crontab 항목의 리디렉션을 통해 crond에서 숨기는 것보다 더 많은 작업입니다.

다음은 추가적인 강조점입니다.

많은 사람들이 스크립트/프로그램이 수행하는 모든 주요 작업 후에 진행 메시지를 출력합니다. 이것은 좋지 않습니다. 진행 메시지 출력앞으로그들의 행동. 명령/함수 호출이 오류가 발생하기 전에 오랫동안 중단된 것처럼 보일 때 많은 문제가 발생합니다. 작업 후에 진행 메시지가 기록되면 스크립트가 중단되고 출력을 보는 사용자는 중단된 작업/명령을 나타내는 메시지를 받지 못합니다. 마지막으로 보이는 메시지는 잘못된 것(성공적인 작업)에 관한 것입니다. 작업 전에 메시지가 작성되면 스크립트/프로그램의 어느 부분에 문제가 있는지 분명합니다.

이것은 Unix 및 Linux 시스템 관리자로서 지난 33년 동안 개발된 cron 작업 모범 사례에 대한 나의 의견입니다.

답변4

나는 최근 데비안의 cron에 대해 조금 울었습니다. 시스템 서비스로 전환하십시오. cron은 정말 골치 아픈 일입니다 =) systemd 서비스는 천국입니다

예:

catMYSERVICE.service

[Unit]
Description=MYSERVICE-SCRIPT.bash
After=default.target

[Service]
ExecStart=/<ABS-PATH-TO-SCRIPT>/MYSERVICE-SCRIPT.bash

[Install]
WantedBy=default.target

그런 다음 그것을 이동/etc/systemd/system/MYSERVICE.service

그 후에는 제어할 수 있습니다.systemctl enable/disable/start/stop/status MYSERVICE

관련 정보