Skip to content

Instantly share code, notes, and snippets.

@alfredkrohmer
Created February 11, 2017 13:39
Show Gist options
  • Star 27 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save alfredkrohmer/8d4c2a5ab62e690772f3d9de5ad2d978 to your computer and use it in GitHub Desktop.
Save alfredkrohmer/8d4c2a5ab62e690772f3d9de5ad2d978 to your computer and use it in GitHub Desktop.
List all user-installed packages on OpenWrt / LEDE
#!/bin/sh
FLASH_TIME=$(opkg info busybox | grep '^Installed-Time: ')
for i in $(opkg list-installed | cut -d' ' -f1)
do
if [ "$(opkg info $i | grep '^Installed-Time: ')" != "$FLASH_TIME" ]
then
echo $i
fi
done
@starcms
Copy link

starcms commented May 16, 2017

Awesome! Thank you!!

@gacallea
Copy link

gacallea commented Jun 26, 2017

found this via @Fiver55 on openwrt forum. if you use opkg status and awk it runs in a flash. here's a mock script:

#!/bin/sh

## thread: https://forum.openwrt.org/viewtopic.php?id=42739
## source: https://gist.github.com/devkid/8d4c2a5ab62e690772f3d9de5ad2d978

FLASH_TIME=$(opkg status busybox | awk '/Installed-Time/ {print $2}')
LIST_INSTALLED=$(opkg list-installed | awk '{print $1}')

PACKAGES_2_INSTALL="/tmp/pack2install.txt"
SYSTEM_INSTALLED="/tmp/installedwithsystem.txt"

if [ -e "$PACKAGES_2_INSTALL" ]; then
	rm -f "$PACKAGES_2_INSTALL"
	touch "$PACKAGES_2_INSTALL"
else
	touch "$PACKAGES_2_INSTALL"
fi

if [ -e "$SYSTEM_INSTALLED" ]; then
	rm -f "$SYSTEM_INSTALLED"
	touch "$SYSTEM_INSTALLED"
else
	touch "$SYSTEM_INSTALLED"
fi

echo
echo "Getting a list of the current manually installed packages (this may take a minute or two):"
echo
for i in $LIST_INSTALLED; do
	if [ "$(opkg status $i | awk '/Installed-Time:/ {print $2}')" != "$FLASH_TIME" ]; then
		echo $i | tee -a "$PACKAGES_2_INSTALL"
	else
		echo $i >> "$SYSTEM_INSTALLED"
	fi
done

echo
echo "The list of current MANUALLY installed packages ready at: \"$PACKAGES_2_INSTALL\""
echo
echo "Just to make sure, a list of packages installed by the SYSTEM at FLASH TIME is ready at: \"$SYSTEM_INSTALLED\""
echo

exit 0

cheers :)

@ejona86
Copy link

ejona86 commented Oct 7, 2017

https://gist.github.com/ejona86/26974041ebbb3bf6602bd1bee0f92860

Faster, more reliable, and fewer false positives (but longer):

#!/bin/sh
FLASH_TIME="$(awk '
$1 == "Installed-Time:" && ($2 < OLDEST || OLDEST=="") {
  OLDEST=$2
}
END {
  print OLDEST
}
' /usr/lib/opkg/status)"

awk -v FT="$FLASH_TIME" '
$1 == "Package:" {
  PKG=$2
  USR=""
}
$1 == "Status:" && $3 ~ "user" {
  USR=1
}
$1 == "Installed-Time:" && USR && $2 != FT {
  print PKG
}
' /usr/lib/opkg/status | sort

Getting FLASH_TIME is shorter with grep ^Installed-Time: /usr/lib/opkg/status | cut -d " " -f 2 | sort -n | head -n 1, but I chose to just use awk.

@muxator
Copy link

muxator commented Oct 21, 2017

That's way faster, @ejona86. A fraction of a second versus multiple seconds. Great

@guymarc
Copy link

guymarc commented Jul 25, 2018

Hello

For me, none of these scripts work.

I noticed that a few of my packages have exactly the same installed time, so busybox would be the only package excluded from the output list.

I build my images with image builder in a "slow" VM.
I think installed time is not the flash time, but the install time during the build process of the image.

I found a workaround by reducing the precision of the install time value.
`#!/bin/sh

PRECISION=6

trunk_time () {
PKGTIME=$(opkg info "$1" | grep '^Installed-Time: ' | cut -f2 -d ' ')
PKGTIME=${PKGTIME:0:$2}
return
}

trunk_time busybox $PRECISION && BUILD_TIME=$PKGTIME

for i in $(opkg list-installed | cut -d' ' -f1)
do
trunk_time $i $PRECISION
if [ "$PKGTIME" != "$BUILD_TIME" ]
then
echo $i
fi
done
`
Understanding these scripts look to be correct for many, do I miss something?

@guymarc
Copy link

guymarc commented Jul 25, 2018

Sorry but seems like I donot know how to insert code in my message

@abrahamtamayo
Copy link

Oh .. Many Tnxs .. I took care about whats programs installed, wrote at a list .. but is possible I missed something in the way .. it's is very useful ..

@tinxx
Copy link

tinxx commented Feb 19, 2021

Yet another variant:

DISTRI_TIME=$(grep Installed-Time /usr/lib/opkg/status | sort | head -n1)

while read -r line; do
  case "$line" in
    "Package: "*)
        package="$line"
        _skip=false;;
    "${DISTRI_TIME}")
        _skip=true;;
    "Auto-Installed: yes")
        _skip=true;;
    "") # Empty line delimenates individual package blocks
        [ "$_skip" = true ] || echo "$package" | awk '{print $2}';;
  esac
done < /usr/lib/opkg/status | sort

Cheers!

@don-coleman
Copy link

And yet another variant. This one produces a more accurate/minimal list, as it also skips all dependents of other packages. It's based on bash, as it uses associative arrays.

https://gist.github.com/don-coleman/2218210aec58986acc80467f9a15d42b

@ZWx4
Copy link

ZWx4 commented Apr 20, 2021

Thanks @guymarc! Your script is the only one that worked for me. The other scripts here just list every single package installed. Maybe it is that way because I also used the Image Builder.

@rafalfitt
Copy link

as someone suggested on https://www.sindastra.de/p/1213/list-user-installed-packages-in-openwrt

You can update busybox via opkg update, so it’s install time can be wrong as reference.
As a result you will have wrong list.
Only one thing you cannot install via opkg is kernel – because you update it over flashing new firmware.
So the kernel’s install time should be used as flash time.
FLASH_TIME=$(opkg info kernel | grep ‘^Installed-Time: ‘)

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