Forkováno z ZeTian/do_anduinos_distupgrade.sh

Naposledy aktivní 2 weeks ago

Revize b860164d3bc87ce41a0ffa21047e22fc715d54ef

do_anduinos_distupgrade.sh Raw
1#!/bin/bash
2
3#=================================================
4# AnduinOS Upgrade Script
5#=================================================
6# This script upgrades AnduinOS from 1.3.7 (plucky)
7# to 1.4.1 (questing).
8#
9# Usage:
10# ./do_anduinos_distupgrade.sh
11# (Script will auto-elevate to root/sudo)
12#=================================================
13
14set -e
15set -o pipefail
16set -u
17
18# --- 1. Visual Definitions ---
19Green="\033[32m"
20Red="\033[31m"
21Yellow="\033[33m"
22Blue="\033[36m"
23Font="\033[0m"
24OK="${Green}[ OK ]${Font}"
25ERROR="${Red}[FAILED]${Font}"
26WARNING="${Yellow}[ WARN ]${Font}"
27
28# --- 2. Configuration ---
29# Use /var/backups for persistence and space safety
30BACKUP_ROOT="/var/backups/anduinos-upgrade"
31BACKUP_DIR="$BACKUP_ROOT/backup_$(date +%Y%m%d_%H%M%S)"
32PPA_BACKUP_DIR="$BACKUP_DIR/ppa"
33UBUNTU_SOURCE_BACKUP="$BACKUP_DIR/ubuntu_sources"
34
35# --- 3. Helper Functions (Logging) ---
36
37function print_ok() {
38 echo -e "${OK} ${Blue} $1 ${Font}"
39}
40
41function print_error() {
42 echo -e "${ERROR} ${Red} $1 ${Font}"
43}
44
45function print_warn() {
46 echo -e "${WARNING} ${Yellow} $1 ${Font}"
47}
48
49# --- 4. Privilege Check (Auto-Elevation) ---
50
51function ensure_root() {
52 if [ "$EUID" -ne 0 ]; then
53 print_warn "This script requires root privileges."
54 print_ok "Attempting to escalate privileges via sudo..."
55
56 if ! command -v sudo &> /dev/null; then
57 print_error "sudo is not installed. Please run this script as root."
58 exit 1
59 fi
60
61 # Re-execute the script with sudo, preserving arguments
62 exec sudo "$0" "$@"
63 exit 0
64 fi
65 # If we are here, we are root.
66}
67
68# --- 4.5 SSH & Persistence Check ---
69
70function check_ssh_safeguard() {
71 if [ -n "${SSH_CLIENT:-}" ] || [ -n "${SSH_TTY:-}" ]; then
72 # Check for screen/tmux
73 if [ -n "${STY:-}" ] || [ -n "${TMUX:-}" ] || [[ "${TERM:-}" == *"screen"* ]] || [[ "${TERM:-}" == *"tmux"* ]]; then
74 print_ok "SSH detected, but running inside persistence (screen/tmux). Safe."
75 return
76 fi
77
78 print_warn "SSH session detected WITHOUT screen/tmux!"
79 print_warn "Network disconnection could kill the critical upgrade process."
80
81 if [ -t 0 ]; then
82 read -p "Continue anyway? (y/N): " confirm
83 if [[ "$confirm" != "y" && "$confirm" != "Y" ]]; then
84 print_error "Aborted. Please use screen/tmux."
85 exit 1
86 fi
87 fi
88
89 fi
90}
91
92# --- 5. Unattended Configuration (Anti-Prompt) ---
93
94function configure_unattended() {
95 print_ok "Configuring system for unattended upgrades..."
96
97 # Install debconf-utils to pre-seed answers
98 if ! command -v debconf-set-selections &> /dev/null; then
99 print_ok "Installing debconf-utils..."
100 apt-get update && apt-get install -y debconf-utils
101 fi
102
103 # Pre-answer "Yes" to "Restart services during package upgrades without asking?"
104 # This kills the libc6/libpam dialog.
105 echo '* libraries/restart-without-asking boolean true' | debconf-set-selections
106
107 # Configure environment variables for the session
108 # NEEDRESTART_MODE=a : Automatically restart services (fixes purple screen prompt)
109 export NEEDRESTART_MODE=a
110 export DEBIAN_FRONTEND=noninteractive
111
112 judge "Configure unattended mode"
113}
114
115# --- 6. Core Logic with Detailed Rollback ---
116
117function rollback_on_error() {
118 print_error "An error occurred during the upgrade process"
119 print_warn "Starting rollback procedure..."
120
121 # Restore ubuntu.sources if backup exists
122 if [ -f "$UBUNTU_SOURCE_BACKUP/ubuntu.sources" ]; then
123 print_ok "Restoring ubuntu.sources..."
124 cp "$UBUNTU_SOURCE_BACKUP/ubuntu.sources" /etc/apt/sources.list.d/
125 print_ok "Restored ubuntu.sources"
126 fi
127
128 # Restore sources.list if backup exists
129 if [ -f "$UBUNTU_SOURCE_BACKUP/sources.list" ]; then
130 print_ok "Restoring sources.list..."
131 cp "$UBUNTU_SOURCE_BACKUP/sources.list" /etc/apt/
132 print_ok "Restored sources.list"
133 fi
134
135 # Restore PPA sources (Detailed Loop from Old Script)
136 if [ -d "$PPA_BACKUP_DIR" ]; then
137 ppa_count=$(ls -1 "$PPA_BACKUP_DIR" 2>/dev/null | wc -l)
138
139 if [ "$ppa_count" -gt 0 ]; then
140 print_ok "Restoring PPA sources..."
141 for file in "$PPA_BACKUP_DIR"/*; do
142 if [ -f "$file" ]; then
143 cp "$file" /etc/apt/sources.list.d/
144 print_ok "Restored $(basename "$file")"
145 fi
146 done
147 fi
148 fi
149
150 # Remove temporary apt configuration if exists
151 if [ -f "/etc/apt/apt.conf.d/99-local-versions" ]; then
152 rm -f /etc/apt/apt.conf.d/99-local-versions
153 print_ok "Removed temporary apt configuration"
154 fi
155
156 # Run apt update to restore repository state
157 print_ok "Running apt update to restore repository state..."
158 apt update || true
159
160 print_warn "Rollback completed"
161 print_warn "Your system has been restored to the previous state"
162 print_warn "Backup files are preserved in: $BACKUP_DIR"
163 print_error "Please check the error messages above and try again"
164
165 exit 1
166}
167
168function judge() {
169 if [[ 0 -eq $? ]]; then
170 print_ok "$1 succeeded"
171 sleep 0.2
172 else
173 print_error "$1 failed"
174 rollback_on_error
175 fi
176}
177
178function check_disk_space() {
179 print_ok "Checking available disk space..."
180
181 # Ensure backup directory exists
182 mkdir -p "$BACKUP_DIR"
183
184 # Get available space in / (in KB)
185 local root_space=$(df / | awk 'NR==2 {print $4}')
186 # Convert to MB
187 local root_space_mb=$((root_space / 1024))
188 # Required space: 2GB
189 local required_space=2048
190
191 print_ok "Available space in /: ${root_space_mb}MB"
192 print_ok "Backup location: $BACKUP_DIR"
193
194 if [ "$root_space_mb" -lt "$required_space" ]; then
195 print_error "Insufficient disk space in /. Required: ${required_space}MB, Available: ${root_space_mb}MB"
196 exit 1
197 fi
198
199 print_ok "Disk space check passed"
200}
201
202function update_system() {
203 print_ok "Ensuring current system (1.3 / Ubuntu 25.04) is fully updated..."
204
205 print_ok "Running apt update..."
206 apt update
207 judge "apt update"
208
209 print_ok "Installing any missing updates for the current version..."
210 # Use non-interactive flags to ensure current 1.3 packages are up-to-date
211 DEBIAN_FRONTEND=noninteractive NEEDRESTART_MODE=a apt upgrade -y
212 judge "apt upgrade"
213}
214
215function backup_ubuntu_sources() {
216 print_ok "Backing up Ubuntu official sources..."
217
218 mkdir -p "$UBUNTU_SOURCE_BACKUP"
219
220 # Backup ubuntu.sources if exists
221 if [ -f "/etc/apt/sources.list.d/ubuntu.sources" ]; then
222 cp /etc/apt/sources.list.d/ubuntu.sources "$UBUNTU_SOURCE_BACKUP/"
223 print_ok "Backed up ubuntu.sources"
224 fi
225
226 # Backup sources.list if it exists and is not empty
227 if [ -f "/etc/apt/sources.list" ] && [ -s "/etc/apt/sources.list" ]; then
228 cp /etc/apt/sources.list "$UBUNTU_SOURCE_BACKUP/"
229 print_ok "Backed up sources.list"
230 fi
231
232 judge "Backup Ubuntu sources"
233}
234
235function backup_and_remove_ppa() {
236 print_ok "Backing up and temporarily removing PPA sources..."
237
238 mkdir -p "$PPA_BACKUP_DIR"
239
240 # Move all files in /etc/apt/sources.list.d/ except ubuntu.sources
241 if [ -d "/etc/apt/sources.list.d" ]; then
242 for file in /etc/apt/sources.list.d/*; do
243 if [ -f "$file" ] && [ "$(basename "$file")" != "ubuntu.sources" ]; then
244 mv "$file" "$PPA_BACKUP_DIR/"
245 print_ok "Moved $(basename "$file") to backup"
246 fi
247 done
248 fi
249
250 print_ok "PPA sources moved to: $PPA_BACKUP_DIR"
251 judge "Backup and remove PPA sources"
252}
253
254function check_apt_source_format() {
255 local old_format=false
256 local new_format=false
257
258 # Check old format (.list)
259 if [ -f "/etc/apt/sources.list" ]; then
260 if grep -v '^#' /etc/apt/sources.list | grep -q '[^[:space:]]'; then
261 old_format=true
262 fi
263 fi
264
265 # Check for ubuntu.sources file in new format
266 if [ -f "/etc/apt/sources.list.d/ubuntu.sources" ]; then
267 if grep -v '^#' /etc/apt/sources.list.d/ubuntu.sources | grep -q '[^[:space:]]'; then
268 new_format=true
269 fi
270 fi
271
272 # Return status
273 if $old_format && $new_format; then
274 echo "both"
275 elif $old_format; then
276 echo "old"
277 elif $new_format; then
278 echo "new"
279 else
280 echo "none"
281 fi
282}
283
284function find_fastest_mirror() {
285 # Redirect all output to stderr
286 echo "Testing mirror speeds..." >&2
287
288 # Enable required packages
289 apt install -y curl lsb-release >&2
290
291 # Get current Ubuntu codename
292 codename=$(lsb_release -cs)
293
294 # Define list of potential mirrors
295 mirrors=(
296 "https://archive.ubuntu.com/ubuntu/"
297 "https://mirror.aarnet.edu.au/pub/ubuntu/archive/" # Australia
298 "https://mirror.fsmg.org.nz/ubuntu/" # New Zealand
299 "https://mirrors.neterra.net/ubuntu/archive/" # Bulgaria
300 "https://mirror.csclub.uwaterloo.ca/ubuntu/" # Canada
301 "https://mirrors.dotsrc.org/ubuntu/" # Denmark
302 "https://mirrors.nic.funet.fi/ubuntu/" # Finland
303 "https://mirror.ubuntu.ikoula.com/" # France
304 "https://mirror.xtom.com.hk/ubuntu/" # Hong Kong
305 "https://mirrors.piconets.webwerks.in/ubuntu-mirror/ubuntu/" # India
306 "https://ftp.udx.icscoe.jp/Linux/ubuntu/" # Japan
307 "https://ftp.kaist.ac.kr/ubuntu/" # Korea
308 "https://ubuntu.mirror.garr.it/ubuntu/" # Italy
309 "https://ftp.uni-stuttgart.de/ubuntu/" # Germany
310 "https://mirror.i3d.net/pub/ubuntu/" # Netherlands
311 "https://mirroronet.pl/pub/mirrors/ubuntu/" # Poland
312 "https://ubuntu.mobinhost.com/ubuntu/" # Iran
313 "http://sg.archive.ubuntu.com/ubuntu/" # Singapore
314 "http://ossmirror.mycloud.services/os/linux/ubuntu/" # Singapore
315 "https://mirror.enzu.com/ubuntu/" # United States
316 "http://jp.archive.ubuntu.com/ubuntu/" # Japan
317 "http://kr.archive.ubuntu.com/ubuntu/" # Korea
318 "http://us.archive.ubuntu.com/ubuntu/" # United States
319 "http://tw.archive.ubuntu.com/ubuntu/" # Taiwan
320 "https://mirror.twds.com.tw/ubuntu/" # Taiwan
321 "https://ubuntu.mirrors.uk2.net/ubuntu/" # United Kingdom
322 "http://mirrors.ustc.edu.cn/ubuntu/" # USTC
323 "http://ftp.sjtu.edu.cn/ubuntu/" # SJTU
324 "http://mirrors.tuna.tsinghua.edu.cn/ubuntu/" # Tsinghua
325 "http://mirrors.aliyun.com/ubuntu/" # Aliyun
326 "http://mirrors.163.com/ubuntu/" # NetEase
327 "http://mirrors.cloud.tencent.com/ubuntu/" # Tencent Cloud
328 "http://mirrors.huaweicloud.com/ubuntu/" # Huawei Cloud
329 "http://mirrors.zju.edu.cn/ubuntu/" # Zhejiang University
330 "http://azure.archive.ubuntu.com/ubuntu/" # Azure
331 "https://mirrors.isu.net.sa/apt-mirror/" # Saudi Arabia
332 "https://mirror.team-host.ru/ubuntu/" # Russia
333 "https://labs.eif.urjc.es/mirror/ubuntu/" # Spain
334 "https://mirror.alastyr.com/ubuntu/ubuntu-archive/" # Turkey
335 "https://ftp.acc.umu.se/ubuntu/" # Sweden
336 "https://mirror.kku.ac.th/ubuntu/" # Thailand
337 "https://mirror.bizflycloud.vn/ubuntu/" # Vietnam
338 )
339
340 declare -A results
341
342 # Test speed of each mirror
343 for mirror in "${mirrors[@]}"; do
344 echo "Testing $mirror ..." >&2
345 response="$(curl -o /dev/null -s -w "%{http_code} %{time_total}\n" \
346 --connect-timeout 1 --max-time 3 "${mirror}dists/${codename}/Release")"
347
348 http_code=$(echo "$response" | awk '{print $1}')
349 time_total=$(echo "$response" | awk '{print $2}')
350
351 if [ "$http_code" -eq 200 ]; then
352 results["$mirror"]="$time_total"
353 echo " Success: $time_total seconds" >&2
354 else
355 echo " Failed: HTTP code $http_code" >&2
356 results["$mirror"]="9999"
357 fi
358 done
359
360 # Sort mirrors by response time
361 sorted_mirrors="$(
362 for url in "${!results[@]}"; do
363 echo "$url ${results[$url]}"
364 done | sort -k2 -n
365 )"
366
367 echo >&2
368 echo "=== Mirrors sorted by response time (ascending) ===" >&2
369 echo "$sorted_mirrors" >&2
370 echo >&2
371
372 # Choose the fastest mirror
373 fastest_mirror="$(echo "$sorted_mirrors" | head -n 1 | awk '{print $1}')"
374
375 if [[ "$fastest_mirror" == "" || "${results[$fastest_mirror]}" == "9999" ]]; then
376 echo "No usable mirror found, using default mirror" >&2
377 fastest_mirror="http://archive.ubuntu.com/ubuntu/"
378 fi
379
380 echo "Fastest mirror found: $fastest_mirror" >&2
381
382 # Only this line will be returned to caller
383 echo "$fastest_mirror"
384}
385
386function generate_new_format() {
387 local mirror="$1"
388 local codename="$2"
389
390 print_ok "Generating new format source list /etc/apt/sources.list.d/ubuntu.sources"
391
392 cat > /etc/apt/sources.list.d/ubuntu.sources <<EOF
393Types: deb
394URIs: $mirror
395Suites: $codename
396Components: main restricted universe multiverse
397Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg
398
399Types: deb
400URIs: $mirror
401Suites: $codename-updates
402Components: main restricted universe multiverse
403Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg
404
405Types: deb
406URIs: $mirror
407Suites: $codename-backports
408Components: main restricted universe multiverse
409Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg
410
411Types: deb
412URIs: $mirror
413Suites: $codename-security
414Components: main restricted universe multiverse
415Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg
416EOF
417
418 print_ok "New format source list updated"
419}
420
421function optimize_apt_sources() {
422 print_ok "Optimizing APT sources..."
423
424 # Install required packages if missing
425 if ! command -v curl &> /dev/null || ! command -v lsb_release &> /dev/null; then
426 print_ok "Installing curl and lsb-release..."
427 apt update && apt install -y curl lsb-release
428 fi
429
430 local format=$(check_apt_source_format)
431 print_ok "Current APT source format status: $format"
432
433 local codename=$(lsb_release -cs)
434 print_ok "Ubuntu codename: $codename"
435
436 if [ "$format" == "new" ]; then
437 print_ok "Already in new format. Skipping mirror re-check to preserve user settings."
438 return
439 fi
440
441 print_ok "Searching for the fastest mirror..."
442 # Capture output, separating stdout (result) from stderr (logs)
443 # But find_fastest_mirror already handles >&2 for logs
444 local fastest_mirror
445 fastest_mirror=$(find_fastest_mirror)
446 print_ok "Fastest mirror selected: $fastest_mirror"
447
448 case "$format" in
449 "none" | "old")
450 print_ok "Converting to modern format..."
451 generate_new_format "$fastest_mirror" "$codename"
452
453 if [ -f "/etc/apt/sources.list" ]; then
454 mv /etc/apt/sources.list /etc/apt/sources.list.bak
455 print_ok "Old sources.list backed up"
456 fi
457 ;;
458 "both")
459 print_ok "Consolidating formats..."
460 mv /etc/apt/sources.list /etc/apt/sources.list.bak
461 print_ok "Old format source list backed up to /etc/apt/sources.list.bak"
462 generate_new_format "$fastest_mirror" "$codename"
463 ;;
464 esac
465
466 judge "Optimize APT sources"
467}
468
469function replace_plucky_with_questing() {
470 print_ok "Replacing plucky with questing in ubuntu.sources..."
471
472 if [ ! -f "/etc/apt/sources.list.d/ubuntu.sources" ]; then
473 print_error "/etc/apt/sources.list.d/ubuntu.sources not found"
474 rollback_on_error
475 fi
476
477 sed -i 's/plucky/questing/g' /etc/apt/sources.list.d/ubuntu.sources
478 judge "Replace plucky with questing"
479
480 print_ok "Running apt update with questing repositories..."
481 apt update
482 judge "apt update with questing"
483}
484
485function install_coreutils_uutils() {
486 print_ok "Installing coreutils-from-uutils..."
487
488 DEBIAN_FRONTEND=noninteractive apt install -y coreutils-from-uutils
489 judge "Install coreutils-from-uutils"
490}
491
492function run_dist_upgrade() {
493 print_ok "Simulating apt dist-upgrade first..."
494 apt -s dist-upgrade > /dev/null
495 judge "apt -s dist-upgrade"
496
497 print_ok "Running apt dist-upgrade in non-interactive mode..."
498
499 # Configure dpkg to keep local versions by default
500 bash -c 'cat > /etc/apt/apt.conf.d/99-local-versions <<EOF
501Dpkg::Options {
502 "--force-confdef";
503 "--force-confold";
504}
505EOF'
506
507 # Run dist-upgrade
508 # Combine variables: DEBIAN_FRONTEND, NEEDRESTART_MODE, APT_LISTCHANGES
509 bash -c 'DEBIAN_FRONTEND=noninteractive NEEDRESTART_MODE=a APT_LISTCHANGES_FRONTEND=none \
510 apt-get -y dist-upgrade \
511 -o Dpkg::Options::="--force-confdef" \
512 -o Dpkg::Options::="--force-confold"'
513
514 judge "apt dist-upgrade"
515
516 # Remove temporary configuration
517 rm -f /etc/apt/apt.conf.d/99-local-versions
518}
519
520function update_release_files() {
521 print_ok "Updating release information files to 1.4.1..."
522
523 # Update /etc/os-release
524 if [ -f "/etc/os-release" ]; then
525 print_ok "Updating /etc/os-release..."
526 bash -c "cat > /etc/os-release" <<EOF
527PRETTY_NAME="AnduinOS 1.4.1"
528NAME="AnduinOS"
529VERSION_ID="1.4.1"
530VERSION="1.4.1 (questing)"
531VERSION_CODENAME=questing
532ID=ubuntu
533ID_LIKE=debian
534HOME_URL="https://www.anduinos.com/"
535SUPPORT_URL="https://github.com/Anduin2017/AnduinOS/discussions"
536BUG_REPORT_URL="https://github.com/Anduin2017/AnduinOS/issues"
537PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
538UBUNTU_CODENAME=questing
539EOF
540
541 judge "Update /etc/os-release"
542 fi
543
544 # Update /etc/lsb-release
545 if [ -f "/etc/lsb-release" ]; then
546 print_ok "Updating /etc/lsb-release..."
547
548 bash -c "cat > /etc/lsb-release" <<EOF
549DISTRIB_ID=AnduinOS
550DISTRIB_RELEASE=1.4.1
551DISTRIB_CODENAME=questing
552DISTRIB_DESCRIPTION="AnduinOS 1.4.1"
553EOF
554
555 judge "Update /etc/lsb-release"
556 fi
557
558 print_ok "Release files updated successfully"
559}
560
561function restore_and_upgrade_ppa_sources() {
562 print_ok "Restoring and upgrading PPA sources..."
563
564 if [ -d "$PPA_BACKUP_DIR" ]; then
565 ppa_count=$(ls -1 "$PPA_BACKUP_DIR" 2>/dev/null | wc -l)
566
567 if [ "$ppa_count" -gt 0 ]; then
568 # Restore files first
569 for file in "$PPA_BACKUP_DIR"/*; do
570 if [ -f "$file" ]; then
571 mv "$file" /etc/apt/sources.list.d/
572 print_ok "Restored $(basename "$file")"
573 fi
574 done
575
576 # Check and upgrade PPA configurations
577 print_ok "Checking restored PPAs for version 'plucky'..."
578 local upgraded_count=0
579
580 # Iterate over all files in sources.list.d to be safe
581 for file in /etc/apt/sources.list.d/*; do
582 if [ -f "$file" ]; then
583 # Skip ubuntu.sources to avoid messing with core repos
584 if [ "$(basename "$file")" == "ubuntu.sources" ]; then
585 continue
586 fi
587
588 # Check if file contains "plucky"
589 if grep -q "plucky" "$file"; then
590 local ppa_name=$(basename "$file")
591
592 # Extract URL (First valid HTTP/HTTPS URL)
593 local url=$(grep -oE 'https?://[^ ]+' "$file" | head -n1)
594 local can_upgrade=false
595
596 if [ -n "$url" ]; then
597 # Remove trailing slash
598 url="${url%/}"
599
600 # Check availability (Release or InRelease)
601 # We use a silent check with timeout to verify if the new questing dist exists
602 if curl -s -I -f -L --max-time 3 "$url/dists/questing/Release" &>/dev/null || \
603 curl -s -I -f -L --max-time 3 "$url/dists/questing/InRelease" &>/dev/null; then
604 can_upgrade=true
605 fi
606 fi
607
608 if $can_upgrade; then
609 sed -i 's/plucky/questing/g' "$file"
610 print_ok "Upgraded PPA $ppa_name to questing"
611 ((upgraded_count++))
612 else
613 print_warn "PPA $ppa_name does not support 'questing' yet (Connection failed or 404)."
614 print_warn "Disabling $ppa_name to ensure clean upgrade."
615 mv "$file" "${file}.save"
616 fi
617 fi
618 fi
619 done
620
621 if [ "$upgraded_count" -eq 0 ]; then
622 print_ok "No PPA files needed version upgrading."
623 fi
624 print_ok "Running apt update with restored PPAs..."
625 apt update
626 judge "Restore and upgrade PPA sources"
627 else
628 print_ok "No PPA sources to restore"
629 fi
630 else
631 print_warn "PPA backup directory not found, skipping restore"
632 fi
633}
634
635function cleanup_system() {
636 print_ok "Cleaning up system..."
637 print_ok "Removing unused packages (orphans)..."
638 if apt autoremove -y; then
639 print_ok "apt autoremove succeeded"
640 else
641 print_warn "apt autoremove failed, but upgrade was successful."
642 fi
643
644 print_ok "Cleaning apt cache..."
645 if apt clean; then
646 print_ok "apt clean succeeded"
647 else
648 print_warn "apt clean failed, but upgrade was successful."
649 fi
650}
651
652function main() {
653 # 1. Ensure we are root first
654 ensure_root
655
656 # --- Enable Logging ---
657 LOG_FILE="/var/log/anduinos-upgrade.log"
658 # Create a fresh log section
659 echo "--- Upgrade Session Started at $(date) ---" >> "$LOG_FILE"
660
661 # Redirect stdout and stderr to tee, appending to the log file
662 exec > >(tee -a "$LOG_FILE") 2>&1
663
664 print_ok "Output is being logged to: $LOG_FILE"
665
666 print_ok "Starting AnduinOS upgrade process..."
667
668 echo -e "${Yellow}WARNING: This script will upgrade your system from 1.3.7 (plucky) to 1.4.1 (questing).${Font}"
669 echo -e "${Yellow}Please ensure you have backed up important data before proceeding.${Font}"
670
671 # Interactive check only if we have a terminal (TTY)
672 if [ -t 0 ]; then
673 read -p "Do you want to continue? (y/N): " confirm
674 if [[ "$confirm" != "y" && "$confirm" != "Y" ]]; then
675 print_error "Upgrade process aborted by user."
676 exit 1
677 fi
678 fi
679
680 # Step 0: Check Safeguards
681 check_ssh_safeguard
682
683 # Step 1: Configure Unattended (Anti-Prompt)
684 configure_unattended
685
686 # Step 1: Check disk space
687 check_disk_space
688
689 # Step 2: Update current system
690 update_system
691
692 # Step 3: Backup Ubuntu official sources
693 backup_ubuntu_sources
694
695 # Step 4: Backup and remove PPA sources
696 backup_and_remove_ppa
697
698 # Step 5: Detect and convert APT format
699 optimize_apt_sources
700
701 # Step 6: Replace plucky with questing
702 replace_plucky_with_questing
703
704 # Step 7: Install coreutils-from-uutils
705 install_coreutils_uutils
706
707 # Step 8: Run dist-upgrade
708 run_dist_upgrade
709
710 # Step 9: Update release files (to 1.4.1)
711 update_release_files
712
713 # Step 10: Restore and upgrade PPA sources
714 restore_and_upgrade_ppa_sources
715
716 # Step 11: Cleanup system
717 cleanup_system
718
719 print_ok "Upgrade completed successfully!"
720 print_ok "Your system has been upgraded to AnduinOS 1.4.1 (questing)"
721 print_ok "Backup files are stored in: $BACKUP_DIR"
722 print_warn "Please reboot your system to complete the upgrade."
723
724 if [ -t 0 ]; then
725 read -p "Do you want to reboot now? (y/N): " reboot_confirm
726 if [[ "$reboot_confirm" == "y" || "$reboot_confirm" == "Y" ]]; then
727 print_ok "Rebooting system..."
728 reboot
729 fi
730 fi
731}
732
733main