This is an old revision of the document!
Opkg extras
Introduction
- This instruction extends Opkg functionality.
- Follow Hotplug extras to extend Hotplug functionality.
- Follow UCI extras to extend UCI functionality.
- Follow the automated section for quick setup.
Features
- Save, restore and roll back Opkg profiles.
- Support automatic and custom profiles.
- Identify user-removed/installed packages.
- Restore automatically after firmware upgrade.
- Upgrade all upgradable packages.
- Find new configurations.
Implementation
- Wrap Opkg calls to provide a seamless invocation method.
- Rely on UCI and backup defaults to store and manage profiles.
- Support importing user-installed packages from Sysupgrade.
- Use Hotplug to detect WAN connectivity and trigger profile restore.
- Utilize lockfiles with lock to avoid race conditions and loops.
- Perform reboot to apply changes after automatic profile restore.
- Write and read non-interactive logs with Syslog for troubleshooting.
- Fetch the default profile to restore and roll back from UCI, unless specified manually.
- Take precedence for remove over install to avoid package conflicts while restoring profile.
- Limit the operation scope to save time: remove installed, install missing, upgrade upgradable.
- Process packages one by one to minimize resource consumption and avoid transaction failure.
Commands
| Opkg sub-command | Description |
|---|---|
help | Show Opkg extras. |
import [<bakprof>] | Import Opkg profile from Sysupgrade backup to UCI. |
save [<prof>] | Save the current Opkg profile to UCI. |
restore [<prof>] | Restore Opkg profile:custom - custom profile configured manually,auto or none - automatic profile. |
rollback [<prof>] | Roll back Opkg profile: remove user-installed packages, install user-removed packages, skip upgraded packages. |
upgr [<pkgtype>] | Upgrade packages by type:au or none - all upgradable,oi - overlay-installed. |
export [<pkgtype>] | Export packages by type:ai or none - all installed,au - all upgradable,ri - ROM-installed,wr - RWM-removed,wi - RWM-installed,or - overlay-removed,oi - overlay-installed,ur - user-removed,ui - user-installed,pr - profile-removed,pi - profile-installed. |
proc <cmd> <pkgs> | Process packages one by one with the given sub-command. |
reinstall <pkgs> | Reinstall specific packages. |
newconf [<path>] | Find new configurations. |
uci [<prof>] < <uciprof> | Initialize Opkg profile from stdin or file. |
uciget <cmd> [<defaults>] | Get Opkg defaults for the given sub-command. |
Instructions
# Configure profile mkdir -p /etc/profile.d cat << "EOF" > /etc/profile.d/opkg.sh opkg() { local OPKG_CMD="${1}" if ! type opkg_"${OPKG_CMD}" &> /dev/null then command opkg "${@}" else shift opkg_"${OPKG_CMD}" "${@}" fi } opkg_help() { cat << EOI opkg [help|import|save|restore|rollback|upgr\ |export|proc|reinstall|newconf|uci|uciget] opkg upgr [au|oi] opkg export [ai|au|ri|wr|wi|or|oi|ur|ui|pr|pi] EOI } opkg_import() { local OPKG_BAK="${1:-/etc/backup/installed_packages.txt}" if grep -q -e "^overlayfs:" /etc/mtab then local OPKG_DEST="overlay" else local OPKG_DEST="unknown" fi if [ -e "${OPKG_BAK}" ] then sed -n -e "s/\s${OPKG_DEST}$/\tipkg/p" "${OPKG_BAK}" \ | opkg uci fi } opkg_save() { local OPKG_PROF="$(opkg uciget "${OPKG_CMD}" auto "${1}")" local OPKG_UR="$(opkg export ur)" local OPKG_UI="$(opkg export ui)" { sed -e "s/$/\trpkg/" "${OPKG_UR}" sed -e "s/$/\tipkg/" "${OPKG_UI}" } | opkg uci "${OPKG_PROF}" rm -f "${OPKG_UR}" "${OPKG_UI}" local OPKG_PROF="rwm" local OPKG_WR="$(opkg export wr)" local OPKG_WI="$(opkg export wi)" { sed -e "s/$/\trpkg/" "${OPKG_WR}" sed -e "s/$/\tipkg/" "${OPKG_WI}" } | opkg uci "${OPKG_PROF}" rm -f "${OPKG_WR}" "${OPKG_WI}" } opkg_restore() { local OPKG_PROF="$(opkg uciget "${OPKG_CMD}" auto "${1}")" local OPKG_AI="$(opkg export ai)" local OPKG_PR="$(opkg export pr)" local OPKG_PI="$(opkg export pi)" opkg proc remove $(grep -x -f "${OPKG_AI}" "${OPKG_PR}") opkg proc install $(grep -v -x -f "${OPKG_AI}" "${OPKG_PI}") rm -f "${OPKG_AI}" "${OPKG_PR}" "${OPKG_PI}" } opkg_rollback() { local OPKG_PROF="$(opkg uciget "${OPKG_CMD}" auto "${1}")" local OPKG_UR="$(opkg export ur)" local OPKG_UI="$(opkg export ui)" local OPKG_PR="$(opkg export pr)" local OPKG_PI="$(opkg export pi)" opkg restore "${OPKG_PROF}" opkg proc remove $(grep -v -x -f "${OPKG_PI}" "${OPKG_UI}") opkg proc install $(grep -v -x -f "${OPKG_PR}" "${OPKG_UR}") rm -f "${OPKG_UR}" "${OPKG_UI}" "${OPKG_PR}" "${OPKG_PI}" } opkg_upgr() { local OPKG_ARG="${1:-au}" if ! type opkg_"${OPKG_CMD}_${OPKG_ARG}" &> /dev/null then opkg help else shift opkg_"${OPKG_CMD}_${OPKG_ARG}" "${@}" fi } opkg_upgr_au() { local OPKG_AI="$(opkg export ai)" local OPKG_AU="$(opkg export au)" opkg proc upgrade $(grep -x -f "${OPKG_AI}" "${OPKG_AU}") rm -f "${OPKG_AI}" "${OPKG_AU}" } opkg_upgr_oi() { local OPKG_OI="$(opkg export oi)" local OPKG_AU="$(opkg export au)" opkg proc upgrade $(grep -x -f "${OPKG_OI}" "${OPKG_AU}") rm -f "${OPKG_OI}" "${OPKG_AU}" } opkg_export() { local OPKG_ARG="${1:-ai}" local OPKG_EXP="$(mktemp -t opkg.XXXXXX)" if ! type opkg_"${OPKG_CMD}_${OPKG_ARG}" &> /dev/null then opkg help else shift opkg_"${OPKG_CMD}_${OPKG_ARG}" "${@}" > "${OPKG_EXP}" cat << EOI ${OPKG_EXP} EOI fi } opkg_export_ai() { opkg list-installed "${@}" | sed -e "s/\s.*$//" } opkg_export_au() { opkg list-upgradable "${@}" | sed -e "s/\s.*$//" } opkg_export_ri() { local OPKG_INFO="/rom/usr/lib/opkg/info" find "${OPKG_INFO}" -name "*.control" -type "f" 2> /dev/null \ | sed -e "s/^.*\///;s/\.control$//" } opkg_export_wr() { local OPKG_INFO="/rwm/upper/usr/lib/opkg/info" find "${OPKG_INFO}" -name "*.control" -type "c" 2> /dev/null \ | sed -e "s/^.*\///;s/\.control$//" } opkg_export_wi() { local OPKG_INFO="/rwm/upper/usr/lib/opkg/info" find "${OPKG_INFO}" -name "*.control" -type "f" 2> /dev/null \ | sed -e "s/^.*\///;s/\.control$//" } opkg_export_or() { local OPKG_INFO="/overlay/upper/usr/lib/opkg/info" find "${OPKG_INFO}" -name "*.control" -type "c" 2> /dev/null \ | sed -e "s/^.*\///;s/\.control$//" } opkg_export_oi() { local OPKG_INFO="/overlay/upper/usr/lib/opkg/info" find "${OPKG_INFO}" -name "*.control" -type "f" 2> /dev/null \ | sed -e "s/^.*\///;s/\.control$//" } opkg_export_ur() { local OPKG_AI="$(opkg export ai)" local OPKG_RI="$(opkg export ri)" grep -v -x -f "${OPKG_AI}" "${OPKG_RI}" rm -f "${OPKG_AI}" "${OPKG_RI}" } opkg_export_ui() { local OPKG_AI="$(opkg export ai)" local OPKG_RI="$(opkg export ri)" grep -v -x -f "${OPKG_RI}" "${OPKG_AI}" rm -f "${OPKG_AI}" "${OPKG_RI}" } opkg_export_pr() { uci -q get opkg."${OPKG_PROF}".rpkg | sed -e "s/\s/\n/g" } opkg_export_pi() { uci -q get opkg."${OPKG_PROF}".ipkg | sed -e "s/\s/\n/g" } opkg_proc() { local OPKG_OPT="$(opkg uciget "${OPKG_CMD}" --force-depends)" local OPKG_CMD="${1:?}" local OPKG_PKG shift for OPKG_PKG in "${@}" do if [ "${OPKG_PKG%%-*}" = "dnsmasq" -a "${OPKG_CMD}" = "remove" ] then /etc/init.d/dnsmasq stop fi opkg "${OPKG_CMD}" "${OPKG_PKG}" ${OPKG_OPT} if [ "${OPKG_PKG%%-*}" = "grep" ] then hash -r fi done } opkg_reinstall() { local OPKG_OPT="$(opkg uciget "${OPKG_CMD}" --force-reinstall)" opkg install "${@}" ${OPKG_OPT} } opkg_newconf() { local OPKG_PATH="${1:-/etc}" find "${OPKG_PATH}" -name "*-opkg" } opkg_uci() { local OPKG_PROF="$(opkg uciget "${OPKG_CMD}" auto "${1}")" if ! uci -q show opkg > /dev/null then uci import opkg < /dev/null fi uci -q batch << EOI delete opkg.${OPKG_PROF} set opkg.defaults=opkg set opkg.custom=opkg set opkg.${OPKG_PROF}=opkg $(sed -r -e "s/^(.*)\s(.*)$/\ add_list opkg.${OPKG_PROF}.\2=\1/") commit opkg EOI } opkg_uciget() { local OPKG_UCI="$(uci -q get opkg.defaults."${1}")" local OPKG_UCI="${3:-${OPKG_UCI}}" local OPKG_UCI="${OPKG_UCI:-${2}}" cat << EOI ${OPKG_UCI} EOI } EOF . /etc/profile.d/opkg.sh # Restore packages automatically mkdir -p /etc/hotplug.d/online cat << "EOF" > /etc/hotplug.d/online/50-opkg-restore if [ ! -e /etc/opkg-restore ] \ && lock -n /var/lock/opkg-restore \ && opkg update then . /etc/profile.d/opkg.sh if uci -q get opkg.rwm &> /dev/null then opkg restore rwm else opkg restore fi touch /etc/opkg-restore lock -u /var/lock/opkg-restore reboot fi EOF cat << "EOF" >> /etc/sysupgrade.conf /etc/hotplug.d/online/50-opkg-restore EOF
Examples
# Save Opkg profile opkg save # Restore Opkg profile opkg update opkg restore # Roll back Opkg profile opkg rollback # Set up a custom Opkg profile uci set opkg.defaults.restore="custom" uci -q delete opkg.custom.rpkg uci add_list opkg.custom.rpkg="dnsmasq" uci add_list opkg.custom.rpkg="ppp" uci -q delete opkg.custom.ipkg uci add_list opkg.custom.ipkg="curl" uci add_list opkg.custom.ipkg="diffutils" uci add_list opkg.custom.ipkg="dnsmasq-full" uci commit opkg # Check hotplug log logread -e hotplug # Upgrade packages opkg update opkg upgr
Automated
uclient-fetch -O opkg-extras.sh "https://openwrt.org/_export/code/docs/guide-user/advanced/opkg_extras?codeblock=0" . ./opkg-extras.sh