#!/bin/bash set -xeuo pipefail # With systemd, we can force logging to the journal. This is better than # spamming the world with cron mails. You can then view these logs using # "journalctl -rat upgrade-and-reboot". if which logger >/dev/null 2>&1 then # Dump stdout and stderr to logger, which will then put everything # into the journal. exec 1> >(logger -t upgrade-and-reboot -p user.info) exec 2> >(logger -t upgrade-and-reboot -p user.error) fi statusfile="/var/tmp/unattended_upgrades.status" # Workaround, because /var/tmp is usually 1777 [[ "$UID" == 0 ]] && chown root:root "$statusfile" logins=$(ps h -C sshd -o euser | awk '$1 != "root" && $1 != "sshd" && $1 != "sshmon"') if [[ -n "$logins" ]] then echo "Will abort now, there are active SSH logins: $logins" echo "abort_ssh" > "$statusfile" exit 1 fi softlockdir=/var/lib/bundlewrap/soft-${node.name} mkdir -p "$softlockdir" printf '{"comment": "UPDATE", "date": %s, "expiry": %s, "id": "UNATTENDED", "items": ["*"], "user": "root@localhost"}\n' \ $(date +%s) \ $(date -d 'now + 30 mins' +%s) \ >"$softlockdir"/UNATTENDED trap 'rm -f "$softlockdir"/UNATTENDED' EXIT ( apt-get update DEBIAN_FRONTEND=noninteractive apt-get -y -q -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef dist-upgrade ) ret=$? echo "apt-get dist-upgrade exited $ret" echo "$ret" > "$statusfile" if (( $ret != 0 )) then exit 1 fi DEBIAN_FRONTEND=noninteractive apt-get -y -q autoclean DEBIAN_FRONTEND=noninteractive apt-get -y -q autoremove % if clean_old_kernels: existing=$(dpkg --get-selections | grep -E '^linux-(image|headers)-[0-9]' || true) if [[ -z "$existing" ]] then echo "ERROR: No installed kernels found! Aborting!" >&2 exit 1 fi current=$(uname -r | sed -r 's/-[a-zA-Z]+$//') latest=$(echo "$existing" | sort --version-sort -t- -k 3,4 | tail -n 1 | sed -r 's/[^0-9]+([0-9]\.[^-]+-[0-9]+).*/\1/') todelete=$(echo "$existing" | grep -v -E "($current|$latest)" | awk '{ print $1 }' || true) if [[ -n "$todelete" ]] then DEBIAN_FRONTEND=noninteractive apt-get -qy purge $todelete fi % endif if [[ -f /var/run/reboot-required ]] then % if 'mail' in data: date | mail -s "SYSREBOOTNOW ${node.name}" ${data['mail']} % endif systemctl reboot % if restart_triggers: else % for affected, restarts in sorted(restart_triggers.items()): up_since=$(systemctl show "${affected}" | sed -n 's/^ActiveEnterTimestamp=//p' || echo 0) up_since_ts=$(date -d "$up_since" +%s || echo 0) now=$(date +%s) if [ $((now - up_since_ts)) -lt 3600 ] then % for restart in sorted(restarts): systemctl restart "${restart}" || true % endfor fi % endfor % endif fi