11

I have a few scripts (that currently run in a CentOS system) I have moved to a new Ubuntu 14.04 system. These scripts are in the /etc/cron.daily to run once a day. These scripts are to run at the system level as root. If I run the scripts with the "sudo" command or run as root (sudo -i), the scripts do exactly what they are supposed to.

Thanks B

Problem:

Cron daily runs but does not activate my bash scripts. I cannot find any record of Cron attempting to run the script

File/Folder permissions:

/etc/cron.daily = root:root 755

etc/cron.daily/bash.sh = root:root 755

var/log/slog (log file for script) = root:root 644

Output of syslog:

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)

Output when script is run manually:

    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)

One of the Bash scripts:

    #!/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

UPDATE:

When I run run-parts --test /etc/cron.daily I get the following list.

/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

My custom scripts are not listed.

1

3 Answers 3

14

You cannot have files within /etc/cron.daily (or the other Cron directories) with a "." in the name.
The name must consist of all upper,lower,numbers,hyphens, or underscores. The reason is run-parts will not pickup the files that do not follow this rule.

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/

1
  • Right. Commands shouldn't have extensions anyway, so that's a good thing.
    – geirha
    Jul 26, 2014 at 12:22
1

The user crontabs, as given by crontab -e or crontab -l, are NOT system crontabs. User crontabs are stored as files within /var/spool/, typically /var/spool/cron/crontab/username

The safe/clean way to edit these is using crontab -e, as it automatically validates the syntax and complains if you make a mistake, thereby not allowing you to mess up too badly.

However, the OP's query is regarding system cron scripts as at /etc/cron.daily, /etc/cron.weekly, and so forth. Typically these scripts are called due to their being within the crontab file at /etc/crontab. Another set of crontabs are also at /etc/cron.d/*. These, along with the scripts in /etc/cron.{daily,weekly,...} are considered the "system" crons.

These system crons are run regardless of the content of root's crontab, even if root's crontab is completely empty. These crontabs (the crontabs, not the scripts) are also a little different in that there is an extra column (column 6) where you have to specify the username that the entry is to run as. This column is of course unnecessary in the "user" crons.

0

You say that with sudo the scripts run. Check if the scripts are registered at root's crontab list using sudo crontab -l to list root's jobs.

If the scripts are registered in root's crontab, then the most probable errors may be:

  • The path to the script may be relative and not absolute which is the prefered solution
  • The script itself is noted chmoded
  • Various environment variables are not loaded by cron during the execution of the jobs

If the scripts are not registered in root's crontab here is an example on how to register them:

Say I have a backup script named backup.sh located at /root/bin `that I want to run on my machine every 10 days and is a system (root's) job. To register it at root's crontab:

  • Type sudo crontab -e to open the root's crontab for edit
  • In a new line enter:

08 22 */10 * * /root/bin/backup.sh packages directories dbs remote email &>/dev/null

To run the cron job as root at 22:08 every 10 days with arguments: packages directories dbs remote email and send any output to /dev/null.

The result is that the backup script will start executing at the specific time by root and will do it's job to backup various directories, apt sources, databases, scp to remote server the tar backup archive and send email to the administrator. As you can see a complex cron job run as system task successfully.

Not the answer you're looking for? Browse other questions tagged .