#!/bin/sh # Void auto-update: # - full xbps-install -Syu # - reboot only for a new kernel # - otherwise restart runit services still running old binaries/libs set -eu LOG=/var/log/void-auto-update.log rc=0 trap '[ $? -eq 0 ] || echo "$(date "+%F %T") FAILED" | tee -a "$LOG" >&2' EXIT echo "=== [$(date '+%F %T')] Starting auto-update ===" # 1. Finish interrupted transactions, drop old unowned kernels. # Orphans only if we run the newest kernel: otherwise -o may remove # the package of the running kernel (with its modules). xbps-reconfigure -a vkpurge rm all newest=$(ls /boot/vmlinuz-* | sed 's|/boot/vmlinuz-||' | sort -V | tail -n1) if [ "$newest" = "$(uname -r)" ]; then xbps-remove -yo fi # 2. Free space: new kernel + modules + initramfs + dracut tmp ~ 400 MB avail_kb=$(df -kP / | awk 'NR==2 {print $4}') if [ "$avail_kb" -lt 512000 ]; then echo "ERROR: only $avail_kb KiB free on /, need 512000. Aborting." >&2 exit 1 fi # 3. Download under timeout, install from cache without timeout # (killing xbps mid-unpack leaves half-installed packages) timeout 1h xbps-install -SyuD xbps xbps-install -yu xbps timeout 1h xbps-install -SyuD xbps-install -yu xbps-remove -yO # 4. Never restart sshd or reboot with a broken sshd config if ! sshd -t; then echo "ERROR: sshd -t failed. No restarts, no reboot." >&2 exit 1 fi # 5. Kernel: grub boots the newest one -> reboot if we don't run it new_kver=$(ls /boot/vmlinuz-* | sed 's|/boot/vmlinuz-||' | sort -V | tail -n1) if [ "$new_kver" != "$(uname -r)" ]; then if [ -s "/boot/initramfs-$new_kver.img" ] && grep -qF "vmlinuz-$new_kver" /boot/grub/grub.cfg; then echo "$(date '+%F %T') reboot: $(uname -r) -> $new_kver" | tee -a "$LOG" reboot exit 0 fi echo "ERROR: initramfs or grub.cfg entry missing for $new_kver. Not rebooting." >&2 rc=1 fi # 6. Restart runit services still running deleted (updated) binaries/libs restarted="" for p in $(xcheckrestart | awk '{print $1}'); do for svc_dir in /var/service/*; do [ "$(cat "$svc_dir/supervise/pid" 2>/dev/null)" = "$p" ] || continue svc=${svc_dir##*/} case "$svc" in agetty-*|udevd|ufw|crond|dbus|elogind|NetworkManager|docker|containerd|tmux*) continue ;; esac echo "Restarting $svc (pid $p)" if sv restart "$svc"; then restarted="$restarted $svc" else rc=1 fi done done [ -z "$restarted" ] || echo "$(date '+%F %T') restart:$restarted" >> "$LOG" echo "=== [$(date '+%F %T')] Auto-update finished (rc=$rc) ===" exit $rc