#!/bin/bash # # apt dist-upgrade of all RUNNING containers (containers only — VMs are # excluded, they may not run an agent or apt at all). Containers without # apt are skipped. Exits non-zero if any upgrade failed. set -uo pipefail INCUS=/usr/bin/incus LOG=/var/log/incus-container-upgrade.log LOCKFILE=/run/lock/incus-container-upgrade.lock # refuse to overlap with a previous, still-running invocation exec 9> "$LOCKFILE" if ! flock -n 9; then echo "another incus-container-upgrade run holds $LOCKFILE, aborting" >&2 exit 1 fi distUpgrade() { local CT=$1 echo -e "\n*** [$(date '+%F %T')] - Dist-upgrading $CT container ***\n" if ! $INCUS exec "$CT" -- sh -c 'command -v apt-get >/dev/null'; then echo "$CT: no apt-get in container, skipping" return 0 fi $INCUS exec "$CT" --env DEBIAN_FRONTEND=noninteractive -- apt-get -qq update && $INCUS exec "$CT" -- sh -c 'apt list --upgradable 2>/dev/null' && $INCUS exec "$CT" --env DEBIAN_FRONTEND=noninteractive -- apt-get -qq -y dist-upgrade } RC=0 for CT in $($INCUS list -c n -f csv status=RUNNING type=container); do if ! distUpgrade "$CT" 2>&1 | tee -a "$LOG"; then echo "[$(date '+%F %T')] FAILED: $CT" | tee -a "$LOG" >&2 RC=1 fi done exit $RC