#!/bin/bash # This script was developed by Mark Tompsett # That nasty grep expression # "/usr/\(\(lib\|share\)/perl5\|\(lib\|share\)/perl/[0-9.]*\)/$FILE2FIND" # care of Robin Sheat # Special thanks to Jared Camins-Esakov for testing, and suggesting # parameter requirements. # # (c) 2012 by Mark Tompsett # Released under GPL v2 or later # Grab the license from www.fsf.org # # 2012-07-26 MLT Added usage() function. # Wrote parameter checking code. # Started integration, but didn't finish. # 2012-07-26 MLT Expanded # - more parameters (file) # - more outputs (.all, .missing and .fix) # - more comments # - Changelog # - More credits and TO DO added. # 2012-07-2X MLT Created # # TO DO: # - change parameters to include: # --koha-dir=: to allow script to be in another location, but # still be able to find koha_perl_deps.pl # --list-dir=: this would mean a specific source.list file would be # used, so that an UBUNTU 10.10 LTS one could be # tested under DEBIAN. # --dist=: debian, ubuntu, etc. Should match 'lsb_release -i' # --release=: 10.10, 12.04, 6.0.5, etc. Should match 'lsb_release -r' # these would match both the apt-file sources.list # file and the install_misc/$DIST[.$VERSION].packages # file. Only need 6.0 for Debian system, get that # with an extra " ... | cut -f1-2 -d'.'". # file: used to generate .all, .missing, and .fix # if specified # full: used to limit output to everything (1), or just NOT FOUND (0) function usage { local tprogram=$1 echo "~:Usage: $tprogram [--koha-dir=] [--list-dir=] " echo "~: [--dist=] [--release=] " echo "~: [--file=] [--full=]" echo "~:" echo "~:koha-dir: The directory in which koha_perl_deps.pl is located." echo "~: the default is \`dirname $tprogram\`." echo "~:list-dir: If you wish to use a specific source.list file" echo "~: you will need to specify the directory it is in." echo "~: dist: This serves a dual role. Firstly, it is used to calculate" echo "~: the name of the source.list file, but also to determine" echo "~: which .packages file should be compared against in the" echo "~: install_misc directory under the koha directory." echo "~: This should be specified along with the release parameter." echo "~: release: This is the version number of the distribution of" echo "~: linux being used. It serves the same dual purpose." echo "~: Sample valid values: 10.04, 12.04, 6.0.5" echo "~: The Debian value of 6.0.5 will be truncated to 6.0 solely." echo "~: This should be specified along with the dist parameter." echo "~: file: If you wish to keep the output around after running the" echo "~: script, give a file name to store it in. There will be" echo "~: three suffixes appended:" echo "~: 1) .all - This is all the libraries it did find." echo "~: 2) .fix - These are the libraries missing from the" echo "~: .packages file." echo "~: 3) .missing - This is lists libraries not found at all." echo "~: This means they should be added to the" echo "~: koha-community repositories." echo "~: It's worthy of a bug report." echo "~: full: Can be 0 or 1. For verbose output use 1. To just list" echo "~: missing files (0), that is the type 3 from above, are" echo "~: listed to STDOUT." echo "~:" echo "~: sample output line for found library:" echo "~: Net::Z3950::ZOOM ~ libnet-z3950-zoom-perl: /usr/lib/perl5/Net/Z3950/ZOOM.pm" echo "~:" echo "~: sample output line for library that doesn't exist:" echo "~: {library name} NOT FOUND!" echo "~:" echo "~: In the bizarre case that there is more than one possibility: " echo "~: GD ~: libgd-gd2-noxpm-perl: /usr/lib/perl5/GD.pm" echo "~: ~: libgd-gd2-perl: /usr/lib/perl5/GD.pm" echo "~: GD is currently the only case, and so has a special exception." echo "~: If you find a new special case, please bug report it at" echo "~: http://bugs.koha-community.org/bugzilla3" echo "~:" echo "~: Sample uses: $prog | grep 'NOT FOUND'" echo "~: Find libraries which aren't in any repository." echo "~: If you see {library name}, the parameters are wrong." echo "~:" echo "~: Sample uses: $prog | grep '~' | cut -f2- -d'~' | cut -f1 -d':'" echo "~: Find libraries which can be 'apt-get install'd" exit $tretval } # define some constants SPACE=" " TAB=" " EQUALS="=" # define some defaults KOHADIR=`dirname $0` LISTDIR="/etc/apt" DISTRIBUTION=`lsb_release -i | cut -f2 -d":" | tr -d "$SPACE" | tr -d "$TAB"` RELEASE=`lsb_release -r | cut -f2 -d":" | tr -d "$SPACE" | tr -d "$TAB"` OUTFILE="" FULL=1 np=$# program=$0 count=0 count=$(($count+1)) while [ ! "$count" -gt "$np" ]; do # echo -n "Parameter #$count: ($1) - " if [[ "$1" =~ "$EQUALS" ]]; then EQPOS=`expr index "$1" "$EQUALS"` PARM=${1:0:$(($EQPOS-1))} VAL=${1:$EQPOS} PARM=`echo "$PARM" | tr [:upper:] [:lower:]` if [ "$PARM" == "--koha-dir" ]; then KOHADIR=$VAL if [ ! -d $KOHADIR ]; then echo "~: Specified Koha directory does not exist!" usage $program fi elif [ "$PARM" == "--list-dir" ]; then LISTDIR=$VAL if [ ! -d $LISTDIR ]; then echo "~: Specified sources.list directory does not exist!" usage $program fi elif [ "$PARM" == "--dist" ]; then DISTRIBUTION=`echo $VAL | tr [:upper:] [:lower:]` if [[ ! "$DISTRIBUTION" =~ ^[a-z]+$ ]]; then echo "~: Distribution name ($DISTRIBUTION) is invalid!" usage $program fi elif [ "$PARM" == "--release" ]; then RELEASE=$VAL if [[ "$RELEASE" =~ [0-9]+.[0-9]+ ]]; then RELEASE=`echo $RELEASE | cut -f1-2 -d'.'` else echo "~: Release number is invalid!" usage $program fi elif [ "$PARM" == "--file" ]; then OUTFILE=$VAL elif [ "$PARM" == "--full" ]; then if [[ "${#VAL}" -eq "1" && "$VAL" =~ [01] ]]; then FULL=$VAL else echo "~: Invalid value for the full parameter!" usage $program fi else echo "~: Invalid parameter passed!" usage $program fi else echo "~: Invalid parameter passed!" usage $program fi shift count=$(($count+1)) done if [ "${#OUTFILE}" -gt "0" ]; then if [ -e "$OUTFILE.all" ]; then echo -n "~: $OUTFILE.all already exists. Overwrite? (y/N) " read ANSWER if [[ "${#ANSWER}" -eq "0" || ! "$ANSWER" =~ [yY] ]]; then echo "~: Aborting!" exit 1 fi fi if [ -e "$OUTFILE.fix" ]; then echo -n "~: $OUTFILE.fix already exists. Overwrite? (y/N) " read ANSWER if [[ "${#ANSWER}" -eq "0" || ! "$ANSWER" =~ [yY] ]]; then echo "~: Aborting!" exit 1 fi fi if [ -e "$OUTFILE.missing" ]; then echo -n "~: $OUTFILE.missing already exists. Overwrite? (y/N) " read ANSWER if [[ "${#ANSWER}" -eq "0" || ! "$ANSWER" =~ [yY] ]]; then echo "~: Aborting!" exit 1 fi fi fi #echo "KOHADIR: $KOHADIR" #echo "LISTDIR: $LISTDIR" #echo "DISTRIBUTION: $DISTRIBUTION" #echo "RELEASE: $RELEASE" #echo "FILEALL: $OUTFILE.all" #echo "FILEFIX: $OUTFILE.fix" #echo "FILEMISSING: $OUTFILE.missing" #echo "FULL: $FULL" np=$# prog=$0 # Inform user of requested file. if [ "${#OUTFILE}" -gt "0" ]; then echo "Storing missing perl libraries to '$OUTFILE.missing'" echo "Storing all perl libraries to '$OUTFILE.all'" fi # Inform user how this is running. if [ "$FULL" -eq "0" ]; then echo "Looking for only missing libraries." else echo "Listing all libraries." fi # Use a configurable variable instead of a pathless ./koha_perl_deps.pl KPD=$KOHADIR/koha_perl_deps.pl # Check that KPD exists. if [ ! -e $KPD ]; then echo "ERROR: Missing $KPD" echo "Consider using the --koha-dir= parameter." usage $program fi # This script uses apt-file to do it's dirty work. # sudo apt-get install apt-file # sudo apt-file update # And I think that's it. Just follow the instructions spewed out # while installing. CHKAPTFILE=`which apt-file | wc -l` if [ "$CHKAPTFILE" -eq "0" ]; then echo "Please install apt-file first before using this script." exit 1 fi # TMPFILE1 = Eventually, a list of perl libraries to locate. # TMPFILE2 = Constantly a temporary dump. # TMPFILE3 = A massive dump of every perl library that apt-file knows about # TMPFILE4 = A file listing the problem dependencies # TMPFILE5 = A file listing of all the dependencies, not as BLAH::BLAH # but as libblah-blah-perl. TMPFILE1=`mktemp` TMPFILE2=`mktemp` TMPFILE3=`mktemp` TMPFILE4=`mktemp` TMPFILE5=`mktemp` # Make giant dump of all the likely locations of the libraries if [ "$FULL" -eq "1" ]; then echo "Building File..." fi apt-file list perl > $TMPFILE3 RESULT=$? if [ "$RESULT" -ne "0" ]; then echo "Perhaps you didn't run 'apt-file update' yet?" rm $TMPFILE1 rm $TMPFILE2 rm $TMPFILE3 rm $TMPFILE4 rm $TMPFILE5 exit 1 fi # Determine where to chop the column # Don't know if the perl script will reformat in the future. if [ "$FULL" -eq "1" ]; then echo "Determining Width..." fi # Going to assume column order won't change, even if width does. $KPD -a | grep "^\s*Installed" > $TMPFILE1 WIDTH=`expr index "\`cat $TMPFILE1\`" "Installed"` WIDTH=$(($WIDTH - 1)) if [ "$FULL" -eq "1" ]; then echo "Using $WIDTH..." fi # Now get the file names. if [ "$FULL" -eq "1" ]; then echo "Listing Dependencies..." fi $KPD -a > $TMPFILE1 # only want the library names, that's why we figured out a width based # on that header line. cat $TMPFILE1 | cut -c1-$WIDTH | grep ^..*$ > $TMPFILE2 # And there are ----'s before and after, so we can trim header's and footer's cat $TMPFILE2 | perl -e '@data=; $t=0; foreach (@data) { if (/\-\-\-\-/) { $t=1-$t; } elsif ($t) { print $_; } }' > $TMPFILE1 # Now loop through the library to find. while read LIB2FIND; do # If we are outputing everything, say the library name. if [ "$FULL" -eq "1" ]; then echo -n "$LIB2FIND " fi # transform the library name into a directory path name FILE2FIND=`echo $LIB2FIND | perl -e '@data=; foreach (@data) { s/\:\:/\//g; s/ //g; chomp $_; print "$_.pm"; }'` # loop for it in the big file we dumped. grep "/usr/\(\(lib\|share\)/perl5\|\(lib\|share\)/perl/[0-9.]*\)/$FILE2FIND" $TMPFILE3 > $TMPFILE2 RESULT=$? # grep: 0 = found, 1 = not found, 2 = error if [ "$RESULT" -eq "1" ]; then # If we are only outputing missing files, then we haven't # said the library name yet. if [ "$FULL" -eq "0" ]; then echo -n "$LIB2FIND " fi echo "NOT FOUND!" # Store it in the missing libraries file. echo "$LIB2FIND" >> $TMPFILE4 elif [ "$RESULT" -gt "0" ]; then # Don't do anything filewise if the grep failed! echo "GREP ERROR!" else # if there are multiple lines and one of them is perl, perl-modules, # or perl-base, choose that one. LINES=`wc -l < $TMPFILE2` if [[ "$FULL" -eq "1" && "$LINES" -gt "1" ]]; then FOUND=0 while read LINE; do if [ "${LINE:0:5}" == "perl:" ]; then echo "~ $LINE" # Don't put perl in the $TMPFILE5 list! FOUND=1 elif [ "${LINE:0:13}" == "perl-modules:" ]; then echo "~ $LINE" # Don't put perl-modules in the $TMPFILE5 list! FOUND=1 elif [ "${LINE:0:10}" == "perl-base:" ]; then echo "~ $LINE" # Don't put perl-base in the $TMPFILE5 list! FOUND=1 fi done < <(cat $TMPFILE2) # If there wasn't a perl, per-modules, perl-base, then # it is unclear what to use! This currently affects GD. # For GD we'll choose the xpm version. if [[ "$FOUND" -eq "0" && "$FILE2FIND" == "GD.pm" ]]; then RECHECK=`grep -v noxpm $TMPFILE2 | wc -l` LINE=`grep -v noxpm $TMPFILE2` if [[ "${#RECHECK}" -gt "0" && "$RECHECK" -eq "1" ]]; then echo "~ $LINE" echo "$LINE" >> $TMPFILE5 else while read LINE; do # use ~: so that any greps trying to delimit the left # and right will not get any library name. # THIS MAY BE BAD LOGIC. echo "~: $LINE" # Because this is a messy case, don't put it # into the $TMPFILE5 list. done < <(cat $TMPFILE2) fi elif [ "$FOUND" -eq "0" ]; then while read LINE; do # use ~: so that any greps trying to delimit the left # and right will not get any library name. # THIS MAY BE BAD LOGIC. echo "~: $LINE" # Because this is a messy case, don't put it # into the $TMPFILE5 list. done < <(cat $TMPFILE2) fi # Otherwise there's just one line, so dump it if we need to. elif [ "$FULL" -eq "1" ]; then echo -n "~ " cat $TMPFILE2 cat $TMPFILE2 >> $TMPFILE5 fi fi done < <(cat $TMPFILE1) # We should check to see if the all libraries list has things which # are not in the {OS}.{version}.packages list. DIST=`lsb_release -i | cut -f2- -d':' | tr [:upper:] [:lower:]` DIST=`echo $DIST | tr -d ' ' | tr -d ' '` VER=`lsb_release -r | cut -f2- -d':'` VER=`echo $VER | tr -d ' ' | tr -d ' '` FILE2CHECK="install_misc/$DIST.$VER.packages" # if we can't find a version'd one, fall back to the default one. if [ ! -e $FILE2CHECK ]; then FILE2CHECK="install_misc/$DIST.packages" fi # Check to see if the $FILE2CHECK exists. # If not, we can't do any file comparing. if [ ! -e $FILE2CHECK ]; then echo "Unable to determine which $DIST .packages file to check!" rm $TMPFILE5 # Otherwise, we can see what we might need to append to it. else echo "Checking $FILE2CHECK for missing perl libraries" # We only want the library names, not the actual full file path part. # grab the library names, sort uniquely, remove blank line # then make sure we don't have perl, perl-modules, and perl-base. # Put the results to "$OUTFILE.all" cat $TMPFILE5 | cut -f1 -d':' | sort -u | grep ^..*$ > "$OUTFILE.all" cat "$OUTFILE.all" | grep -v "^perl$" | grep -v "^perl-modules$" > $TMPFILE5 cat $TMPFILE5 | grep -v "^perl-base$" > "$OUTFILE.all" rm $TMPFILE5 while read LIBRARY; do RESULT=`grep "$LIBRARY\s*[iI][nN][sS][tT][aA][lL][lL]" $FILE2CHECK` if [ "${#RESULT}" -eq "0" ]; then # it did not found it. echo "$FILE2CHECK is missing $LIBRARY." echo "$LIBRARY install" >> "$OUTFILE.fix" fi done < <(cat "$OUTFILE.all") fi # we can safely delete our Blah::BLAH library list, # the temporary grep file and the mega apt-file dump rm $TMPFILE1 rm $TMPFILE2 rm $TMPFILE3 # If the user specified an out file, then move the temporary files if [ "${#OUTFILE}" -gt "0" ]; then mv $TMPFILE4 "$OUTFILE.missing" # Otherwise delete them else rm $TMPFILE4 fi