Clearing rpm cache ...

This script is intended to delete the rpm and delta files in /var/cache/zypp/packages if you keep these files locally. If you don’t know what it means, then you don’t need it, as RPM files caching is disable by default for all repositories.

The usage is simple (however that script was a piece of tiny and tricky bash programming). For those who might wonder, the magic key was sort -rV, that performs a sort of version numbers within text. Without this option, this script would have been significantly longer and more complicated. I wrote it a while ago but now that my file server is getting full, I had to test it and ended up rewriting it from scratch (as usual). It seems to be working … but you’ll use it - as always - at your own risk.

Here’s the code:


 #! /bin/bash
#: Title       : rpmcache
#: Date Created: Sat Aug 20 14:27:51 PDT 2011 
#: Last Edit   : Mon Jan  2 13:04:04 PST 2012
#: Author      : Agnelo de la Crotche (please_try_again)
#: Version     : 1.0
#: Description : delete rpm packages from zypper cache while keeping
#                a given number of versions (default is 2)
#: Usage       : rpmcache -l | -o | -d | -k | -D | -O [N]
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

# !!! comment out this line or set DEBUG to 0 to really delete rpms !!!
DEBUG=1

PKGDIR=/var/cache/zypp/packages
NumVer=2

TMPDIR=${TMPDIR:-/tmp}
PKGDIR_DEF=$(awk '/packagesdir *=/ { print $NF}' /etc/zypp/zypp.conf)
PKGDIR=${PKGDIR:-PKGDIR_DEF}
pkglst=$TMPDIR/pkg.lst
orplst=$TMPDIR/orp.lst
dellst=$TMPDIR/del.lst
keplst=$TMPDIR/kep.lst
pkgdel=$TMPDIR/pkgdel.sh
orpdel=$TMPDIR/orpdel.sh
spksed=$TMPDIR/spkg.sed
arch=$(uname -m)
Arch=${arch/i6/i[56]}

del="to delete"
kep="to keep"


# list all rpms
function lst_rpms {
echo "Processing list of rpms ${!1} ..."
lst=${1}lst ; lst=${!lst}
[ "$1" == "del" -o "$1" == "kep" ] && C=$NumVer || C=0
echo > $lst
for dir in $(find -L $PKGDIR -mindepth 2 -type d ! -empty -name "$Arch" -o -name "noarch" ) ; do
  ls -1 $dir | sed '/delta.rpm/d' | sed -f $spksed \
| awk '{ if ( $1 == P ) print "#", $1"-"$2 ; else print $1"-"$2 ; P=$1 }' \
| sed -e :a -e '$!N;s/
#/ /;ta' -e 'P;D' | sed 's/  / /g' \
| awk 'BEGIN { C='$C' } ; { if (NF > C) {for (i=C+1; i <= NF ; i++) print $i}}' \
| sed "s|^|$dir/|" | sort -Vr >> $lst
done
if [ "$1" == "del" -o "$1" == "kep" ] ; then
	find -L $PKGDIR -mindepth 2 -type f -name "*delta.rpm" >> $dellst
else
	sed -n 's/rpm-$/rpm/p' $lst > $orplst
	sed -i 's/rpm-$/rpm/' $lst
fi
}

# list installed packages and available rpms 
function lst_pkgs {
	echo "Looking for installed packages ..."
	zypper se -i -t package | awk '/^i/{ print "s/\\("$3"\\)-\\([0-9A-E]\\)/\\1 \\2/"} ; END {print "s/ \\(32bit\\)-/-\\1 /;s/ \\(.*\\) /-\\1 /"}' > $spksed
	echo "Processing file list ..."
	lst_rpms pkg
}

# delete rpms { 
function del_rpms {
	[ -f $1 ] || return
	sed -n 's|^/|rm -v /|p' $1 > $pkgdel
	echo "Deleting rpms ..."
	unalias rm 2>/dev/null
	$DEL $pkgdel
	rm $pkgdel
}

# display usage
function usage {
PRG=$(basename $0)
VER=$(awk '/^#: Version/ { print $NF }' $0)
cat << EOFUSAGE
$PRG $VER - lists/clears rpm packages cache.

Usage: $PRG [ -l | -k | -d | -D | -o | -O] [ N ]

    -l --list     list all rpm packages in cache
    -o --orphans  list rpms of not installed packages
    -d --delete   list rpm packages to be deleted
    -k --keep     list rpm packages to be kept
     N            Number of package versions to keep (default: 2)

    -D            delete older rpm packages (!)
    -O            delete rpms of non installed packages (!)
EOFUSAGE
}

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Script starts here. 

# check if we are root
[ $UID -eq 0 ] || exec echo "You have to run this script as root or sudo"

args=`getopt -q -u -o klodhOD -l keep,list,orphans,delete,help -- "$@"`
set -- $args

OPTS=(${args%--*})
ARGS=(${args##*--})

[ ${#OPTS[li]} -lt 1 ] && exec echo "Missing or invalid option"
[/li][ ${#OPTS[li]} -gt 1 ] && exec echo "Two many options"
[/li][ ${#ARGS[li]} -le 1 ] && n=${ARGS[0]} || exec echo "Two many arguments"
[/li]
NumVer=${n:-$NumVer}

[ "$1" == "-h" -o "$1" == "--help" ] && usage || lst_pkgs
[ "x$DEBUG" == "x1" ] && DEL=cat || DEL=sh

case $1 in
-l|--list) cat $pkglst ;;
-o|--orphans|-O) [ "$1" == "-O" ] && del_rpms $orplst || cat $orplst ;; 
-d|--delete|-D) lst_rpms del ; [ "$1" == "-D" ] && del_rpms $dellst || cat $dellst ;;
-k|--keep) lst_rpms kep ; diff $dellst $pkglst | sed -n 's/^> //p' ;;
esac

The script won’t delete files until you set DEBUG to 0 or comment out this line (in red in the code above). When DEBUG is set to 1, the script will only display the rm commands it would execute. By default, the script will keep the 2 latest versions of the packages. You can change this default by giving the number of versions you want to keep as argument. Only the packages for the local architecture (x86_64 or i[56]86) can be deleted as well as the “noarch” packages, and only the packages for the openSUSE version on which the script is executed. If you keep the packages on a file server and symlink /var/cache/zypp/packages (so do I), you’ll have to run the script on each version and on each architecture.

Usage:

rpmcache -l --list : list all the rpm packages
rpmcache -d --delete [N] : list the packages that would be deleted while keeping the N latest versions of the rpms.
rpmcache -k --keep [N] : list the packages that would be kept in cache while keeping the N latest versions of the rpms.
rpmcache -o --orphans : delete rpms of non installed packages only.

Only one option can be used (sorry , I could have combined -d and -o).
These options only display files and won’t delete anything (no matter the state of the DEBUG flag).
Obviously, merging the output of rpmcache --delete and rpmcache --keep should match the (sorted) output of rpmcache --list.

Now the destructive options (if DEBUG is commented out or set to 0):
rpmcache -D: delete the rpms but preserve the 2 latest versions.
rpmcache -D 1 : delete the rpms but preserve the latest version.
rpmcache -D 3 : delete the rpms but preserve the 3 latest versions.
rpmcache -D 0 : delete all the rpms ( preserving 0 latest version).
rpmcache -D N : delete the rpms but preserve the N latest versions.
rpmcache -O : delete “orphan” rpms, rpms still in cache for packages that are not installed (most likely because they have been deinstalled).

Delta files - if they are any - will be deleted in any case.

This script is not dangerous. It won’t harm your system. However the options -D and -O will delete files that you might not be able to get from anywhere. So these options are “destructive”. Use them with caution and after you make sure they’ll do what you want (that’s what the listing options are for).

to do:

One could add a list of packages that should never be deleted. Some people like to keep older versions of chromium or the nvidia driver for example, and it has be proven to be helpful in the past. I don’t need it yet. If you happen to need it now, you’re welcome to add this feature.