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.

Effective Life Changes: Self-Contracts

This blog post was inspired by a Ted talk I just watched from Mark Adams. He mentions a system called Lock-in. A brief scouring of the internet didn’t get anywhere for me, but I did manage to extract some value from his talk.

Let’s call this system Self-Contracts. It’s a work in progress, and I’ll keep this post as it’s home for now.

Structure

You will need the following. Create a cloud text document or your favourite record system and start writing the following:

Constraint

You’re trying to make an improvement in your life, so most likely you’re trying to give yourself an Enabling Constraint.

Penalty

You’ve got to make ‘doing the thing’ the lesser evil – the penalty for not doing it needs to be a lot worse.

Risk

What you have to risk if you fail.

Reward

What you stand to gain should you succeed.

Stakeholders

These are people involved that have a vested interest in you succeeding. They may cast shame upon you (depending on how you structure your contract) if you breach your contract.

Exit Criteria

What would be required to make this self-contract obsolete and never reoccur?

Time

A set period of time for your self-contract to be in effect

Conditions

The self-contract is indefinite or unbounded by time. There may still be conditions to exit a self-contract not based on time.

Example

Self-Contract: Alcohol Constraint

Constraint: No drinking alcohol when above 95KGs in body weight.
Penalty: Social Shame
Risk: Pride, seen to have no control.
Reward: Health, Productivity, Control.
Stakeholders: Flatmates
Exit Criteria: Discovering a life-threatening disease, where drinking alcohol is the least of my worries.

Conclusion

This is a work in progress. Any suggestions to refine, constructive criticism is welcomed. Feel free to leave a comment.

Create a free website or blog at WordPress.com.

Up ↑