Cron 作业:最佳实践

Cron 作业:最佳实践

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

echo我只是想知道一旦我设置了 a是否应该注释掉这些行cron job,因为用户不会看到它们。此外,我不确定当cron job运行有echo线路时是否会对性能产生影响。

我想知道实施时的一些好的做法cron jobs,谢谢。

答案1

标准编码实践应该适用于此,无论它是否运行cron。例如,

  • 使用变量时用双引号引起来,这样 shell 就没有任何机会进行单词拆分或通配符
  • 旨在使用小写变量名称而不是完全大写,这样它们就不会与典型的大写环境变量发生冲突
  • 将调试语句写入标准错误,让正常的程序流程可以自由使用标准输出

您可以按照以下方式编写该片段

#!/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)有 2 种方式生成输出:

  • 显式地将echo输出定向到script_1.log(或$LOGDIR/$LOG_FILE在您的脚本中)
  • 隐式直接echo输出到 stdout(即,不重定向输出echo),在这种情况下,echo输出将被捕获在script_1.cronlog文件中

我个人的偏好是编写明确指示的脚本全部输出到<script_name>.log文件并保留<script_name>.cronlog捕获任何 ( cron) 运行时错误/消息。

答案3

我的 cron 作业原则:

  1. 将进度消息输出到 stdout
  2. 进度消息说明脚本执行的操作即将执行,而不是脚本刚刚执行的操作
  3. 写入 crontab 条目以将 stdout 和 stderr 重定向到 /dev/null (例如* * * * * /path/to/my/script >/dev/null 2>&1

很多人(尤其是 ruby​​/python/java 程序员)更喜欢代码保持沉默。对于 cron 作业来说,这是一个错误(IMO)。任何人都会执行的第一个故障排除步骤是手动调用脚本/程序以查看错误消息。他们将在终端中看到进度消息,并准确地看到脚本/程序在失败时尝试执行的操作。当脚本/程序静默时,这些有用的故障排除信息就会丢失。由于 crontab 条目会丢弃输出(由于重定向到 /dev/null),因此脚本/程序输出不会导致 cron 向任何人发送状态电子邮件。

对于对默认情况下输出状态消息有严重恐惧症的脚本/程序编写者来说,另一种选择是实现-v/--verbose选项来打开它们。然而,对于简单的脚本来说,这通常比始终输出状态消息并通过 crontab 条目中的重定向将它们隐藏在 crond 之外要多得多的工作。

这里额外强调一下:

很多人在脚本/程序执行每个主要操作后都会输出进度消息。这不好。输出进度消息他们的行动。当命令/函数调用在出错之前似乎挂起很长时间时,就会出现很多问题。当在操作之后写入进度消息时,脚本将挂起,并且观看输出的用户将不会收到指示挂起的操作/命令的消息。最后一条可见的消息是关于错误的事情(成功的操作)。当消息在操作之前写入时,很清楚脚本/程序的哪一部分出现了问题。

以上是我在过去 33 年里作为 Unix 和 Linux 系统管理员形成的对 cron 作业最佳实践的看法。

答案4

我最近刚刚为 Debian 上的 cron 哭了一会儿。切换到 systemd 服务。 cron 真是令人头疼 =) systemd 服务就是天堂

例子:

猫 MYSERVICE.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

相关内容