Cross-Platform System Update Script for Linux: Update and Clean Any Linux Distribution Easily

In this post, we’ll explore one of the scripts that I use in my basic system configuration toolkit. This script streamlines the process of updating and cleaning up various Linux distributions, allowing me to maintain multiple systems efficiently.

Cross-Platform System Update Script for Linux: Update and Clean Any Linux Distribution Easily

Keeping your Linux system up-to-date is crucial for stability, security, and performance. Yet, Linux distributions vary in how they handle updates, cache management, and automatic upgrade services.

In this post, we’ll explore one of the scripts that I use in my basic system configuration toolkit. This script streamlines the process of updating and cleaning up various Linux distributions, allowing me to maintain multiple systems efficiently. Each script in this series is designed to handle a key area of system setup, so stay tuned as I continue sharing these solutions, tailored for seamless cross-platform functionality.

Certainly! Here’s a revised blog post explaining the latest version of the update.sh script. This post outlines how the script performs system updates, upgrades, and cleanups, as well as how it disables automatic updates on multiple distributions.

Overview of the update.sh Script

This script is designed to:

  • Disable automatic updates to prevent potential interruptions, regardless of the distribution.
  • Update the list of repositories and upgrade packages.
  • Clean up package caches and unused dependencies, ensuring that the system runs smoothly with minimal bloat.

Supported distributions include:

  • Ubuntu/Debian
  • Fedora/CentOS/RHEL
  • OpenSUSE
  • Arch Linux

This cross-platform flexibility makes it an ideal tool for anyone managing different systems across a network.

#!/bin/bash -eu

# update.sh       - Update package lists and upgrade the server to the latest versions.

# Function to get the distribution type
get_distro() {
    if [[ -f /etc/os-release ]]; then
        . /etc/os-release
        echo "$ID"
    else
        echo "unknown"
    fi
}

# Disable automatic updates for each distribution
disable_auto_updates() {
    case "$DISTRO" in
        ubuntu|debian)
            echo "==> Disabling apt-daily services on Debian/Ubuntu"
            systemctl stop apt-daily.timer apt-daily-upgrade.timer
            systemctl disable apt-daily.timer apt-daily-upgrade.timer
            systemctl mask apt-daily.timer apt-daily-upgrade.timer
            systemctl stop apt-daily.service apt-daily-upgrade.service
            systemctl disable apt-daily.service apt-daily-upgrade.service
            systemctl mask apt-daily.service apt-daily-upgrade.service
            systemctl daemon-reload
            ;;
        fedora|centos|rhel)
            echo "==> Disabling dnf-automatic service on Fedora/CentOS/RHEL"
            systemctl stop dnf-automatic.timer
            systemctl disable dnf-automatic.timer
            # Update /etc/dnf/automatic.conf to disable auto-updates
            if [[ -f /etc/dnf/automatic.conf ]]; then
                sudo sed -i 's/^apply_updates = .*/apply_updates = no/' /etc/dnf/automatic.conf
                echo "==> Updated apply_updates to 'no' in /etc/dnf/automatic.conf"
            fi
            ;;
        arch)
            echo "==> Arch Linux typically does not have automatic updates enabled by default"
            # Optional: disable pamac update timers if used
            systemctl disable pamac-mirrorlist.timer pamac-cleancache.timer pamac-update.timer 2>/dev/null
            ;;
        opensuse*|suse)
            echo "==> Disabling packagekit service on OpenSUSE"
            systemctl stop packagekit.service
            systemctl disable packagekit.service
            # Update /etc/zypp/zypp.conf to disable auto-updates
            if [[ -f /etc/zypp/zypp.conf ]]; then
                sudo sed -i 's/^do_auto_updates = .*/do_auto_updates = false/' /etc/zypp/zypp.conf
                echo "==> Updated do_auto_updates to 'false' in /etc/zypp/zypp.conf"
            fi
            ;;
        *)
            echo "Automatic update disabling is not supported for $DISTRO"
            ;;
    esac
}

# Function to update and upgrade packages based on distribution
update_and_upgrade() {
    case "$DISTRO" in
        ubuntu|debian)
            echo "==> Updating and upgrading on Debian/Ubuntu"
            apt-get update
            if [[ $UPDATE =~ true || $UPDATE =~ 1 ]]; then
                apt-get -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" dist-upgrade
            fi
            apt-get -y autoremove --purge
            apt-get clean
            ;;
        fedora|centos|rhel)
            echo "==> Updating and upgrading on Fedora/CentOS/RHEL"
            dnf makecache
            if [[ $UPDATE =~ true || $UPDATE =~ 1 ]]; then
                dnf -y upgrade
            fi
            dnf -y autoremove
            dnf clean all
            ;;
        arch)
            echo "==> Updating and upgrading on Arch Linux"
            pacman -Sy
            if [[ $UPDATE =~ true || $UPDATE =~ 1 ]]; then
                pacman -Syu --noconfirm
            fi
            pacman -Sc --noconfirm
            ;;
        opensuse*|suse)
            echo "==> Updating and upgrading on OpenSUSE"
            zypper refresh
            if [[ $UPDATE =~ true || $UPDATE =~ 1 ]]; then
                zypper update -y
            fi
            zypper clean --all
            ;;
        *)
            echo "Unsupported distribution: $DISTRO"
            exit 1
            ;;
    esac
}

# Main script execution
DISTRO=$(get_distro)
disable_auto_updates
update_and_upgrade

echo "System update and cleanup completed on $DISTRO."

Code Breakdown

Let’s dive into each section of the code and explain how it accomplishes the task across different distributions.

Detecting the Linux Distribution

