Files
scripts/debian/upgrade_debian.sh
T
2026-02-15 17:42:42 +00:00

285 lines
8.0 KiB
Bash

#!/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
MAX_LOG_SIZE_KB=1024 # 1MB
# Função de Log (modificada para usar logger)
log() {
local message="$1"
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
# Escreve no ficheiro de log
echo "$timestamp: $message" | tee -a "$LOG_FILE"
# Envia para o syslog (opcional)
logger -t "debian_upgrade" "$message"
}
# Função para limitar o tamanho do log
limit_log_size() {
local log_file="$1"
local max_size_kb="$2"
local max_size_bytes=$((max_size_kb * 1024))
if [ -f "$log_file" ]; then
local current_size=$(stat -c %s "$log_file" 2>/dev/null || wc -c < "$log_file" 2>/dev/null)
if [ "$current_size" -gt "$max_size_bytes" ]; then
log "Aviso: Ficheiro de log $log_file excedeu $max_size_kb KB. A truncar..."
tail -n 500 "$log_file" > "${log_file}.tmp" && mv "${log_file}.tmp" "$log_file"
log "Ficheiro de log truncado. As últimas 500 linhas foram mantidas."
fi
fi
}
# 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
mkdir -p "$(dirname "$LOG_FILE")"
limit_log_size "$LOG_FILE" "$MAX_LOG_SIZE_KB" # Verifica o tamanho do log no início
# 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