My update script, if anyone would like to copy and use it for themselves

Freepoorman

Active Member
Joined
Mar 8, 2024
Messages
263
Reaction score
164
Credits
2,248
Bash:
#!/bin/bash

# Function to handle errors
handle_error() {
    echo "An error occurred: $1"
    read -p "Press Enter to exit."
    exit 1
}

# Trap errors
trap 'handle_error "$BASH_COMMAND"' ERR

# Logging directory
LOG_DIR="/home/erik/Documents/Update_logs"

# Ensure the log directory exists
mkdir -p "$LOG_DIR"

# Rotate logs to keep a maximum of 5 logs
rotate_logs() {
    local log_dir=$1
    local max_logs=5

    # Find and remove older log files
    find "$log_dir" -name "*.log" -type f -mtime +$max_logs -exec rm -f {} \;
}

# Rotate logs before creating a new one
rotate_logs "$LOG_DIR"

# Logging
LOG_FILE="$LOG_DIR/system_update_$(date +%Y%m%d%H%M%S).log"
exec &> >(tee -a "$LOG_FILE")

# Extend sudo timeout
sudo -v

echo -e "Reloading system manager configuration before performing full system update and cleanup..."
sudo systemctl daemon-reload

echo -e "\nUpdating package lists..."
sudo apt-get update || handle_error "Failed to update package lists"

echo -e "\nUpgrading all installed packages..."
sudo apt-get dist-upgrade -y || handle_error "Failed to upgrade packages"

echo -e "\nInstalling security updates not included in the regular upgrade..."
SECURITY_UPDATES=$(apt-get -s upgrade | awk '/^Inst/ { if ($4 !~ /^(.*-security|security)$/) next; print $2 }')
echo "Security updates to be installed: $SECURITY_UPDATES"

if [ -n "$SECURITY_UPDATES" ]; then
    sudo apt-get install --only-upgrade $SECURITY_UPDATES -y || handle_error "Failed to install security updates"
else
    echo "No security updates found."
fi

echo -e "\nInstalling recommended drivers..."
sudo ubuntu-drivers autoinstall || handle_error "Failed to install recommended drivers"

echo -e "\nRemoving unnecessary packages..."
sudo apt-get autoremove -y || handle_error "Failed to remove unnecessary packages"

echo -e "\nCleaning up package cache..."
sudo apt-get clean || handle_error "Failed to clean package cache"

echo -e "\nPurging unnecessary packages and their configuration files..."
sudo apt-get autoremove --purge -y || handle_error "Failed to purge unnecessary packages"

echo -e "\nCleaning up journal logs..."
sudo journalctl --vacuum-time=2d || handle_error "Failed to clean journal logs"

echo -e "\nUpdating Snap packages..."
sudo snap refresh || handle_error "Failed to update Snap packages"

echo -e "\nUpdating Flatpak packages..."
flatpak update -y || handle_error "Failed to update Flatpak packages"

echo -e "\nClearing the Linux cache..."
sudo sh -c 'echo 1 > /proc/sys/vm/drop_caches' || handle_error "Failed to clear Linux cache"

echo -e "\nSystem update and cleanup completed."

# Prompt for reboot or exit
read -p "Press [Enter] to reboot or [Esc] to exit the terminal..." -s -n 1 key
if [[ $key = $'\e' ]]; then
    echo "Exiting the terminal..."
else
    echo "Rebooting the system..."
    sudo reboot
fi

Feel free to make suggestions and criticisms. I'd appreciate it very much
 


You should remove sudo statements from the script, the script itself must be run with sudo anyway.
You might also want to run checkbashisms on your script and convert it to POSIX compatible script.
Thank you. I'll get working on it... I never get tired of improving my system however I can. Appreciate the feedback
 
Some observations:

The script is really more than an "update" script mentioned in the thread title. It upgrades with the "dist-upgrade" option, by-passing the "upgrade" option, so it's actually more than an upgrade script as well. It's a dist-upgrade or full upgrade job. Possible issues with dist-upgrade are that it removes packages which ordinarily upgrade doesn't do, and that can run into dependency problems. They are usually correctable though,

As elegant as the log rotation in the script is, re-inventing the wheel is probably unnecessary. The logrotate package is able to configure logs with a little configuration including the power to compress logs to keep them efficiently.
 
But full-upgrade is supposed to be less agressive at deleting dependencies from what I read?
In the debian release notes for upgrading here:
one finds the comment in Section 4.4.5:
In some cases, doing the full upgrade (as described below) directly might remove large numbers of packages that you will want to keep. We therefore recommend a two-part upgrade process: first a minimal upgrade to overcome these conflicts, then a full upgrade

There are many more details in that link which may be of interest, but the main point I guess, is to try and avoid having the system in a less than optimal state after running your script. Getting all the details in order can be a challenge.

In relation to the full upgrade being "less aggressive", it's not really so much that which is its feature as the following from the man page:
Code:
dist-upgrade in addition to performing the function of upgrade, also intelligently handles changing
           dependencies with new versions of packages; apt-get has a "smart" conflict resolution system, and it will
           attempt to upgrade the most important packages at the expense of less important ones if necessary. The
           dist-upgrade command may therefore remove some packages.

It's clear from the debian link above, that running this suggested command:
Code:
apt upgrade --without-new-pkgs
before the dist-upgrade command, will get the system to be as upgraded as possible with what it has already installed, so that it is the best possible state for the "intelligent" operation of the dist-upgrade option to upgrade further to the new stage, likely with a new kernel, and the additional packages which may be relevant. Note that the above command uses apt, but apt-get can replace it.
 
In the debian release notes for upgrading here:
one finds the comment in Section 4.4.5:


There are many more details in that link which may be of interest, but the main point I guess, is to try and avoid having the system in a less than optimal state after running your script. Getting all the details in order can be a challenge.

In relation to the full upgrade being "less aggressive", it's not really so much that which is its feature as the following from the man page:
Code:
dist-upgrade in addition to performing the function of upgrade, also intelligently handles changing
           dependencies with new versions of packages; apt-get has a "smart" conflict resolution system, and it will
           attempt to upgrade the most important packages at the expense of less important ones if necessary. The
           dist-upgrade command may therefore remove some packages.

It's clear from the debian link above, that running this suggested command:
Code:
apt upgrade --without-new-pkgs
before the dist-upgrade command, will get the system to be as upgraded as possible with what it has already installed, so that it is the best possible state for the "intelligent" operation of the dist-upgrade option to upgrade further to the new stage, likely with a new kernel, and the additional packages which may be relevant. Note that the above command uses apt, but apt-get can replace it.
Thank you. This helps a lot and I will implement
Bash:
apt upgrade --without-new-pkgs
before dist-upgrade then to ensure full update and have my system as optimized as possible.. Am I understanding correctly? I will read the docs ASAP, I'm just in the middle of creating an offline password manager... getting familiar with argon2 hashing and implementing it in Python is cooking my brain at the moment..
 
For debian distributions then sudo apt update && apt upgrade is the safest bet as it dost remove any packages and safely updates your system, you can eapand this with sudo apt update && apt upgrade -y this will run the scripts without asking further permission, or follow it with apt autoremove to remove unwanted temporary filesi or another of my favorites s sudo apt autoremove && apt clean which cleans out nearly everything

sudo apt full -upgrade
You should also avoid using apt in scripts and instead use apt-get
sorry I totally diss agree, apt-get was the OLD command used by Debian packages, apt [without the get] is the newer and current standard
see https://itsfoss.com/apt-vs-apt-get-difference/
 
sorry I totally diss agree, apt-get was the OLD command used by Debian packages, apt [without the get] is the newer and current standard
see https://itsfoss.com/apt-vs-apt-get-difference/
Now I'm confused, it looks like my English betrayed me, here is what man apt says:

SCRIPT USAGE AND DIFFERENCES FROM OTHER APT TOOLS
The apt(8) commandline is designed as an end-user tool and it may change behavior between versions. While it tries not to break backward compatibility this is not guaranteed either if a change
seems beneficial for interactive use.

All features of apt(8) are available in dedicated APT tools like apt-get(8) and apt-cache(8) as well. apt(8) just changes the default value of some options (see apt.conf(5) and specifically the
Binary scope). So you should prefer using these commands (potentially with some additional options enabled) in your scripts as they keep backward compatibility as much as possible.

It says "So you should prefer using these commands (potentially with some additional options enabled) in your scripts as they keep backward compatibility as much as possible."

Which command are "these" here?
So it looks like the complete opposite of what I understood so far hm...

edit:

@Brickwizard
No sorry but it appears your link as well does not agree with you:

The apt-get command has a lot more options that are useful for writing low-level scripts and tools.

This is in line with man apt which is that apt should not be used in scripting, but is otherwise perfectly fine and better to use for interactive use.
 
Last edited:
but is otherwise perfectly fine and better to use for interactive use.
I don't do scripting per-say, I do like to string several commands together, but for the newbie I like to keep it simple
 
Thanks everyone for the advice. I enhanced the script by making the suggested edits:


Bash:
#!/bin/bash

# Function to handle errors with more context
handle_error() {
    echo "An error occurred at line ${BASH_LINENO[0]}:"
    echo "Command: $BASH_COMMAND"
    echo "Error: $1"
    read -p "Press Enter to exit."
    exit 1
}

# Trap errors
trap 'handle_error "$BASH_COMMAND"' ERR

# Logging directory
LOG_DIR="/home/erik/Documents/Update_logs"

# Ensure the log directory exists
mkdir -p "$LOG_DIR"

# Rotate logs to keep a maximum of 5 logs
rotate_logs() {
    local log_dir=$1
    local max_logs=5

    # Find and remove older log files
    find "$log_dir" -name "*.log" -type f -mtime +$max_logs -exec rm -f {} \;
}

# Rotate logs before creating a new one
rotate_logs "$LOG_DIR"

# Logging
LOG_FILE="$LOG_DIR/system_update_$(date +%Y%m%d%H%M%S).log"
exec &> >(tee -a "$LOG_FILE")

# Extend sudo timeout
sudo -v

echo -e "Reloading system manager configuration before performing full system update and cleanup..."
sudo systemctl daemon-reload

echo -e "\nUpdating package lists..."
sudo apt-get update || handle_error "Failed to update package lists"

echo -e "\nUpgrading all installed packages without installing new packages..."
sudo apt-get upgrade --without-new-pkgs -y || handle_error "Failed to upgrade packages without new packages"

echo -e "\nUpgrading all installed packages including distribution updates..."
sudo apt-get dist-upgrade -y || handle_error "Failed to upgrade packages"

echo -e "\nInstalling security updates not included in the regular upgrade..."
SECURITY_UPDATES=$(apt-get -s upgrade | grep "^Inst" | grep -i security | awk '{print $2}')
echo "Security updates to be installed: $SECURITY_UPDATES"

if [ -n "$SECURITY_UPDATES" ]; then
    sudo apt-get install --only-upgrade $SECURITY_UPDATES -y || handle_error "Failed to install security updates"
else
    echo "No security updates found."
fi

echo -e "\nInstalling recommended drivers..."
# Verify if ubuntu-drivers is available or use an alternative method
if command -v ubuntu-drivers &> /dev/null; then
    sudo ubuntu-drivers autoinstall || handle_error "Failed to install recommended drivers"
else
    echo "ubuntu-drivers command not found. Skipping driver installation."
fi

echo -e "\nRemoving unnecessary packages..."
sudo apt-get autoremove -y || handle_error "Failed to remove unnecessary packages"

echo -e "\nCleaning up package cache..."
sudo apt-get clean || handle_error "Failed to clean package cache"

echo -e "\nPurging unnecessary packages and their configuration files..."
sudo apt-get autoremove --purge -y || handle_error "Failed to purge unnecessary packages"

echo -e "\nCleaning up journal logs..."
sudo journalctl --vacuum-time=2d || handle_error "Failed to clean journal logs"

echo -e "\nUpdating Snap packages..."
sudo snap refresh || handle_error "Failed to update Snap packages"

echo -e "\nUpdating Flatpak packages..."
flatpak update -y || handle_error "Failed to update Flatpak packages"

echo -e "\nClearing the Linux cache..."
sudo sync && sudo sh -c 'echo 1 > /proc/sys/vm/drop_caches' || handle_error "Failed to clear Linux cache"

echo -e "\nSystem update and cleanup completed."

# Prompt for reboot or exit with clear instructions
read -p "Press [Enter] to reboot or [Esc] to exit the terminal..." -s -n 1 key
if [[ $key = $'\e' ]]; then
    echo "Exiting the terminal..."
else
    echo "Rebooting the system..."
    sudo reboot
fi
 
S
Thanks everyone for the advice. I enhanced the script by making the suggested edits:


Bash:
#!/bin/bash

# Function to handle errors with more context
handle_error() {
    echo "An error occurred at line ${BASH_LINENO[0]}:"
    echo "Command: $BASH_COMMAND"
    echo "Error: $1"
    read -p "Press Enter to exit."
    exit 1
}

# Trap errors
trap 'handle_error "$BASH_COMMAND"' ERR

# Logging directory
LOG_DIR="/home/erik/Documents/Update_logs"

# Ensure the log directory exists
mkdir -p "$LOG_DIR"

# Rotate logs to keep a maximum of 5 logs
rotate_logs() {
    local log_dir=$1
    local max_logs=5

    # Find and remove older log files
    find "$log_dir" -name "*.log" -type f -mtime +$max_logs -exec rm -f {} \;
}

# Rotate logs before creating a new one
rotate_logs "$LOG_DIR"

# Logging
LOG_FILE="$LOG_DIR/system_update_$(date +%Y%m%d%H%M%S).log"
exec &> >(tee -a "$LOG_FILE")

# Extend sudo timeout
sudo -v

echo -e "Reloading system manager configuration before performing full system update and cleanup..."
sudo systemctl daemon-reload

echo -e "\nUpdating package lists..."
sudo apt-get update || handle_error "Failed to update package lists"

echo -e "\nUpgrading all installed packages without installing new packages..."
sudo apt-get upgrade --without-new-pkgs -y || handle_error "Failed to upgrade packages without new packages"

echo -e "\nUpgrading all installed packages including distribution updates..."
sudo apt-get dist-upgrade -y || handle_error "Failed to upgrade packages"

echo -e "\nInstalling security updates not included in the regular upgrade..."
SECURITY_UPDATES=$(apt-get -s upgrade | grep "^Inst" | grep -i security | awk '{print $2}')
echo "Security updates to be installed: $SECURITY_UPDATES"

if [ -n "$SECURITY_UPDATES" ]; then
    sudo apt-get install --only-upgrade $SECURITY_UPDATES -y || handle_error "Failed to install security updates"
else
    echo "No security updates found."
fi

echo -e "\nInstalling recommended drivers..."
# Verify if ubuntu-drivers is available or use an alternative method
if command -v ubuntu-drivers &> /dev/null; then
    sudo ubuntu-drivers autoinstall || handle_error "Failed to install recommended drivers"
else
    echo "ubuntu-drivers command not found. Skipping driver installation."
fi

echo -e "\nRemoving unnecessary packages..."
sudo apt-get autoremove -y || handle_error "Failed to remove unnecessary packages"

echo -e "\nCleaning up package cache..."
sudo apt-get clean || handle_error "Failed to clean package cache"

echo -e "\nPurging unnecessary packages and their configuration files..."
sudo apt-get autoremove --purge -y || handle_error "Failed to purge unnecessary packages"

echo -e "\nCleaning up journal logs..."
sudo journalctl --vacuum-time=2d || handle_error "Failed to clean journal logs"

echo -e "\nUpdating Snap packages..."
sudo snap refresh || handle_error "Failed to update Snap packages"

echo -e "\nUpdating Flatpak packages..."
flatpak update -y || handle_error "Failed to update Flatpak packages"

echo -e "\nClearing the Linux cache..."
sudo sync && sudo sh -c 'echo 1 > /proc/sys/vm/drop_caches' || handle_error "Failed to clear Linux cache"

echo -e "\nSystem update and cleanup completed."

# Prompt for reboot or exit with clear instructions
read -p "Press [Enter] to reboot or [Esc] to exit the terminal..." -s -n 1 key
if [[ $key = $'\e' ]]; then
    echo "Exiting the terminal..."
else
    echo "Rebooting the system..."
    sudo reboot
fi


Sorry, I forgot... Now that I run it with sudo /directory/script.sh I can remove sudo from commands:


Bash:
#!/bin/bash

# Function to handle errors with more context
handle_error() {
    echo "An error occurred at line ${BASH_LINENO[0]}:"
    echo "Command: $BASH_COMMAND"
    echo "Error: $1"
    read -p "Press Enter to exit."
    exit 1
}

# Trap errors
trap 'handle_error "$BASH_COMMAND"' ERR

# Logging directory
LOG_DIR="/home/erik/Documents/Update_logs"

# Ensure the log directory exists
mkdir -p "$LOG_DIR"

# Rotate logs to keep a maximum of 5 logs
rotate_logs() {
    local log_dir=$1
    local max_logs=5

    # Find and remove older log files
    find "$log_dir" -name "*.log" -type f -mtime +$max_logs -exec rm -f {} \;
}

# Rotate logs before creating a new one
rotate_logs "$LOG_DIR"

# Logging
LOG_FILE="$LOG_DIR/system_update_$(date +%Y%m%d%H%M%S).log"
exec &> >(tee -a "$LOG_FILE")

echo -e "Reloading system manager configuration before performing full system update and cleanup..."
systemctl daemon-reload

echo -e "\nUpdating package lists..."
apt-get update || handle_error "Failed to update package lists"

echo -e "\nUpgrading all installed packages without installing new packages..."
apt-get upgrade --without-new-pkgs -y || handle_error "Failed to upgrade packages without new packages"

echo -e "\nUpgrading all installed packages including distribution updates..."
apt-get dist-upgrade -y || handle_error "Failed to upgrade packages"

echo -e "\nInstalling security updates not included in the regular upgrade..."
SECURITY_UPDATES=$(apt-get -s upgrade | grep "^Inst" | grep -i security | awk '{print $2}')
echo "Security updates to be installed: $SECURITY_UPDATES"

if [ -n "$SECURITY_UPDATES" ]; then
    apt-get install --only-upgrade $SECURITY_UPDATES -y || handle_error "Failed to install security updates"
else
    echo "No security updates found."
fi

echo -e "\nInstalling recommended drivers..."
# Verify if ubuntu-drivers is available or use an alternative method
if command -v ubuntu-drivers &> /dev/null; then
    ubuntu-drivers autoinstall || handle_error "Failed to install recommended drivers"
else
    echo "ubuntu-drivers command not found. Skipping driver installation."
fi

echo -e "\nRemoving unnecessary packages..."
apt-get autoremove -y || handle_error "Failed to remove unnecessary packages"

echo -e "\nCleaning up package cache..."
apt-get clean || handle_error "Failed to clean package cache"

echo -e "\nPurging unnecessary packages and their configuration files..."
apt-get autoremove --purge -y || handle_error "Failed to purge unnecessary packages"

echo -e "\nCleaning up journal logs..."
journalctl --vacuum-time=2d || handle_error "Failed to clean journal logs"

echo -e "\nUpdating Snap packages..."
snap refresh || handle_error "Failed to update Snap packages"

echo -e "\nUpdating Flatpak packages..."
flatpak update -y || handle_error "Failed to update Flatpak packages"

echo -e "\nClearing the Linux cache..."
sync && sh -c 'echo 1 > /proc/sys/vm/drop_caches' || handle_error "Failed to clear Linux cache"

echo -e "\nSystem update and cleanup completed."

# Prompt for reboot or exit with clear instructions
read -p "Press [Enter] to reboot or [Esc] to exit the terminal..." -s -n 1 key
if [[ $key = $'\e' ]]; then
    echo "Exiting the terminal..."
else
    echo "Rebooting the system..."
    reboot
fi
 


Members online


Top