To handle different package managers and settings across Linux distributions, the get_distro function checks the os-release file to identify the specific distribution.

get_distro() {
    if [[ -f /etc/os-release ]]; then
        . /etc/os-release
        echo "$ID"
    else
        echo "unknown"
    fi
}

Disabling Automatic Updates

Automatic updates can be a problem, especially on servers where you need control over when packages are upgraded. Here’s how the disable_auto_updates function tackles this for each supported distribution:

  1. Ubuntu/Debian: Stops and disables apt-daily services that trigger automatic updates.
  2. Fedora/CentOS/RHEL: Disables dnf-automatic by stopping its timer and setting apply_updates = no in /etc/dnf/automatic.conf.
  3. OpenSUSE: Disables the packagekit service and updates do_auto_updates = false in /etc/zypp/zypp.conf.
  4. Arch Linux: Arch doesn’t enable automatic updates by default, but for completeness, we also check for pamac update timers and disable them if present.
disable_auto_updates() {
    case "$DISTRO" in
        ubuntu|debian)
            echo "==> Disabling apt-daily services on Debian/Ubuntu"
            systemctl stop apt-daily.timer apt-daily-upgrade.timer
            systemctl disable apt-daily.timer apt-daily-upgrade.timer
            systemctl mask apt-daily.timer apt-daily-upgrade.timer
            systemctl stop apt-daily.service apt-daily-upgrade.service
            systemctl disable apt-daily.service apt-daily-upgrade.service
            systemctl mask apt-daily.service apt-daily-upgrade.service
            systemctl daemon-reload
            ;;
        fedora|centos|rhel)
            echo "==> Disabling dnf-automatic service on Fedora/CentOS/RHEL"
            systemctl stop dnf-automatic.timer
            systemctl disable dnf-automatic.timer
            # Update /etc/dnf/automatic.conf to disable auto-updates
            if [[ -f /etc/dnf/automatic.conf ]]; then
                sudo sed -i 's/^apply_updates = .*/apply_updates = no/' /etc/dnf/automatic.conf
                echo "==> Updated apply_updates to 'no' in /etc/dnf/automatic.conf"
            fi
            ;;
        arch)
            echo "==> Arch Linux typically does not have automatic updates enabled by default"
            systemctl disable pamac-mirrorlist.timer pamac-cleancache.timer pamac-update.timer 2>/dev/null
            ;;
        opensuse*|suse)
            echo "==> Disabling packagekit service on OpenSUSE"
            systemctl stop packagekit.service
            systemctl disable packagekit.service
            # Update /etc/zypp/zypp.conf to disable auto-updates
            if [[ -f /etc/zypp/zypp.conf ]]; then
                sudo sed -i 's/^do_auto_updates = .*/do_auto_updates = false/' /etc/zypp/zypp.conf
                echo "==> Updated do_auto_updates to 'false' in /etc/zypp/zypp.conf"
            fi
            ;;
        *)
            echo "Automatic update disabling is not supported for $DISTRO"
            ;;
    esac
}

This function executes the appropriate commands and configuration updates based on the detected distribution.

Performing Updates and Cleanup

Next, the update_and_upgrade function handles the package manager commands for updating and upgrading software on each supported system:

  • Ubuntu/Debian: Uses apt-get for updating, upgrading, and cleaning up the package cache.
  • Fedora/CentOS/RHEL: Uses dnf for the same tasks.
  • Arch Linux: Utilizes pacman for package updates and cleanup.
  • OpenSUSE: Uses zypper to refresh repositories, update packages, and clean cache.
update_and_upgrade() {
    case "$DISTRO" in
        ubuntu|debian)
            echo "==> Updating and upgrading on Debian/Ubuntu"
            apt-get update
            if [[ $UPDATE =~ true || $UPDATE =~ 1 ]]; then
                apt-get -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" dist-upgrade
            fi
            apt-get -y autoremove --purge
            apt-get clean
            ;;
        fedora|centos|rhel)
            echo "==> Updating and upgrading on Fedora/CentOS/RHEL"
            dnf makecache
            if [[ $UPDATE =~ true || $UPDATE =~ 1 ]]; then
                dnf -y upgrade
            fi
            dnf -y autoremove
            dnf clean all
            ;;
        arch)
            echo "==> Updating and upgrading on Arch Linux"
            pacman -Sy
            if [[ $UPDATE =~ true || $UPDATE =~ 1 ]]; then
                pacman -Syu --noconfirm
            fi
            pacman -Sc --noconfirm
            ;;
        opensuse*|suse)
            echo "==> Updating and upgrading on OpenSUSE"
            zypper refresh
            if [[ $UPDATE =~ true || $UPDATE =~ 1 ]]; then
                zypper update -y
            fi
            zypper clean --all
            ;;
        *)
            echo "Unsupported distribution: $DISTRO"
            exit 1
            ;;
    esac
}

Running the Script

This script automatically detects the Linux distribution and applies the necessary steps. To use the script:

For a full upgrade, set the UPDATE environment variable before running:

UPDATE=true sudo ./update.sh

Run the script with sudo:

sudo ./update.sh

Save it as update.sh and make it executable:

chmod +x update.sh

Final Thoughts

This script is designed to manage updates across multiple Linux distributions, making it easier to maintain consistency and control across systems. With its cross-platform compatibility, it ensures that no matter the server or system, your updates are handled efficiently and without unwanted automatic interruptions.

Read next

Automating GRUB Configuration Across Linux Distributions

In this post, we’re going to explore the grub.sh script, which is designed to handle the configuration and hardening of GRUB across various Linux distributions. We’ll go over each line of the script to understand what it does and how it contributes to the overall configuration.