Skip to content

Instantly share code, notes, and snippets.

@patrakov
Last active Dec 7, 2021
Embed
What would you like to do?
Automatically reinstall OpenWRT packages after firmware upgrades
The script helps you restore all installed OpenWRT packages after upgrading the main firmware image via sysupgrade. It works
ONLY if the default firmware image provided by the OpenWRT project is sufficient to get connected to the Internet, but you
want some extra packages for additional functionality. In other words, it WILL NOT WORK if connecting to the Internet
requires installing extra packages (e.g., a kernel module for your LTE modem).
The script has been tested for upgrading from OpenWRT 18.06.1 to 18.06.2 and to a development snapshot, as well as between
development snapshots. On LEDE 17.01.x, "flock" is not a part of the default image, so has to be installed manually.
Initial setup:
1. Save the script to /etc/package-list/persist.sh
2. chmod 755 /etc/package-list/persist.sh
3. echo "*/5 * * * * flock -n /var/lock/persist.lock /etc/package-list/persist.sh" > /etc/crontabs/root
4. Edit /etc/sysupgrade.conf to mention /etc/package-list/ and other files that should be preserved, e.g. /etc/firewall.user
5. touch /usr/.extra-pakages-installed
6. Reboot the router
7. Wait for it to come up again and to create /etc/package-list/extra-packages.txt
If there is anything ($BADPACKAGE) listed that you think should only be installed as a dependency:
opkg flag ok $BADPACKAGE
sed -i "/^$BADPACKAGE\$/d" /etc/package-list/extra-packages.txt
If you plan to use snapshots, add luci to /etc/package-list/extra-packages.txt.
Further on, the script will automatically track any extra packages that you install or remove.
At this point, you can upgrade firmware as usual, and all the extra packages will be automatically reinstalled after a
reboot - just wait 10 minutes (more if you have a slow connection). It is possible to watch the progress in
/var/log/persist-packages.log.
After the installation, the script will reboot the router once more, just in case, e.g. to apply firewall settings that
depend on the new packages.
#!/bin/sh
exec > /var/log/persist-packages.log 2>&1
set -x
PKGS=/etc/package-list/extra-packages.txt
# https://github.com/openwrt/packages/issues/6744, not fixed in 18.06.x
fix_route53() {
if grep -q CURL_SSL /usr/lib/ddns/update_route53_v1.sh 2>/dev/null ; then
sed -i /CURL_SSL/d /usr/lib/ddns/update_route53_v1.sh
fi
}
list_extra_packages() {
if [ ! -f $PKGS ] || [ /usr/lib/opkg/status -nt $PKGS ] ; then
# Find the latest package in the ROM
PROG='
$1 == "Installed-Time:" && ($2 < NEWEST || NEWEST=="") {
NEWEST=$2
}
END {
print NEWEST
}
'
FLASH_TIME="$( awk "$PROG" /rom/usr/lib/opkg/status )"
# All user-installed packages minus those from ROM mistakenly marked as such
# plus (those explicitly marked previously minus those not installed)
MARKED=`awk '{RE=RE "|" $0} END { print RE }' $PKGS`
MARKED='^('${MARKED#|}')$'
PROG='
$1 == "Package:" {
PKG=$2
USR=""
}
$1 == "Status:" && $3 ~ "user" {
USR=1
}
$1 == "Installed-Time:" && $2 > FT && ( USR || ( PKG ~ MARKED ) ) {
print PKG
}
'
awk -v FT="$FLASH_TIME" -v MARKED="$MARKED" "$PROG" /usr/lib/opkg/status | sort > $PKGS.tmp
mv $PKGS.tmp $PKGS
# Maybe somebody updated it and OpenWRT team forgot to propagate the fix?
fix_route53
fi
}
install_extra_packages() {
set -e
opkg update
UPGRADE=`opkg list-upgradable | cut -d ' ' -f 1`
if [ -n "$UPGRADE" ] ; then
opkg upgrade $UPGRADE
opkg flag ok $UPGRADE
fi
INSTALL_CANDIDATES=`cat $PKGS`
# Weed out packages that don't exist anymore
INSTALL=""
for CANDIDATE in $INSTALL_CANDIDATES ; do
if [ -n "`opkg list $CANDIDATE`" ] ; then
INSTALL="$INSTALL $CANDIDATE"
fi
done
if [ -n "$INSTALL" ] ; then
opkg install $INSTALL
fi
fix_route53
find /etc -name \*-opkg -exec rm '{}' ';'
touch /usr/.extra-pakages-installed
sleep 70
reboot
}
if [ -f /usr/.extra-pakages-installed ] ; then
list_extra_packages
elif [ -f $PKGS ] ; then
install_extra_packages
fi
@kevinoid
Copy link

kevinoid commented Sep 19, 2020

This is great, thanks for posting it! Neat trick to use Install-Time to weed out "user" packages from /rom.

Have you considered running persist.sh as a sysupgrade runscript (like Rafciq's approach) instead of every 5 minutes via cron? Might be a bit snappier and more efficient if it's workable.

@patrakov
Copy link
Author

patrakov commented Sep 19, 2020

I was not aware of the "sysupgrade runscript" based approach.

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