.
This commit is contained in:
Vendored
+255
@@ -0,0 +1,255 @@
|
||||
#!/bin/bash
|
||||
# =============================================
|
||||
# Debian Distribution Upgrade Script
|
||||
# Upgrades Debian to the next stable release
|
||||
# =============================================
|
||||
# Configuration
|
||||
LOG_FILE="/var/log/debian_upgrade.log"
|
||||
BACKUP_DIR="/root/debian_upgrade_backup_$(date +%Y%m%d_%H%M%S)"
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[1;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Function to log messages
|
||||
log() {
|
||||
echo -e "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
|
||||
}
|
||||
|
||||
# Function to ask for confirmation
|
||||
ask_confirmation() {
|
||||
local message="$1"
|
||||
local default="$2" # "y" or "n"
|
||||
while true; do
|
||||
if [ "$default" = "y" ]; then
|
||||
read -p "$message [Y/n]: " choice < /dev/tty
|
||||
else
|
||||
read -p "$message [y/N]: " choice < /dev/tty
|
||||
fi
|
||||
# Default choice if user just presses Enter
|
||||
if [ -z "$choice" ]; then
|
||||
choice="$default"
|
||||
fi
|
||||
case "$choice" in
|
||||
y|Y|yes|Yes|YES)
|
||||
return 0
|
||||
;;
|
||||
n|N|no|No|NO)
|
||||
return 1
|
||||
;;
|
||||
*)
|
||||
echo "Please answer yes or no."
|
||||
;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
# Function to check if running on Raspberry Pi
|
||||
is_raspberry_pi() {
|
||||
if [ -f /proc/device-tree/model ] && grep -q "Raspberry Pi" /proc/device-tree/model; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to validate if curl is installed
|
||||
check_curl() {
|
||||
if ! command -v curl >/dev/null 2>&1; then
|
||||
log "Installing curl..."
|
||||
if ! apt install -y curl; then
|
||||
log "${RED}Failed to install curl${NC}"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
# Function to get current Debian version
|
||||
get_current_version() {
|
||||
CURRENT_VERSION=$(cat /etc/debian_version | cut -d'.' -f1)
|
||||
CURRENT_CODENAME=$(grep -oP '(?<=VERSION_CODENAME=).*' /etc/os-release)
|
||||
log "Current Debian version: $CURRENT_CODENAME (Debian $CURRENT_VERSION)"
|
||||
}
|
||||
|
||||
# Function to get next Debian stable version
|
||||
get_next_version() {
|
||||
if ! check_curl; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
NEXT_CODENAME=$(curl -s "http://ftp.debian.org/debian/dists/stable/Release" | grep -oP '(?<=Codename: ).*' | head -n 1)
|
||||
if [ -z "$NEXT_CODENAME" ]; then
|
||||
log "${RED}Failed to fetch next Debian version${NC}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
NEXT_VERSION=$(curl -s "http://ftp.debian.org/debian/dists/${NEXT_CODENAME}/Release" | grep -oP '(?<=Version: ).*' | cut -d'.' -f1)
|
||||
log "Next Debian version available: $NEXT_CODENAME (Debian $NEXT_VERSION)"
|
||||
return 0
|
||||
}
|
||||
|
||||
# Function to backup important configurations
|
||||
backup_configs() {
|
||||
log "Creating backup of important configurations in $BACKUP_DIR..."
|
||||
mkdir -p "$BACKUP_DIR" || {
|
||||
log "${RED}Failed to create backup directory${NC}"
|
||||
return 1
|
||||
}
|
||||
|
||||
# Backup APT sources
|
||||
cp -a /etc/apt/sources.list "$BACKUP_DIR/" || {
|
||||
log "${RED}Failed to backup /etc/apt/sources.list${NC}"
|
||||
return 1
|
||||
}
|
||||
cp -a /etc/apt/sources.list.d/ "$BACKUP_DIR/" 2>/dev/null || true
|
||||
|
||||
# Backup installed packages
|
||||
dpkg --get-selections > "$BACKUP_DIR/installed_packages.txt" || {
|
||||
log "${RED}Failed to backup installed packages${NC}"
|
||||
return 1
|
||||
}
|
||||
|
||||
# Backup important system configs
|
||||
cp -a /etc/network/interfaces "$BACKUP_DIR/" 2>/dev/null || true
|
||||
cp -a /etc/resolv.conf "$BACKUP_DIR/" 2>/dev/null || true
|
||||
cp -a /etc/ssh/sshd_config "$BACKUP_DIR/" 2>/dev/null || true
|
||||
|
||||
log "${GREEN}Backup completed successfully${NC}"
|
||||
return 0
|
||||
}
|
||||
|
||||
# Function to update APT repositories
|
||||
update_repositories() {
|
||||
log "Updating APT repositories to $NEXT_CODENAME..."
|
||||
sed -i "s/$CURRENT_CODENAME/$NEXT_CODENAME/g" /etc/apt/sources.list || {
|
||||
log "${RED}Failed to update /etc/apt/sources.list${NC}"
|
||||
return 1
|
||||
}
|
||||
|
||||
if [ -d /etc/apt/sources.list.d/ ]; then
|
||||
find /etc/apt/sources.list.d/ -type f -name "*.list" -exec sed -i "s/$CURRENT_CODENAME/$NEXT_CODENAME/g" {} \; || {
|
||||
log "${RED}Failed to update repositories in /etc/apt/sources.list.d/${NC}"
|
||||
return 1
|
||||
}
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# Function to perform the upgrade
|
||||
perform_upgrade() {
|
||||
log "Updating package lists..."
|
||||
if ! apt update; then
|
||||
log "${RED}Failed to update package lists${NC}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
log "Performing full upgrade..."
|
||||
if ! apt full-upgrade -y; then
|
||||
log "${RED}Failed to perform full upgrade${NC}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
log "Performing distribution upgrade to $NEXT_CODENAME..."
|
||||
if ! apt dist-upgrade -y; then
|
||||
log "${RED}Failed to perform distribution upgrade${NC}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# Function to clean up after upgrade
|
||||
cleanup() {
|
||||
log "Cleaning up..."
|
||||
apt autoremove -y || log "${YELLOW}Warning: Failed to autoremove packages${NC}"
|
||||
apt clean || log "${YELLOW}Warning: Failed to clean APT cache${NC}"
|
||||
return 0
|
||||
}
|
||||
|
||||
# Function to verify upgrade
|
||||
verify_upgrade() {
|
||||
NEW_CODENAME=$(grep -oP '(?<=VERSION_CODENAME=).*' /etc/os-release)
|
||||
if [ "$NEW_CODENAME" != "$NEXT_CODENAME" ]; then
|
||||
log "${RED}Upgrade verification failed. Current codename is still $NEW_CODENAME${NC}"
|
||||
return 1
|
||||
fi
|
||||
log "${GREEN}Successfully upgraded to $NEXT_CODENAME (Debian $NEXT_VERSION)${NC}"
|
||||
return 0
|
||||
}
|
||||
|
||||
# Main function
|
||||
main() {
|
||||
# Check if running as root
|
||||
if [ "$(id -u)" -ne 0 ]; then
|
||||
log "${RED}This script must be run as root. Use 'sudo'.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if this is a Debian system
|
||||
if [ ! -f /etc/debian_version ]; then
|
||||
log "${RED}This script is only for Debian-based systems.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if running on Raspberry Pi
|
||||
if is_raspberry_pi; then
|
||||
log "${RED}WARNING: This is a Raspberry Pi device.${NC}"
|
||||
log "${RED}Upgrading the Debian distribution may break compatibility with Raspberry Pi OS.${NC}"
|
||||
if ! ask_confirmation "Are you sure you want to continue?" "n"; then
|
||||
log "${YELLOW}Aborting Debian distribution upgrade${NC}"
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
# Get current and next Debian versions
|
||||
get_current_version
|
||||
if ! get_next_version; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if upgrade is needed
|
||||
if [ "$CURRENT_CODENAME" == "$NEXT_CODENAME" ]; then
|
||||
log "No new Debian stable version available. Current version: $CURRENT_CODENAME"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Ask for confirmation
|
||||
if ! ask_confirmation "Do you want to upgrade from $CURRENT_CODENAME to $NEXT_CODENAME?" "n"; then
|
||||
log "${YELLOW}Skipping Debian distribution upgrade${NC}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Backup configurations
|
||||
if ! backup_configs; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Update repositories
|
||||
if ! update_repositories; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Perform upgrade
|
||||
if ! perform_upgrade; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Clean up
|
||||
cleanup
|
||||
|
||||
# Verify upgrade
|
||||
if ! verify_upgrade; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log "${YELLOW}Please reboot the system to complete the upgrade${NC}"
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Call main function
|
||||
main
|
||||
Reference in New Issue
Block a user