Skip to main content

Command Palette

Search for a command to run...

How to Automate System Updates Using a Custom Bash Script

Updated
4 min read
How to Automate System Updates Using a Custom Bash Script

This blog post introduces a Bash script designed to simplify Linux system updates across various distributions. With this script, you can:

  • Perform system updates with a single command.

  • Schedule updates using cron jobs for convenience.

  • Log every update for better tracking and troubleshooting.


Prerequisites

Before using this script, ensure you have:

  • Root/sudo access on your Linux system.

  • Basic knowledge of Linux commands.

  • Sufficient disk space for updates.

  • A stable internet connection.


The Script

#!/bin/bash

RELEASE_FILE="/etc/os-release"
LOG_DIR="/var/log/system_updates"
DATE=$(date '+%Y-%m-%d_%H-%M-%S')
LOG_FILE="$LOG_DIR/system_update_$DATE.log"
LOCK_FILE="/tmp/system_update.lock"
MAX_RETRIES=3
RETRY_DELAY=5

cleanup() {
    rm -f "$LOCK_FILE"
    log_message "------------------Script execution completed"
}

trap cleanup EXIT

log_message() {
    local message="$1"
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    echo "$timestamp - $message" | sudo tee -a "$LOG_FILE"
}

check_system_resources() {
    local min_space=1000000
    local available_space=$(df /usr -k | awk 'NR==2 {print $4}')

    if [ "$available_space" -lt "$min_space" ]; then
        log_message "!!!!! ERROR: Insufficient disk space. Required: 1GB, Available: $((available_space / 1024))MB !!!!!"
        exit 1
    fi
}

create_lock() {
    if [ -f "$LOCK_FILE" ]; then
        local pid=$(cat "$LOCK_FILE")
        if kill -0 "$pid" 2>/dev/null; then
            log_message "*****Another update process is running. Exiting"
            exit 1
        fi
    fi
    echo $$ > "$LOCK_FILE"
}

create_log_directory() {
    if [ ! -d "$LOG_DIR" ]; then
        log_message "Creating log directory..."
        if sudo mkdir -p "$LOG_DIR"; then
            sudo chmod 750 "$LOG_DIR"
            log_message "Log directory created at $LOG_DIR"
        else
            log_message "!!!! ERROR: Failed to create log directory !!!!"
            exit 1
        fi
    fi
}

check_internet() {
    local retry=0
    while [ $retry -lt $MAX_RETRIES ]; do
        if ping -c 1 8.8.8.8 >/dev/null 2>&1; then
            return 0
        fi
        retry=$((retry + 1))
        log_message "Waiting for internet connection (attempt $retry/$MAX_RETRIES)"
        sleep $RETRY_DELAY
    done
    log_message "!!!!! ERROR: No internet connection !!!!!"
    return 1
}

update_arch() {
    log_message "----------Updating Arch Linux------------"

    if ! sudo pacman -Sy --noconfirm 2>&1 | sudo tee -a "$LOG_FILE"; then
        log_message "ERROR: Failed to sync package databases"
        return 1
    fi

    if sudo pacman -Su --noconfirm 2>&1 | sudo tee -a "$LOG_FILE"; then
        log_message "--------------Arch Linux system updated successfully"
        sudo paccache -r
    else
        log_message "!!!!! ERROR: Failed to update Arch Linux system !!!!!"
        return 1
    fi
}

update_apt() {
    log_message "--------------Updating APT-based system-------------"

    export DEBIAN_FRONTEND=noninteractive

    local retry=0
    while [ $retry -lt $MAX_RETRIES ]; do
        if sudo apt-get update -y 2>&1 | sudo tee -a "$LOG_FILE" && \
           sudo apt-get upgrade -y 2>&1 | sudo tee -a "$LOG_FILE" && \
           sudo apt-get dist-upgrade -y 2>&1 | sudo tee -a "$LOG_FILE"; then
            log_message "---------------APT system updated successfully"
            sudo apt-get autoremove -y
            sudo apt-get clean
            return 0
        fi
        retry=$((retry + 1))
        log_message "Update attempt $retry failed. Retrying in $RETRY_DELAY seconds..."
        sleep $RETRY_DELAY
    done
    log_message "!!!!! ERROR: Failed to update APT system after $MAX_RETRIES attempts !!!!!"
    return 1
}

update_redhat() {
    log_message "--------------Updating RedHat-based system---------------"

    local retry=0
    while [ $retry -lt $MAX_RETRIES ]; do
        if sudo dnf update -y 2>&1 | sudo tee -a "$LOG_FILE" && \
           sudo dnf upgrade -y 2>&1 | sudo tee -a "$LOG_FILE"; then
            log_message "---------------RedHat system updated successfully"
            sudo dnf clean all
            return 0
        fi
        retry=$((retry + 1))
        log_message "Update attempt $retry failed. Retrying in $RETRY_DELAY seconds..."
        sleep $RETRY_DELAY
    done
    log_message "!!!! ERROR: Failed to update RedHat system after $MAX_RETRIES attempts !!!!"
    return 1
}

main() {
    if [ "$EUID" -ne 0 ]; then
        echo "This script must be run as root. Please use sudo." >&2
        exit 1
    fi

    create_lock
    create_log_directory

    log_message "------------------------Starting system update"

    check_system_resources

    if ! check_internet; then
        exit 1
    fi

    if grep -qi "arch" "$RELEASE_FILE"; then
        update_arch
    elif [ -d /etc/apt ]; then
        update_apt
    elif grep -qiE "redhat|fedora|centos" "$RELEASE_FILE"; then
        update_redhat
    else
        log_message "!!!! ERROR: Unsupported or unrecognized Linux distribution !!!!!"
        exit 1
    fi

    log_message "--------------------------System update process completed"
}

main

Setting Up the Script

  1. Download the script.

  2. Make it executable: chmod +x update.sh

  3. Move it to a system directory: sudo mv update.sh /usr/local/bin/update

  4. Set proper permissions: sudo chmod 755 /usr/local/bin/update


Automating the Script with Cron

To schedule daily updates, create a cron job:

  1. Open the cron editor:

     sudo crontab -e
    
  2. Add the following line:

     0 0 * * * /usr/local/bin/update
    

This schedules the script to run every day at midnight.


Managing Log Files

To prevent log file accumulation, create another cron job to delete logs older than 30 days:

0 0 * * * find /var/log/system_updates/ -type f -mtime +30 -exec rm {} \;

Conclusion

By automating your system updates with this script, you can save time and ensure your Linux system is secure and up-to-date. It’s especially useful for servers and critical systems.

Give this script a try, and let me know how it works for you! Got questions or suggestions? Feel free to reach out via email.

Don’t forget to share this with your fellow Linux enthusiasts!