Skip to content

Instantly share code, notes, and snippets.

@S4tyendra
Last active May 13, 2025 04:28
Show Gist options
  • Save S4tyendra/7152fb0a6f66e5436bbe6ab24296f9bd to your computer and use it in GitHub Desktop.
Save S4tyendra/7152fb0a6f66e5436bbe6ab24296f9bd to your computer and use it in GitHub Desktop.
Update ubuntu systems automatically
#!/bin/bash
set -eo pipefail
# --- Banner ---
echo "======================================"
echo "πŸš€ Automated Ubuntu LTS Upgrade Tool"
echo "======================================"
# --- Check for sudo/root ---
if [[ "$EUID" -ne 0 ]]; then
echo "❌ Error: This script requires root privileges"
echo "πŸ“Œ Please run with: sudo $0"
exit 1
fi
# --- Pre-upgrade checks ---
echo "πŸ” Performing pre-upgrade checks..."
# Check disk space (require at least 5GB free)
FREE_SPACE=$(df -BG / | awk 'NR==2 {print $4}' | tr -d 'G')
if [[ "${FREE_SPACE%.*}" -lt 5 ]]; then
echo "❌ Error: Insufficient disk space (${FREE_SPACE}GB). At least 5GB recommended."
exit 1
fi
# Create timestamp for files
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
BACKUP_DIR="/root/pre-upgrade-backup-${TIMESTAMP}"
LOG_FILE="/var/log/system-upgrade-${TIMESTAMP}.log"
PACKAGE_LIST="${BACKUP_DIR}/installed-packages.txt"
PACKAGE_SELECTIONS="${BACKUP_DIR}/package-selections.txt"
REPO_BACKUP_DIR="${BACKUP_DIR}/sources.list.d"
APT_KEYS_BACKUP="${BACKUP_DIR}/apt-trusted-keys.gpg"
APT_KEYRINGS_DIR="${BACKUP_DIR}/keyrings"
# Create backup directories
mkdir -p "$BACKUP_DIR" "$REPO_BACKUP_DIR" "$APT_KEYRINGS_DIR"
# --- Save installed packages ---
echo "πŸ“¦ Saving list of installed packages..." | tee -a "$LOG_FILE"
apt-mark showmanual > "$PACKAGE_LIST"
dpkg --get-selections > "$PACKAGE_SELECTIONS"
echo "πŸ“‹ Package lists saved to:" | tee -a "$LOG_FILE"
echo " - $PACKAGE_LIST (manually installed packages)" | tee -a "$LOG_FILE"
echo " - $PACKAGE_SELECTIONS (all package selections)" | tee -a "$LOG_FILE"
# --- Backup repositories ---
echo "πŸ” Backing up repository configurations..." | tee -a "$LOG_FILE"
# Copy main sources.list
cp /etc/apt/sources.list "${BACKUP_DIR}/sources.list.original"
# Copy all repository files from sources.list.d
cp -r /etc/apt/sources.list.d/* "$REPO_BACKUP_DIR" 2>/dev/null || true
# Backup trusted keys
cp /etc/apt/trusted.gpg "$APT_KEYS_BACKUP" 2>/dev/null || true
cp -r /etc/apt/trusted.gpg.d/* "$APT_KEYS_BACKUP.d" 2>/dev/null || mkdir -p "$APT_KEYS_BACKUP.d"
# Backup keyrings directory if it exists
cp -r /etc/apt/keyrings/* "$APT_KEYRINGS_DIR" 2>/dev/null || true
# Save PPA information if add-apt-repository is available
if command -v add-apt-repository > /dev/null; then
add-apt-repository --list > "${BACKUP_DIR}/ppa-list.txt" 2>/dev/null || true
fi
echo "πŸ“¦ Repository configurations backed up to $REPO_BACKUP_DIR" | tee -a "$LOG_FILE"
# Create recovery script
RECOVERY_SCRIPT="${BACKUP_DIR}/restore-packages.sh"
cat > "$RECOVERY_SCRIPT" << 'EOL'
#!/bin/bash
set -e
if [[ "$EUID" -ne 0 ]]; then
echo "❌ Please run as root or with sudo."
exit 1
fi
SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"
PACKAGE_LIST="${SCRIPT_DIR}/installed-packages.txt"
PACKAGE_SELECTIONS="${SCRIPT_DIR}/package-selections.txt"
SOURCES_ORIGINAL="${SCRIPT_DIR}/sources.list.original"
SOURCES_BACKUP_DIR="${SCRIPT_DIR}/sources.list.d"
APT_KEYS_BACKUP="${SCRIPT_DIR}/apt-trusted-keys.gpg"
APT_KEYRINGS_BACKUP="${SCRIPT_DIR}/keyrings"
if [[ ! -f "$PACKAGE_LIST" || ! -f "$PACKAGE_SELECTIONS" ]]; then
echo "❌ Package lists not found in ${SCRIPT_DIR}"
exit 1
fi
# --- Restore repositories (optional) ---
echo "πŸ”„ Would you like to restore your original repository sources? (y/n)"
read -r RESTORE_REPOS
if [[ "$RESTORE_REPOS" == "y" || "$RESTORE_REPOS" == "Y" ]]; then
echo "πŸ” Restoring repository configurations..."
# Backup current sources just in case
CURRENT_BACKUP="/etc/apt/sources.list.before-restore"
echo "πŸ“¦ Backing up current sources.list to $CURRENT_BACKUP"
cp /etc/apt/sources.list "$CURRENT_BACKUP"
# Restore main sources file
if [[ -f "$SOURCES_ORIGINAL" ]]; then
echo "πŸ“„ Restoring main sources.list..."
cp "$SOURCES_ORIGINAL" /etc/apt/sources.list
fi
# Restore additional sources
if [[ -d "$SOURCES_BACKUP_DIR" && -n "$(ls -A "$SOURCES_BACKUP_DIR" 2>/dev/null)" ]]; then
echo "πŸ“ Restoring sources.list.d directory..."
cp -r "$SOURCES_BACKUP_DIR"/* /etc/apt/sources.list.d/ 2>/dev/null || true
fi
# Restore trusted keys
if [[ -f "$APT_KEYS_BACKUP" ]]; then
echo "πŸ”‘ Restoring trusted APT keys..."
cp "$APT_KEYS_BACKUP" /etc/apt/trusted.gpg 2>/dev/null || true
fi
# Restore keyrings
if [[ -d "$APT_KEYRINGS_BACKUP" && -n "$(ls -A "$APT_KEYRINGS_BACKUP" 2>/dev/null)" ]]; then
echo "πŸ” Restoring APT keyrings..."
mkdir -p /etc/apt/keyrings
cp -r "$APT_KEYRINGS_BACKUP"/* /etc/apt/keyrings/ 2>/dev/null || true
fi
echo "βœ… Repository configurations restored!"
fi
echo "πŸ”„ Updating package lists..."
apt update || {
echo "⚠️ APT update failed. Please check your sources.list and try again."
echo "πŸ“ You can view your backed up sources in $SCRIPT_DIR"
exit 1
}
apt install openssh-server -y || {
echo "⚠️ SSH Server installation failed!."
}
echo "πŸ“¦ Reinstalling packages from list..."
xargs apt install -y < "$PACKAGE_LIST" || true
echo "πŸ”„ Restoring package selections..."
dpkg --set-selections < "$PACKAGE_SELECTIONS"
apt-get dselect-upgrade -y || true
echo "βœ… Package restoration completed!"
echo "πŸ“‹ Note: Some packages may not have been restored if they're no longer available"
echo " in the repositories or are incompatible with the new Ubuntu release."
EOL
chmod +x "$RECOVERY_SCRIPT"
echo "πŸ“œ Recovery script created at $RECOVERY_SCRIPT" | tee -a "$LOG_FILE"
# --- Package management ---
echo "πŸ”„ Updating package lists..." | tee -a "$LOG_FILE"
apt update >> "$LOG_FILE" 2>&1 || { echo "❌ Failed to update package lists"; exit 1; }
echo "πŸ“¦ Upgrading existing packages..." | tee -a "$LOG_FILE"
apt upgrade -y >> "$LOG_FILE" 2>&1 || { echo "❌ Failed to upgrade packages"; exit 1; }
echo "βš™οΈ Performing distribution upgrade..." | tee -a "$LOG_FILE"
apt dist-upgrade -y >> "$LOG_FILE" 2>&1 || { echo "❌ Failed to perform distribution upgrade"; exit 1; }
echo "🧹 Cleaning up unnecessary packages..." | tee -a "$LOG_FILE"
apt autoremove --purge -y >> "$LOG_FILE" 2>&1
apt clean >> "$LOG_FILE" 2>&1
# --- Prepare for release upgrade ---
echo "πŸ› οΈ Installing and configuring upgrade tools..." | tee -a "$LOG_FILE"
apt install -y update-manager-core >> "$LOG_FILE" 2>&1 || { echo "❌ Failed to install update-manager-core"; exit 1; }
# Configure for LTS releases only
echo "πŸ“„ Setting release upgrade policy to LTS..." | tee -a "$LOG_FILE"
sed -i 's/^Prompt=.*/Prompt=lts/' /etc/update-manager/release-upgrades
# --- Backup important configuration ---
echo "πŸ’Ύ Creating backup of critical system files..." | tee -a "$LOG_FILE"
cp -a /etc/fstab /etc/network /etc/ssh "$BACKUP_DIR" 2>/dev/null || true
echo "πŸ“ System configuration backup stored in $BACKUP_DIR" | tee -a "$LOG_FILE"
# --- Execute release upgrade ---
echo "πŸš€ Starting non-interactive upgrade to latest LTS..." | tee -a "$LOG_FILE"
echo "⏳ This may take a while. Please be patient."
export DEBIAN_FRONTEND=noninteractive
do-release-upgrade -f DistUpgradeViewNonInteractive >> "$LOG_FILE" 2>&1 || {
echo "⚠️ Release upgrade process exited with status $?"
echo "πŸ“– Check $LOG_FILE for details"
echo "πŸ“¦ If needed, restore packages using $RECOVERY_SCRIPT"
echo "⚠️ Manual intervention may be required!"
exit 1
}
# --- Final cleanup and reboot ---
echo "🧹 Performing final system cleanup..." | tee -a "$LOG_FILE"
apt autoremove --purge -y >> "$LOG_FILE" 2>&1
apt clean >> "$LOG_FILE" 2>&1
echo "βœ… Upgrade process completed successfully!" | tee -a "$LOG_FILE"
echo "πŸ“‹ Summary:" | tee -a "$LOG_FILE"
echo " - System upgraded to latest LTS release" | tee -a "$LOG_FILE"
echo " - Logs available at: $LOG_FILE" | tee -a "$LOG_FILE"
echo " - Backup saved to: $BACKUP_DIR" | tee -a "$LOG_FILE"
echo " - Package lists backed up and can be restored with: $RECOVERY_SCRIPT" | tee -a "$LOG_FILE"
echo " - Repository sources backed up to: $REPO_BACKUP_DIR" | tee -a "$LOG_FILE"
# Schedule reboot with countdown
echo "πŸ”„ System will reboot in 30 seconds. Press Ctrl+C to cancel." | tee -a "$LOG_FILE"
sleep 5
echo "πŸ”„ Rebooting in 25 seconds..." | tee -a "$LOG_FILE"
sleep 5
echo "πŸ”„ Rebooting in 20 seconds..." | tee -a "$LOG_FILE"
sleep 5
echo "πŸ”„ Rebooting in 15 seconds..." | tee -a "$LOG_FILE"
sleep 5
echo "πŸ”„ Rebooting in 10 seconds..." | tee -a "$LOG_FILE"
sleep 5
echo "πŸ”„ Rebooting in 5 seconds..." | tee -a "$LOG_FILE"
sleep 5
echo "πŸ”„ Rebooting now!" | tee -a "$LOG_FILE"
reboot
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment