Update Reminders in Arch Linux Terminal

Disclaimer: Proceed with caution, I’m fairly new to Arch & Linux, so please do due diligence and research around any commands you enter on your system.

I was trying to conceive of a method of updating regularly and safely in Arch Linux.

You shouldn’t automatically apply updates, Arch is designed for human intervention. With automatically applying updates there’s the chance that you’ll log in one day to a broken system. I haven’t settled on my backup strategy yet so that adds extra risk.

There are still some things you can do to speed up and prepare/notify yourself around updates, I will call this my¬†Update Prep System. Apologies for the bad formatting, still getting a hang of blogging and styling WordPress. Additional apologies for the rough scripting, if there is interest I’ll extract this source into a public git repo.

Update Prep System

update-prep-notification

Pre-requisites

  • Arch install (although may work on other distros)
  • cronie
#!/usr/bin/env bash

sudo pacman -Syy cronie
sudo systemctl enable --now cronie.service

Steps

The system consists of these steps:

  1. Install the cron job
  2. Regular download of new packages (pacman) without install
  3. Upgrade user .bashrc
  4. Each time terminal opens, if new packages are ready, echo before the prompt.

Script for downloading updated packages

Save the following script somewhere as `download-packages` for the cron job to access it.

#!/usr/bin/env bash
#
# Usages
#     Please run to check: root@root# crontab -l
#
# Usage
#     [-h|--help]    - show help

logdir="/var/log"
logpath="$logdir/download-packages.log"
if [ ! -f $logpath ]; then
    mkdir -p "${logdir}"
    touch "${logpath}"
fi

function printlog () {
    local DATE=`date '+%Y-%m-%d %H:%M:%S'`
    echo "${DATE}: $1" | tee -a $logpath
}

# root check
user="$(whoami)"
if [ "$user" != "root" ]; then
    printlog "This script must be run as root user."
    exit 1;
fi

if [ -z "${1+xxx}" ] || [ "$1" == "-h" ] || [ "$1" == "--help" ]; then
    echo "Usage"
    echo "    NOTE: This script must be run as root."
    echo "    --download                 downloads new packages"
fi

if [ "$1" == "--download" ]; then
    printlog "Downloading new packages..."

    # TODO: print to log file...
    pacman -Syuw --noconfirm
    printlog "New package check complete."
    exit 0;
fi

exit 1; # should be impossible to reach here.

cron job

Run this script `add-root-cronjob_download-packages.sh –install-cron` to instruct your system to regularly download new packages:

#!/usr/bin/env bash
#
# Usage
#     [-h|--help]    - show help
#
# Dependencies
#     - cronie (Arch)

cron="1 * * * *" # each hour
#cron="* * * * *" # test every minute
logdir="/tmp"
logpath="$logdir/.download-packages.log"
if [ ! -f $logpath ]; then
    mkdir -p "${logdir}"
    touch "${logpath}"
fi

function printlog () {
    local DATE=`date '+%Y-%m-%d %H:%M:%S'`
    echo "${DATE}: $1" | tee -a $logpath
}


# root check, script must be run as user first.
user="$(whoami)"
if [ "$user" != "root" ]; then
    printlog "This script must be run as root user."
    exit 1;
fi
printlog "root user detected."


# show help if no args are passed, or if help flag gets passed
if [ -z "${1+xxx}" ] || [ "$1" == "-h" ] || [ "$1" == "--help" ]; then
    echo "Usage"
    echo "--install-cron             creates cronjob to run this script hourly"
fi


# run as user.
if [ "$1" == "--install-cron" ]; then
    printlog "Attempting to install cron job"
    #####################
    # check if cronie has been installed
    pacman -Qi cronie >/dev/null 2>&1
    if [ $? -eq 0 ]
    then
        printlog "Cronie already installed, continuing."
    else
        printlog "installing cronie."
        sudo pacman -Syy cronie
        sudo systemctl enable --now cronie.service
    fi
    
    # rewrite crontab into temp file
    cwd=$(pwd)
    tempdir="/tmp/croninstall"
    mkdir -p $tempdir
    cd $tempdir
    job="crontab.tmp"
    # copy current crontab to temporary file $job
    crontab -l > $job
    dlscript="/path/to/download-packages"
    printlog "creating temporary crontab for editing: '${tempdir}/$job'"
    cronjob="${cron} /usr/bin/env bash ${dlscript} --download"
    echo "${cronjob}" >> $job
    printlog "installing cron job from '${tempdir}/$job' to ${user}'s crontab:"
    printlog "${cronjob}"
    crontab $job
    printlog "cleaning up temporary cron job install files"
    rm -rf $tempdir
    cd "${cwd}"
    printlog "contents of $user crontab: (to edit, run \$ crontab -e)"
    crontab -l | tee -a $logpath

    printlog "install mode of this script finished. Exit."
    exit 0;
fi

Upgrade .bashrc

Use the following script `add-bashrc-check.sh` to upgrade your .bashrc to check if updates are ready to install.


#!/usr/bin/env bash

user="$(whoami)"
group="$(groups $user)"
if [ "$user" == "root" ] || [ "$group" == "root" ]; then
    echo "This install script must be run for/as a non-root user."
    exit 1;
fi

cat  ~/.bashrc

# check if there are package updates and notify user.
# installed with archlinux/install/mine/download-packages-install/add-bashrc-check.sh
bash is-offline-updates-ready
if [ \$? -eq 0 ]; then
    echo "Updates required. Run 'upgrade-packages' to install."
fi
EOT
exit 0;

Open Terminal: Are Updates Ready?

Place this script `is-offline-updates-ready.sh` on your user `$PATH`. This checks for pending updates each time a terminal is open and stays silent if there aren’t any.

#!/usr/bin/env bash

# How to use this script
#     bash is-offline-updates-ready
#     if [ $? -eq 0 ]
#     then
#         echo "Updates required."
#     fi


if [ "$1" == "-h" ] || [ "$1" == "--help" ]; then
    echo "Usage:"
    echo "    NOTE: This script must be run as root."
    echo "    returns 0 if packages are ready to install"
    echo "    returns 1 if no new packages are downloaded"
fi


# grep for lines containing an arrow (i.e. contain the format 1.0.0.0 -> 2.0.0.0)
toUpdate=$(pacman -Qu | grep "\->" | wc -l)
if [ $toUpdate -gt 0 ]; then
    echo "There are $toUpdate packages to update."
    exit 0;
fi

exit 1;

upgrade-packages

A small script that upgrades all pacman and aur packages. You could use your own implementation as mine is a bit primitive right now.

#!/usr/bin/env bash

# https://wiki.archlinux.org/index.php/Pacman#Upgrading_packages
# https://wiki.archlinux.org/index.php/System_maintenance#Upgrading_the_system


# Upgrade AUR (yay) via running git install script again.
# ------------------------------------------------------------------------------
#       https://github.com/Jguer/yay/issues/1087#issuecomment-545585765
# TODO: only remove and reinstall if newer yay package exists.
sudo pacman -R yay
# TODO: put the following in a yay install script for D.R.Y.
cwd=$(pwd)
cd /tmp
git clone https://aur.archlinux.org/yay.git
cd yay
makepkg -si
cd ..
rm -rf yay
cd "$cwd"
# ------------------------------------------------------------------------------

echo "upgrading packages => pacman -Syu"
sudo pacman -Syu

echo "upgrading packages => yay -Syu --devel --timeupdate"
yay -Syu --devel --timeupdate

finally {}

Let me know if you’d like me to extract this to a public git repo, at the moment it’s highly coupled to my personal scripts repo and filesystem structure.

Blog at WordPress.com.

Up ↑