#!/bin/bash
set -euo pipefail
# =========================================================
# Pre-upgrade snapshot
# Captures system state into a timestamped directory.
# =========================================================
SNAP="/root/pre-upgrade-$(date +%F-%H%M)"
mkdir -p "$SNAP" && cd "$SNAP"
echo "[+] Collecting system info..."
# ---------- System identity ----------
{
echo "=== hostnamectl ===" ; hostnamectl
echo ; echo "=== /etc/os-release ===" ; cat /etc/os-release
echo ; echo "=== uname -a ===" ; uname -a
echo ; echo "=== uptime ===" ; uptime
} > sysinfo.txt
# ---------- Held packages ----------
apt-mark showhold > holds.txt
# ---------- Services ----------
{
echo "=== systemctl --failed ==="
systemctl --failed
echo
echo "=== inactive services ==="
systemctl list-units --type=service --all | grep inactive || true
} > services.txt
# ---------- Storage / mounts ----------
{
echo "=== findmnt ===" ; findmnt
echo ; echo "=== /etc/fstab ===" ; cat /etc/fstab
} > storage.txt
# ---------- Network ----------
{
echo "=== ip -br -c a ==="
ip -br -c a
echo
echo "=== /etc/netplan ==="
cat /etc/netplan/*.yaml 2>/dev/null || true
echo
echo "=== iptables -nvL ==="
iptables -nvL || true
echo
echo "=== iptables -t nat -nvL ==="
iptables -t nat -nvL || true
} > network.txt
# ---------- /etc backup ----------
# Compressed archive of /etc so that, if apt overwrites a config file
# during the upgrade (the Y/I/N/O/D/Z prompt), we have a pristine copy
# to diff and restore from. Saved inside $SNAP for a single self-
# contained pre-upgrade folder; 2>/dev/null swallows benign warnings
# about /etc/.pwd.lock or sockets that change mid-archive.
echo "[+] Backing up /etc ..."
tar -czf etc.tar.gz /etc 2>/dev/null || true
echo
echo "[+] Snapshot saved to: $SNAP"
ls -lah "$SNAP"What each file gives you back later:
sysinfo.txt— distro/kernel version + uptime. The “before” line of any post-mortem.holds.txt— packages explicitly held back. Empty is fine; non-empty means those holds need to survive the upgrade.services.txt— failed and inactive services as they are right now. Critical: if a service is already failed before the upgrade, you don’t want to chase it as a regression afterwards.storage.txt— runtime mounts vs persistentfstab. A discrepancy is a red flag worth investigating before the reboot, not after.network.txt— interfaces, netplan, firewall rules. Iptables especially: Docker recreates its chains on every restart, but your custom rules don’t come back unlessnetfilter-persistentsurvived the upgrade.