Skip to content

Instantly share code, notes, and snippets.

@h908714124
Last active February 4, 2026 18:54
Show Gist options
  • Select an option

  • Save h908714124/7325d8213b81dce638a20ab9866d414d to your computer and use it in GitHub Desktop.

Select an option

Save h908714124/7325d8213b81dce638a20ab9866d414d to your computer and use it in GitHub Desktop.
update-fedora
#!/bin/bash
queue=""
REPLY=""
pop() {
if [[ $queue ]]; then
REPLY="${queue:0:1}"
queue="${queue:1}"
else
REPLY=""
return 0
fi
}
read_q() {
pop
if [[ $REPLY ]]; then
echo "$1$REPLY"
return 0
else
read -p "$1"
queue="$REPLY"
pop
fi
}
synopsis() {
tput bold
echo "USAGE"
tput sgr0
echo " update-fedora [batch_commands]"
echo
tput bold
echo "EXAMPLES"
tput sgr0
echo " update-fedora"
echo " When there is no parameter, the program starts in interactive mode."
echo " update-fedora uoy"
echo " Batch mode: perform commands 'u'(pdate), 'o'(ffline) and 'y'(es) in sequence."
echo " Warning! If any updates are available,"
echo " this will perform an offline update and reboot your computer."
echo " update-fedora uoy"
echo " Batch mode: perform commands 'u'(pdate), 'o'(ffline) and 'y'(es) in sequence."
echo " Warning! If any updates are available,"
echo " this will perform an offline update and reboot your computer."
echo " update-fedora sq"
echo " Batch mode: perform commands 's'(how) and 'q'(uit) in sequence."
echo " Show available updates, then quit."
echo " update-fedora cq"
echo " Batch mode: perform commands 'c'(hangelog) and 'q'(uit) in sequence."
echo " If updates are available, show the changelog, then quit."
}
release_type() {
sed -n -E 's/^RELEASE_TYPE=(\S+)/\1/p' /etc/os-release
}
os_release() {
sed -n -E 's/^VERSION_ID=(\S+)/\1/p' /etc/os-release
}
target_release() {
local current result
current=$(os_release)
if [[ $(release_type) != "stable" ]]; then
echo $current
return 0
fi
local metainfo=/usr/share/metainfo/org.fedoraproject.fedora.metainfo.xml
if [[ -f $metainfo ]]; then
result=$(xmllint --xpath "/component/releases//release[@type='stable']/@version" $metainfo | \
sed -n -E 's/.*[=]["]([0-9]+)["].*/\1/p' | \
sort -rn | \
head -1)
else
result=$(curl -s "https://fedoraproject.org/releases.json" | \
jq -r ".[]|select( .arch == \"$(uname -m)\") |.version" | \
sort -rn | \
head -1)
fi
if (( result >= current )); then
echo $result
else
echo $current
fi
}
is_update_prepared() {
sudo dnf offline status | grep -F -q "offline reboot"
}
check_updates_available() {
[[ $(dnf check-update --refresh 2> /dev/null) ]]
}
system_update() {
sudo dnf -y system-upgrade download --releasever=$1 && {
read_q "A system update is prepared. Would you like to reboot right now? [y/N] "
[[ $REPLY =~ [yY] ]] && sudo dnf -y offline reboot
}
}
update_running() {
sudo dnf -y update --refresh
}
submenu_update_prepared() {
echo "An offline-update is prepared."
while true; do
read_q "[r]eboot [c]lean [q]uit ? "
case $REPLY in
r)
sudo dnf -y offline reboot
return 0
;;
c)
sudo dnf -y offline clean
return 0
;;
q)
return 0
;;
esac
done
}
update_offline() {
sudo dnf -y update --refresh --offline || return 1
submenu_update_prepared
}
default_action() {
local opt options
options=$(getopt -u -o "h" -l "help" -- "$@")
(( $? == 0 )) || {
synopsis
return 1
}
for opt in $options; do
case "$opt" in
-h | --help)
synopsis
return 0
;;
--)
;;
*)
[[ $queue ]] && {
synopsis
return 1
}
queue="$opt"
;;
esac
done
if is_update_prepared; then
if [[ $queue = *:* ]]; then
queue="${queue#*:}"
else
queue=""
fi
submenu_update_prepared
return 0
elif [[ $queue = *:* ]]; then
queue=${queue%:*}
fi
check_updates_available && {
echo "An update is available."
while true; do
read_q "[s]how [u]pdate [c]hangelog [q]uit ? "
case $REPLY in
s)
dnf check-update
;;
u)
while true; do
read_q "[o]ffline [r]unning [q]uit [b]ack ? "
case $REPLY in
o)
update_offline
return 0
;;
q)
return 0
;;
r)
update_running
return 0
;;
b)
break
;;
esac
done
;;
c)
dnf changelog --upgrades
;;
q)
return 0
;;
esac
done
}
queue=""
echo "The system is up-to-date."
local current target
current=$(os_release)
target=$(target_release)
if (( current == target )); then
[[ $(release_type) = "stable" ]] && {
read_q "Would you like to upgrade to rawhide? [y/N] "
[[ $REPLY =~ [yY] ]] && system_update rawhide
}
elif (( current < target )); then
echo "A system update to fedora $(( current + 1 )) is available."
read_q "Would you like to download it now? [y/N] "
[[ $REPLY =~ [yY] ]] && system_update $(( current + 1 ))
fi
return 0
}
return 2> /dev/null || {
default_action "$@"
exit $?
}
@h908714124
Copy link
Author

h908714124 commented Dec 25, 2025

Keeping fedora updated is a bit hard. It's not a rolling distro, unless you use rawhide. This script simplifies the task, because it knows when to do the system-update. I keep it in ~/.local/bin/update-fedora and run it frequently. I also like to disable the notifications from Discover.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment