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 作业原则:
- 将进度消息输出到 stdout
- 进度消息说明脚本执行的操作即将执行,而不是脚本刚刚执行的操作
- 写入 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