Setting up a daily apt-get check with email

I don’t log into my Debian webhost every day, so one of the first things I do out of habit now is to check and see there are any updates available for the system with your usual:

$ sudo apt-get update
$ sudo apt-get upgrade

Why not automate the process, and have the system automatically check for me, and let me know when there are updates available?

Of course, I’m not the first person to think of this, so there is a lot of prior work out there. I used Mattias Wikström’s Apt Update script as my foundation.

The script

The script is pretty basic - it runs apt-get update, and if it returns successful, runs a simulated upgrade with apt-get --simulate upgrade. If the output from that includes “Inst”, there were packages that would have been installed, so the update_found variable is set to true.

The script then builds the email message, using the email variable as the main part of the message, and appends the output from the simulated upgrade, and finally sends the email using msmtp, as I previous described and set up.

#!/bin/sh
#
# Cron Script - place in /etc/cron.daily
#
# Runs "apt-get update" and prints the output of a simulated
# upgrade if any package would be installed.
# 
# script from: http://www.mattiaswikstrom.net/linux/20050526-apt-update-script.html
#

email="From: server@address.com
To: email@address.com
Subject: Updates are available for your server
Mime-Version: 1.0
Content-Type: text/html

<h2>Updates are available</h2>
<p>Run apt-get upgrade to install the following updates:</p>"

update_found=false
apt-get update | grep -q '^Get' \
        && sim=$(apt-get --simulate upgrade) \
        && echo "$sim" | grep -q '^Inst' \
        && update_found=true

if [ "$update_found" = "true" ]; then
    email="$email $sim"
    echo "$email" | msmtp email@address.com
fi 

exit 0

Save the script to /etc/cron.daily folder without the .sh extension (this is surprisingly important - it took me a bit to figure out why it wasn’t working at first), and then chmod it to be executable.

$ sudo touch /etc/cron.daily/apt-get_email
$ sudo vim /etc/cron.daily/apt-get_email
$ sudo chmod +x /etc/cron.daily/apt-get_email

Setting up cron

Now that the script is created, we need to set up cron to run this script on a daily basis.

Cron logs are, by default, stored in /var/log/syslog. Since I’m going to be doing stuff with cron, I decided I wanted to have cron logs go to their own log file. Thankfully, changing the setting for this is simple - in /etc/rsyslog.conf, find the cron line under “Rules” that is commented out, and remove the comment (it was on line 63 for me), and then restart rsyslog:

-- Edit /etc/rsyslog.conf
$ sudo vim /etc/rsyslog.conf

-- Find and remove # on cron line
# cron.*              /var/log/cron.log

-- Restart rsyslog
$ sudo systemctl restart rsyslog.service

Testing the script

Finally, we’re ready to test the script. Keep in mind - if there’s not currently any updates available, the script won’t send an email. If this is the case, you can change the value of update_found on line 21 from false to true, which will cause the email to be sent regardless if there are updates available or not.

You can either run the script manually, or trigger cron to rerun it’s daily scripts manually:

$ sudo run-parts /etc/cron.daily/

Once the cron.daily scripts run, you should be see output in your new cron log:

$ sudo cat /var/log/cron.log
Jul 21 20:33:18 -username- anacron[16255]: Updated timestamp for job `cron.daily' to 2016-07-21

If everything worked correctly, you should receive an email with the output of the simulated apt-get update.

layouts/post/single.html