RedHat iTOps Tube

Monday, May 14, 2012

Checking for unused SlackBuilds

I wrote a little script to check for unneeded SlackBuilds on my system and thought I'd share it here. It works by checking each installed package with a _SBo tag to see if it is a dependency for any other installed SlackBuild package.



By default, the script just prints the list of the 'unneeded' packages to stdout. The commandline options are: -i (interactive) prompts for package deletion during the search; -p prompts for deletion after the search; -v runs in verbose mode, where you can see dependencies.



The script works by checking the README files for dependency info, so it is slow and can get tripped up by spelling mistakes or optional dependencies. It's not perfect, it works well enough.



You need to have sbopkg installed for this all to work. Obviously, package deletion only works if you run as root.




Code:


#!/bin/bash



# modified version of that found in removepkg

package_name()

{

    STRING=`basename $1`

    # If we don't do this, commands run later will take the '-' to be an option

    # and will destroy the package database.  Packages should not contain spaces

    # in them.  Normally this type of problem results from a command line typo.

    if [ "$(echo $STRING | cut -b 1)" = "-" ]; then

      STRING="malformed-package-name-detected"

    fi

    # Check for old style package name with one segment:

    if [ "$(echo $STRING | cut -f 1 -d -)" = "$(echo $STRING | cut -f 2 -d -)" ]; then

      echo $STRING

    else # has more than one dash delimited segment

      # Count number of segments:

      INDEX=1

      while [ ! "$(echo $STRING | cut -f $INDEX -d -)" = "" ]; do

        INDEX=$(expr $INDEX + 1)

      done

      INDEX=$(expr $INDEX - 1) # don't include the null value

      # If we don't have four segments, return the old-style (or out of spec) package name:

      if [ "$INDEX" = "2" -o "$INDEX" = "3" ]; then

        echo $STRING

      else # we have four or more segments, so we'll consider this a new-style name:

        NAME=$(expr $INDEX - 3)

        NAME="$(echo $STRING | cut -f 1-$NAME -d -)"

        echo $NAME

      fi

    fi

}



remove_pkg()

{

    if [ -n "$REMOVE_ALL" ]

    then

        INPUT="Y"

    else

        echo -en "33[0m: remove? (y)es/(n)o/(a)ll/(q)uit "

        read -n 1 INPUT

        INPUT=$(echo $INPUT | tr '[:lower:]' '[:upper:]')

    fi



    if [ "$INPUT" = "Q" ]

    then

        echo

        exit 0

    fi

    if [ "$INPUT" = "A" ]

    then

        REMOVE_ALL=true

    fi

    if [ "$INPUT" = "I" ]

    then

        unset INTERACTIVE

    fi

    if [ "$INPUT" = "Y" ]

    then

        /sbin/removepkg $1

    fi

}



set -e

source /etc/sbopkg/sbopkg.conf



LOGPATH=/var/log/packages

SBOPATH=$REPO_ROOT/SBo/$REPO_BRANCH

FLAGGED=""



for PARAM in "$@"

do

    if [ "$PARAM" = "-v" ]; then

        VERBOSE=true

    fi

    if [ "$PARAM" = "-p" ]; then

        PROMPT=true

    fi

    if [ "$PARAM" = "-i" ]; then

        INTERACTIVE=true

        unset PROMPT

    fi

    if [ "$PARAM" = "-h" ]; then

        echo -e "-i interactive (prompt for deletion after each package)\n-p prompt for deletion before exit\n-v verbose"

        exit 0

    fi

done



for FILENAME in $LOGPATH/*SBo

do

  PKGNAM="$(package_name $FILENAME)"

  if [ -n "$VERBOSE" ]; then

      echo -ne "33[0m$PKGNAM ... "

  fi

  HAS_DEPENDENCY=0

  HAS_INSTALLED_DEPENDENCY=0

  for MATCH in $(find $SBOPATH -name README -exec grep -wil $PKGNAM '{}' + )

  do

      DEPENDENCY=$(basename $(dirname $MATCH) )

      if [ "$PKGNAM" != "$DEPENDENCY" ]; then

          HAS_DEPENDENCY=1

          ls $LOGPATH/*SBo | grep -q $LOGPATH/$DEPENDENCY && HAS_INSTALLED_DEPENDENCY=1

          if [ "$?" -eq 0 ]; then

              if [ -n "$VERBOSE" ]; then

                  echo -en " 33[1;32m$DEPENDENCY "

              fi

          else

              if [ -n "$VERBOSE" ]; then

                  echo -en " 33[0m$DEPENDENCY "

              fi

          fi

      fi

  done



  if [ "$HAS_DEPENDENCY" -eq 1 ]; then

      if [ "$HAS_INSTALLED_DEPENDENCY" -eq 0 ]; then

          if [ -n "$VERBOSE" ]; then

              echo -en "33[1;31m ... not needed"

          else

              echo -en "33[0m$PKGNAM"

          fi



          if [ -n "$INTERACTIVE" ]; then

              if [ $(whoami) = "root" ]; then

                  remove_pkg $PKGNAM   

              fi

          fi



          if [ -z "$VERBOSE" ]; then

              echo

          fi



          FLAGGED="$FLAGGED $PKGNAM"

      fi

  fi



  if [ -n "$VERBOSE" ]; then

      echo

  fi

done



if [ -n "$VERBOSE" ]; then

    FLAGGED_COUNT=$(echo $FLAGGED | wc -w)

    echo -e "\n33[0mNumber of packages that can be removed: $FLAGGED_COUNT\n"

fi



if [ -z "$INTERACTIVE" -a -n "$PROMPT" ]; then

    if [ $(whoami) = "root" ]; then

        for PKGNAM in $FLAGGED

        do

            echo -en "33[0m$PKGNAM"

            remove_pkg $PKGNAM

            echo

        done

    else

        echo "Run as root to remove unneeded packages"

    fi

fi



exit 0