wajig: a simple command line interface to Debian package mgmt
I've been juggling the use of various Debian Package Management tools
over the years (including the likes of dselect, deity, deity-gtk,
aptitutde, apt-get, dpkg, gnome-apt, apt-cache, and so on).
I've written a shell script front-end which I call "wajig" to do some
of the common tasks I do in managing various Debian installations. I
include the script below in case others might find it useful or others
might give me wisdom on how to do some of these better. I would not
yet vouch for it's accuracy (in terms of identifying new and updated
packages)
WARNING: I suggest you review the code carefully to be sure for
yourself that I don't include any trojan horses. Currently I assume
the script is being run as root. Thus, someone with less scruples than
myself :-) could mislead you into running code as root that trashes
your system, or worse. Nonetheless, I've used this for quite a while
now and I've never trashed my system.
In brief I use it as follows:
# wajig update (update available list: apt-get update)
# wajig new (list new packages to Debian)
# wajig newupgrade (list upgradeable pkgs since update)
# wajig toupgrade (list all upgradeable pkgs)
# wajig install xmms (install the xmms package)
# wajig remove xmms
# wajig listfiles xmms (list files supplied by installed pkg)
# wajig whichpkg ppmmake (search Debian packages web page for
packages containing ppmmake. This one
lets me avoid going to the web page
to find information each time)
and many more, including upgrade, dist-upgrade, reconfigure,
repackage, source, clean, autoclean, status, describe, search.
Code is provided as is without warranty.
Finally, I've been using Debian for many years but am not an
officially registered Debian developer.
#!/bin/bash
#
# WAJIG: Debian Package Management Front End
#
# Remembering all the different commands to get different
# information about different aspects of Debian package management and
# then using other commands to install and remove packages
# was all becoming too much for me.
#
# Swaping between dselect, deity, deity-gtk, aptitutde, apt-get, dpkg,
# gnome-apt, apt-cache, and so on was interesting but cumbersome.
#
# This script simply collects together what I have learnt about
# various commands! Clearly I have yet to learn all there is.
# Also, this script is a bit of a hack, and many things could surely be
# done better. I find it useful and in case others do I release it.
#
# Suggestions are most welcome. Email Graham.Williams@cmis.csiro.au.
#
# Currently it only runs as root which needs to be rectified.
# Perhaps using fakeroot or sudo when (and only when) it is required.
#
# Copyright (c) 2001 Graham Williams, Kayon Toga.
#
# Code is provided as is without warranty.
#
# Released under the GNU General Public License.
self=$(basename $0)
init_dir=/root/.wajig
scratch_dir=${init_dir}
avail_now=${init_dir}/pkg.available
avail_tmp=${init_dir}/pkg.available.tmp
avail_prev=${init_dir}/pkg.available.prev
install_now=${init_dir}/pkg.installed
function usage ()
{
echo "Usage: ${self} [-h|--help] <command> [<args>]"
echo ""
echo " init Initialise the internal archives"
echo " reset Reset the internal archives"
echo ""
echo " update Update the list of available packages"
echo " upgrade Upgrade all installed pacakges"
echo " dist-upgrade Upgrade to a new distribution"
echo " install <packages> Install package from net"
echo " installdeb <deb> Install package from a .deb file"
echo " force <packages>"
echo " reconfigure <packages>"
echo " repackage <package> Generate .deb from installed package"
echo " remove <packages>"
echo " source <packages> Retrieve package source from net"
echo ""
echo " clean Remove all cached apt-get files"
echo " autoclean Remove old cached apt-get files"
echo ""
echo " status [<pattern>]"
echo " version [<pattern>]"
echo " available <packages> List versions of given packages"
echo " describe <packages>"
echo " description <packages>"
echo " fulldescription <packages>"
echo " orphans [<packages>]"
echo ""
echo " list"
echo " listnames [<pattern>]"
echo " listfiles <package>"
echo " search <pattern>"
echo " whichpkg <pattern> Search for file in a package"
echo ""
echo " toinstall"
echo " topurge"
echo " toupgrade List packages with newer versions available"
echo " newupgrade"
echo " new List new packages since last update"
echo ""
echo " findfile <string>"
}
function update.available ()
{
#
# Generate current list of available packages, backing up the old list.
#
if [ ! -e ${avail_now} ]; then
touch ${avail_now}
fi
mv -f ${avail_now} ${avail_tmp} 2>/dev/null
apt-cache dumpavail |
egrep '^(Package|Version):' |
awk '
/^Package: / {pkg=$2}
/^Version: / {print pkg,$2}
' > ${avail_now}
mv -f ${avail_tmp} ${avail_prev}
printf "There are $(wc -l ${avail_now} | awk '{print $1}') packages now "
printf "available compared to $(wc -l ${avail_prev} | awk '{print $1}') "
printf "previously.\n"
}
function update.installed ()
{
# Generate current list of installed packages.
if [ ! -e ${install_now} ]; then
touch ${install_now}
fi
cat /var/lib/dpkg/status |
egrep '^(Package|Status|Version):' |
awk '
/^Package: / {pkg=$2}
/^Status: / {s1=$2;s2=$3;s3=$4}
/^Version: / {print pkg,$2,s1,s2,s3}
' |
grep " install ok installed" |
awk '{print $1,$2}' | sort > ${install_now}
echo "There are $(wc -l ${install_now} | awk '{print $1}') packages installed."
}
#
# Initialise the cache.
#
if [ ! -e ${avail_now} -o ! -e ${avail_prev} -o \
! -e ${install_now} -o ! -d ${init_dir} ]; then
if [ "$1" = "init" ]; then
rm -f ${avail_now} ${avail_prev} ${install_now}
if [ ! -d ${init_dir} ]; then
mkdir ${init_dir}
fi
update.available
update.installed
cp ${avail_now} ${avail_prev}
else
printf "*******************************************************************
Welcome to the ${self} Debain Package Information Toolkit
\tPlease initialise first with: ${self} init
\tThis will simply generate available and install lists that
\treflect the current status of the installation.
\tThis toolkit is intended to be run as root only (currently)
\tEventually it will be able to be run as any user and will use
\tsudo or fakeroot as appropriate.
\tCached information files are stored in ${init_dir}
*******************************************************************
"
fi
exit 0
fi
#
# Process command line options
#
case "$1" in
--help|-h)
usage
exit 0
;;
-*)
echo -n "${self}: Error: "
echo "Unrecognised option: $1"
usage
exit 1
;;
esac
#
# Perform the requested action
#
case "$1" in
autoclean)
if [ $# -gt 1 ]; then
shift
echo -n "${self}: Error: "
echo "$1 requires no further arguments: $*"
exit 1
fi
apt-get autoclean
;;
available)
if [ $# -eq 1 ]; then
echo -n "${self}: Error: "
echo "$1 requires a list of packages"
exit 1
fi
shift
echo "Package Available Installed"
echo "===================================================================="
for package in $*; do
join -a 1 -a 2 ${avail_now} ${install_now} |
egrep "^${package} " |
awk '{printf("%-20s\t%-20s\t%-20s\n", $1, $2, $3)}'
done
;;
clean)
if [ $# -gt 1 ]; then
shift
echo -n "${self}: Error: "
echo "$1 requires no further arguments: $*"
exit 1
fi
apt-get clean
;;
describe)
if [ $# -eq 1 ]; then
echo -n "${self}: Error: "
echo "$1 requires a list of packages"
exit 1
fi
shift
dpkg --status $* |
awk '
/^Package:/ {printf("%-20s ",$2)}
/^Description:/ {print}' |
sed 's|Description:||'
;;
description)
if [ $# -eq 1 ]; then
echo -n "${self}: Error: "
echo "$1 requires a list of packages"
exit 1
fi
shift
for package in $*; do
apt-cache dumpavail |
awk -v package=$package '
BEGIN {found=0}
/^Package: / {if ($2 == package) {found=1;printf("%s:", $2);next}
if (found==1) {print "";found=0;next}
}
found==0 {next}
/^Description: / {print}
/^ / {print}' |
sed 's|Description:||'
done
;;
dist-upgrade)
if [ $# -gt 1 ]; then
shift
echo -n "${self}: Error: "
echo "$1 requires no further arguments: $*"
exit 1
fi
apt-get dist-upgrade
update.installed
;;
findfile)
shift
dpkg --search $1
;;
fulldescription)
if [ $# -eq 1 ]; then
echo -n "${self}: Error: "
echo "$1 requires a list of packages"
exit 1
fi
shift
apt-cache show $*
;;
force)
if [ $# -eq 1 ]; then
echo -n "${self}: Error: "
echo "$1 requires a list of packages"
exit 1
fi
shift
dpkg --install --force overwrite $(ls /var/cache/apt/archives/$** | sort | tail -1)
update.installed
;;
init|reset)
rm -f ${avail_now} ${avail_prev} ${install_now}
update.available
update.installed
cp ${avail_now} ${avail_prev}
;;
install)
if [ $# -eq 1 ]; then
echo -n "${self}: Error: "
echo "$1 requires a list of packages"
exit 1
fi
shift
apt-get install $*
update.installed
;;
installdeb)
if [ $# -eq 1 ]; then
echo -n "${self}: Error: "
echo "$1 requires the deb file to be installed"
exit 1
fi
shift
dpkg --install $1
update.installed
;;
list)
shift
dpkg -l '*'
;;
listnames)
if [ $# -eq 1 ]; then
shift
apt-cache pkgnames | sort
else
shift
apt-cache pkgnames | grep $1 | sort
fi
;;
listfiles)
shift
dpkg --listfiles $1
;;
new)
#
# List packages that have appeared since last update.
#
if [ $# -gt 1 ]; then
shift
echo -n "${self}: Error: "
echo "$1 requires no further arguments: $*"
exit 1
fi
join -v 1 -a 2 ${avail_prev} ${avail_now}
;;
newupgrade)
#
# Identify packages that have a newer version now available
# as compared to prior to the update.
#
if [ $# -gt 1 ]; then
shift
echo -n "${self}: Error: "
echo "$1 requires no further arguments: $*"
exit 1
fi
echo "Package Available Installed"
echo "===================================================================="
join -a 1 -a 2 ${avail_now} ${install_now} |
awk 'NF==3 && $2 != $3 {print}' > ${init_dir}/pkg.tmp1
join -a 1 -a 2 ${avail_prev} ${install_now} |
awk 'NF==3 && $2 != $3 {print}' > ${init_dir}/pkg.tmp2
join ${init_dir}/pkg.tmp1 ${init_dir}/pkg.tmp2 |
awk 'NF==5 && $2 != $4 {printf("%-20s\t%-20s\t%-20s\n", $1, $2, $3)}' >\
${init_dir}/pkg.tmp3
join -a 1 -v 2 ${init_dir}/pkg.tmp1 ${init_dir}/pkg.tmp2 |
awk '{printf("%-20s\t%-20s\t%-20s\n", $1, $2, $3)}' >>\
${init_dir}/pkg.tmp3
cat ${init_dir}/pkg.tmp3 | sort
rm -f ${init_dir}/pkg.tmp?
;;
orphans)
#
# List those libraries that are not required by any other installed package
#
shift
deborphan $*
;;
reconfigure)
shift
dpkg-reconfigure $*
;;
remove)
if [ $# -eq 1 ]; then
echo -n "${self}: Error: "
echo "$1 requires a list of packages"
exit 1
fi
shift
apt-get remove $*
update.installed
;;
repackage)
shift
dpkg-repack $1
;;
search)
shift
apt-cache search $*
;;
source)
if [ $# -eq 1 ]; then
echo -n "${self}: Error: "
echo "Please identify the packages you require sources for"
exit 1
fi
shift
apt-get source $*
;;
status|version)
shift
dpkg --list $*
;;
toinstall)
echo "Packages marked to be installed but not yet installed:"
echo "===================================================================="
shift
dpkg -l | head -5
dpkg -l '*' | grep "^i[^i]"
;;
topurge)
echo "Packages marked to be purged but currently installed:"
echo "===================================================================="
shift
dpkg -l '*' | grep "^pi"
;;
toupgrade)
#
# Find packages that have an Available version more recent than Installed
#
if [ $# -gt 1 ]; then
shift
echo -n "${self}: Error: "
echo "$1 requires no further arguments: $*"
exit 1
fi
echo "Package Available Installed"
echo "===================================================================="
join -a 1 -a 2 ${avail_now} ${install_now} |
awk 'NF==3 && $2 != $3 {printf("%-20s\t%-20s\t%-20s\n", $1, $2, $3)}'
;;
upgrade)
if [ $# -gt 1 ]; then
shift
echo -n "${self}: Error: "
echo "$1 requires no further arguments: $*"
exit 1
fi
apt-get upgrade
update.installed
;;
update)
if [ $# -gt 1 ]; then
shift
echo -n "${self}: Error: "
echo "$1 requires no further arguments: $*"
exit 1
fi
apt-get update
printf "Update: "
update.available
;;
whichpkg)
if [ $# -ne 2 ]; then
echo -n "${self}: Error: "
echo "$1 requires a name to look for"
exit 1
fi
shift
if ping -c 1 packages.debian.org 2>&1 >/dev/null; then
results=${scratch_dir}/search.results
wget --output-document=${results} http://packages.debian.org/cgi-bin/search_contents.pl\?word=$1\&case=insensitive\&version=unstable\&arch=i386\&directories=yes 2> /dev/null
cat ${results} |
egrep -v '^<|^$|^Packages search page' |
perl -p -e 's|<[^>]*>||g;s|<[^>]*$||g;s|^[^<]*>||g'
else
printf "${self}: Error: $1: Debian packages host not available.\n"
exit 1
fi
;;
*)
echo "${self}: unrecognised command. Type ${self} --help for information."
usage
exit 1
;;
esac
Reply to: