我有几个脚本(目前在 CentOS 系统中运行)已移至新的 Ubuntu 14.04 系统。这些脚本位于 /etc/cron.daily 中,每天运行一次。这些脚本将以 root 身份在系统级别运行。如果我使用“sudo”命令运行脚本或以 root 身份运行(sudo -i),脚本将完全按照预期执行。
谢谢B
问题:
Cron 每天运行,但不会激活我的 bash 脚本。我找不到 Cron 尝试运行脚本的任何记录
文件/文件夹权限:
/etc/cron.daily = 根:根 755
etc/cron.daily/bash.sh = 根:根 755
var/log/slog(脚本的日志文件)= root:root 644
系统日志的输出:
Jul 25 10:39:45 SYSTEM1 cron[24337]: (CRON) INFO (pidfile fd = 3)
Jul 25 10:39:45 SYSTEM1 cron[24338]: (CRON) STARTUP (fork ok)
Jul 25 10:39:45 SYSTEM1 cron[24338]: (CRON) INFO (Skipping @reboot jobs -- not system startup)
Jul 25 10:40:01 SYSTEM1 CRON[24341]: (smmsp) CMD (test -x /etc/init.d/sendmail && /usr/share/sendmail/sendmail cron-msp)
Jul 25 10:41:17 SYSTEM1 cron[24375]: (CRON) INFO (pidfile fd = 3)
Jul 25 10:41:17 SYSTEM1 cron[24376]: (CRON) STARTUP (fork ok)
Jul 25 10:41:17 SYSTEM1 cron[24376]: (CRON) INFO (Skipping @reboot jobs -- not system startup)
Jul 25 10:43:37 SYSTEM1 crontab[24413]: (root) LIST (root)
Jul 25 10:45:01 SYSTEM1 CRON[24415]: (root) CMD (test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily ))
Jul 25 11:00:01 SYSTEM1 CRON[24620]: (smmsp) CMD (test -x /etc/init.d/sendmail && /usr/share/sendmail/sendmail cron-msp)
Jul 25 11:17:01 SYSTEM1 CRON[25239]: (root) CMD ( cd / && run-parts --report /etc/cron.hourly)
Jul 25 11:17:37 SYSTEM1 crontab[25243]: (root) LIST (root)
Jul 25 11:17:51 SYSTEM1 crontab[25246]: (root) BEGIN EDIT (root)
Jul 25 11:18:10 SYSTEM1 crontab[25246]: (root) END EDIT (root)
Jul 25 11:20:01 SYSTEM1 CRON[25308]: (smmsp) CMD (test -x /etc/init.d/sendmail && /usr/share/sendmail/sendmail cron-msp)
手动运行脚本时的输出:
Jul 25 11:24:57 SYSTEM1 sendmail[25398]: s6PFOvdY025398: from=USER1, size=601, class=0, nrcpts=1, msgid=<[email protected]>, relay=root@localhost
Jul 25 11:24:57 SYSTEM1 sm-mta[25399]: s6PFOvV7025399: from=<[email protected]>, size=843, class=0, nrcpts=1, msgid=<[email protected]>, proto=ESMTP, daemon=MTA-v4, relay=localhost [127.0.0.1]
Jul 25 11:24:57 SYSTEM1 sendmail[25398]: s6PFOvdY025398: [email protected], ctladdr=USER1 (251679327/251679327), delay=00:00:00, xdelay=00:00:00, mailer=relay, pri=30601, relay=[127.0.0.1] [127.0.0.1], dsn=2.0.0, stat=Sent (s6PFOvV7025399 Message accepted for delivery)
Jul 25 11:24:59 SYSTEM1 sm-mta[25401]: s6PFOvV7025399: to=<[email protected]>, ctladdr=<[email protected]> (251679327/251679327), delay=00:00:02, xdelay=00:00:02, mailer=relay, pri=120843, relay=MAILSERVER.DOMAIN.LOCAL. [100.100.100.1], dsn=2.0.0, stat=Sent (<[email protected]> [InternalId=3393981] Queued mail for delivery)
Jul 25 11:40:01 SYATEM1 CRON[25542]: (smmsp) CMD (test -x /etc/init.d/sendmail && /usr/share/sendmail/sendmail cron-msp)
其中一个 Bash 脚本:
#!/bin/bash
#########################################################################################
# Created by: Brandt Winchell #
# Date Modified: 04-13-2014 #
# Version: 2.0 #
# ScriptFunction> #
# Create folder directories for logs & backups #
# Remove local backups older than $RETAINDAYS #
# Transfer the backup files from the VCSA to the local system #
# Verify the backup files exists and are not empty #
# Mail a report (include error report if problem exists) #
# Changelog> #
# 2.0 Added mail functionality for report !!(Sendmail needs to be #
# configured on local machine. Refer to "sendmail --help") #
# Fixed file size check logic #
#########################################################################################
#########################################################################################
# Variables
SYSNAME=$(hostname -s)
REMOTESYSNAME="SYSTEM1"
REMOTEFQDN="SYSTEM1.DOMAIN.LOCAL"
DAY=`date +%d`
MONTH=`date +%m`
YEAR=`date +%Y`
DATEMOD="$DAY$MONTH$YEAR"
REMOTEBKDIR1="/storage/db/backups"
LOCALBKDIR="/storage/backups"
BKFILE="$REMOTESYSNAME"_"$DATEMOD"
BKLOG="/var/log/slog"
BKLOG_DIR="/var/log"
ERRLOG="$REMOTEBKDIR1/$REMOTESYSNAME"_"$DATEMOD.err"
RETAINDAYS="21"
MAILENABLED=true #Send email of reports
SENDER="[email protected]"
RECIPIENT=$2
SUBJECT=$1
BOUNDARY="EOF_FILEBOUNDRY"
MAIL_BODY=$3
declare -a ATTACHMENTS
#########################################################################################
# Function BUILD_MESSAGE
get_mimetype(){
# warning: assumes that the passed file exists
echo "file in array followed by mime-type: $1" >> $BKLOG 2>&1
file --mime-type "$1" | sed 's/.*: //' >> $BKLOG 2>&1
}
# Build headers
build_message(){
printf '%s\n' "From: $SENDER
To: $RECIPIENT
Subject: $SUBJECT
Mime-Version: 1.0
Content-Type: multipart/mixed; boundary=\"$BOUNDARY\"
--${BOUNDARY}
Content-Type: text/html; charset=\"US-ASCII\"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
#MailBody
$MAIL_BODY
"
# now loop over the attachments, guess the type
# and produce the corresponding part, encoded base64
for file in "${ATTACHMENTS[@]}"; do
[ ! -f "$file" ] && echo "Warning: attachment $file not found, skipping" >> $BKLOG 2>&1 && continue
mimetype=$(get_mimetype "$file")
printf '%s\n' "--${BOUNDARY}
Content-Type: $mimetype
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename=\"$file\"
"
base64 "$file"
echo
done
# print last boundary with closing --
printf '%s\n' "--${BOUNDARY}--"
echo "Mail debug:" >> $BKLOG 2>&1
echo "to:$RECIPIENT" >> $BKLOG 2>&1
echo "from:$SENDER" >> $BKLOG 2>&1
echo "Mail body:$MAIL_BODY" >> $BKLOG 2>&1
}
# Function END
#########################################################################################
# Create log file and error log, if one does not exist
# Create backup log directory and file, if it does not exist
if [ ! -d "$BKLOG" ]; then
mkdir -p $BKLOG_DIR
touch $BKLOG >> $BKLOG 2>&1
fi
# Create backup directory, if it does not exist
if [ ! -d "$LOCALBKDIR" ]; then
mkdir -p $LOCALBKDIR >> $BKLOG 2>&1
fi
#########################################################################################
# Begin logging process (Begin log)
echo "****************************************************************************" >> $BKLOG 2>&1
echo "`date`: Script $0 starting" >> $BKLOG 2>&1
echo "`whoami`: User running script" >> $BKLOG 2>&1
#########################################################################################
# Remove any local files older than $RETAINDAYS days old
echo "`date`: Removing backups or error logs older than $RETAINDAYS" >> $BKLOG 2>&1
find $LOCALBKDIR/$REMOTESYSNAME -name $REMOTESYSNAME'*.tar' -mtime +$RETAINDAYS -exec rm -f {} \; >> $BKLOG 2>&1
find $LOCALBKDIR/$REMOTESYSNAME -name $REMOTESYSNAME'*.err' -mtime +$RETAINDAYS -exec rm -f {} \; >> $BKLOG 2>&1
#########################################################################################
# Check to verify backup file is not empty
echo "`date`: Verifying backup file is not empty" >> $BKLOG 2>&1
#(Check file on remote system for file size)
RESULTS=""
RESULTS=$(ssh root@$REMOTEFQDN "/usr/bin/du $REMOTEBKDIR1/$BKFILE.tar" | awk '{print $1}') #(Obtain file size)
echo "DB backup file //$REMOTEFQDN/$REMOTEBKDIR1/$BKFILE size (bytes): $RESULTS" >> $BKLOG 2>&1
if [ "$RESULTS" \> 0 ]; then #(File has content)
echo "Backup file from M:$MONTH D:$DAY Y:$YEAR has content." >> $BKLOG 2>&1
else #(File is empty)
echo "Backup file from M:$MONTH D:$DAY Y:$YEAR is EMPTY. Check the error log stored with the backup" >> $BKLOG 2>&1
echo "Process has ended with error. Check log"
# Send mail report with error report
ATTACHMENTS=( "$BKLOG" )
[[ -z $1 ]] && SUBJECT=":-( ERROR:Backup Report for $REMOTEFQDN from $SYSNAME"
[[ -z $2 ]] && RECIPIENT="[email protected]"
[[ -z $3 ]] && MAIL_BODY="Backup file is empty or missing for $REMOTEFQDN. Check the error log attached or
error log at //$REMOTEFQDN$ERRLOG."
if [ "$MAILENABLED" == true ]; then
echo "Sending mail with error report" >> $BKLOG 2>&1
build_message | sendmail -t -oi
fi
exit 1 #(Stop process and exit script)
fi
#########################################################################################
# Transfer backup files and error logs
echo "`date`: Transferring $BKFILE and $ERRLOG from $REMOTESYSNAME to $SYSNAME" >> $BKLOG 2>&1
# Make the directory structure if it does not exist
if [ ! -d "$LOCALBKDIR/$REMOTESYSNAME" ]; then
mkdir -p $LOCALBKDIR/$REMOTESYSNAME >> $BKLOG 2>&1
fi
# Transfer the $BKFILE.tar file (DB backup)
EXITSTATUS1=""
scp root@$REMOTEFQDN:$REMOTEBKDIR1/$BKFILE.tar $LOCALBKDIR/$REMOTESYSNAME/$BKFILE.tar >> $BKLOG 2>&1 #(Copy the backup file)
EXITSTATUS1=$?
if [ "$EXITSTATUS1" -ne 0 ]; then #(Transfer process had error)
echo "Copy process of $BKFILE from $REMOTEFQDN has failed with result: $EXITSTATUS1" >> $BKLOG 2>&1
else #(Transfer process was successful)
echo "Copy process of $BKFILE from $REMOTEFQDN is successful with resulte: $EXITSTATUS1" >> $BKLOG 2>&1
fi
# Transfer the $BKFILE.err file (error log)
EXITSTATUS2=""
scp root@$REMOTEFQDN:$REMOTEBKDIR1/$BKFILE.err $LOCALBKDIR/$REMOTESYSNAME/$BKFILE.err >> $BKLOG 2>&1 #(Copy the error file)
EXITSTATUS2=$?
if [ "$EXITSTATUS2" -ne 0 ]; then #(Transfer process had error)
echo "Copy process of $ERRLOG from $REMOTEFQDN has failed with result: $EXITSTATUS2" >> $BKLOG 2>&1
else #(Transfer process was successful)
echo "Copy process of $ERRLOG from $REMOTEFQDN is successful with resulte: $EXITSTATUS2" >> $BKLOG 2>&1
fi
echo "`date`: Transferring $BKFILE and $ERRLOG from $REMOTESYSNAME to $SYSNAMEE completed." >> $BKLOG 2>&1
#########################################################################################
# Verify transfer process worked
echo "`date`: Verifying copy function....." >> $BKLOG 2>&1
if [ "$EXITSTATUS1" == 0 ] && [ "$EXITSTATUS2" == 0 ]; then #(Transfer of both files were successful)
echo "Transfer of files to $SYSNAME was successful." >> $BKLOG 2>&1
# Send mail report
[[ -z $1 ]] && SUBJECT=":-) SUCCESS:Backup Report for $REMOTEFQDN from $SYSNAME"
[[ -z $2 ]] && RECIPIENT="[email protected]"
[[ -z $3 ]] && MAIL_BODY="Backup & transfer successful for $REMOTEFQDN on $MONTH $DAY $YEAR. Transferred://$REMOTEFQDN
$REMOTEBKDIR1/$BKFILE (size $RESULTS Kb) to //$SYSNAME/$LOCALBKDIR/$REMOTESYSNAME"
if [ "$MAILENABLED" == true ]; then
echo "Sending mail for successful transfer" >> $BKLOG 2>&1
build_message | sendmail -t -oi
fi
else #(At least one file failed to transfer)
echo "Transfer of files to $SYSNAME FAILED. Check $BKLOG for more details." >> $BKLOG 2>&1
# Send mail report
ATTACHMENTS=( "$BKLOG" "$LOCALBKDIR/$REMOTESYSNAME/$BKFILE.err" )
[[ -z $1 ]] && SUBJECT=":-( ERROR:Backup Report for $REMOTEFQDN from $SYSNAME"
[[ -z $2 ]] && RECIPIENT="[email protected]"
[[ -z $3 ]] && MAIL_BODY="Backup or transfer failed for $REMOTEFQDN. Check the log at $BKLOG"
if [ "$MAILENABLED" == true ]; then
echo "Sending mail for failed transfer" >> $BKLOG 2>&1
build_message | sendmail -t -oi
fi
fi
#########################################################################################
# Cleanup variables
EXITSTATUS1=""
EXITSTATUS2=""
#########################################################################################
# End logging statement
echo "`date`: Script $0 ended" $BKLOG 2>&1
echo "****************************************************************************" >> $BKLOG 2>&1
更新:
当我运行时,run-parts --test /etc/cron.daily
我得到以下列表。
/etc/cron.daily/apt
/etc/cron.daily/apt-show-versions
/etc/cron.daily/aptitude
/etc/cron.daily/dpkg
/etc/cron.daily/logrotate
/etc/cron.daily/ntp
/etc/cron.daily/passwd
/etc/cron.daily/sendmail
/etc/cron.daily/upstart
我的自定义脚本未列出。
答案1
/etc/cron.daily(或其他 Cron 目录)中的文件名称不能带有“.” 。
名称必须全部由大写字母、小写字母、数字、连字符或下划线组成。原因是 run-parts 不会拾取不遵循此规则的文件。
http://voidtech.wordpress.com/2014/02/13/cron-a-script-in-cron-daily-folder-is-not-executed-fix/ http://justcheckingonall.wordpress.com/2009/06/28/cron-does-not-run-scripts/
答案2
用户 crontabs 由crontab -e
或给出crontab -l
,包括不是系统 crontab。用户 crontab 存储在 /var/spool/ 中的文件中,通常是 /var/spool/cron/crontab/用户名
编辑这些内容的安全/干净的方法是使用crontab -e
,因为它会自动验证语法并在您犯错误时发出警告,从而不允许您搞得太糟。
但是,原帖作者的疑问是关于系统 cron 脚本,例如/etc/cron.daily
,/etc/cron.weekly
等等。通常,这些脚本被调用是因为它们位于 /etc/crontab 的 crontab 文件中。另一组 crontab 也位于 /etc/cron.d/*。这些脚本以及 /etc/cron.{daily,weekly,...} 中的脚本被视为“系统” cron。
这些系统 cron 的运行与 root 的 crontab 内容无关,即使 root 的 crontab 完全为空。这些 crontab(crontab,而不是脚本)也略有不同,因为有一个额外的列(第 6 列),您必须在其中指定要以哪个用户名运行条目。当然,在“用户” cron 中,此列是不必要的。
答案3
您说的是sudo
运行脚本。检查脚本是否已在根的crontab 列表用于sudo crontab -l
列出 root 的任务。
如果脚本挂号的在root的crontab中,最可能的错误可能是:
- 脚本的路径可能是相对的,而不是绝对的,这是首选的解决方案
- 脚本本身被标记为 chmoded
- 在执行作业期间,cron 不会加载各种环境变量
如果脚本尚未注册在 root 的 crontab 中,这里有一个如何注册它们的示例:
backup.sh
假设我有一个名为located at 的备份脚本/root/bin
,我希望每 10 天在我的计算机上运行一次,并且是系统(root)的作业。要将其注册到 root 的 crontab:
- 键入
sudo crontab -e
以打开 root 的 crontab 进行编辑 - 在新行中输入:
08 22 */10 * * /root/bin/backup.sh packages directories dbs remote email &>/dev/null
运行 cron 作业以 root 身份每 10 天 22:08 运行一次,参数如下:packages directories dbs remote email
和将任何输出发送至/dev/null
。
结果是备份脚本将在特定时间由 root 开始执行,并执行其工作以备份各种目录、apt 源、数据库、将 tar 备份存档 scp 到远程服务器并向管理员发送电子邮件。如您所见,复杂的 cron 作业作为系统任务成功运行。