Linking programs and man pages in /opt to /usr/local/


Many users who have the packages from this web site installed on their systems as how they might make linkes from the /opt directories to /usr/local/bin, /usr/local/man, etc. This problem is discussed in Question 7 in the FAQ. Owen Birnie sent me the following instructions and shell script. Marek Krawus offered a modification to allow unlinking of individual packages and the flexibility to link in some place other that /usr/local.

Instructions

It's fairly simple to use. Calling it without any parameters will make it search through all the directories in /opt looking for /bin /sbin and /lib directories. If it finds any, it links them to a file of the same name in /usr/ local/[bin|sbin|lib]. You may want to use the individual install feature to be careful what you link.

You can install individual packages by giving the script the name of the package on the command line.

The only other option that there is is "clean" which simply removes the /usr/ local/* tree. (Disabled by default.)

Once, it's been run, it's a simple case of including /usr/local/bin, /usr/local/ sbin in your path and /usr/local/man in your MANPATH.

It does it's best to survive if there's a name clash, or a problem. The only two of concern I've come across are:

  1. If there is an empty sbin bin or lib in any /opt/* directory, it will produce a number of errors as it tries to link a wildcard.
  2. The script uses /usr/man/* to build /usr/local/man. I once came across a package that required a man8. It reported that ln couldn't create a file. The easiest way is to create /usr/man/man8.
Owen Birnie (A.S.B.), Xara Networks Ltd., UK, owen@xara.net.


Important Further comments (Steve C.):

  1. Save the script below to pkglink.sh. Make sure to make it executable with

    chmod +x pkglink.sh

  2. The output of pkglink.sh -h gives instructions:

    Owen's Package Linker:-
    Usage:-
    pkglink.sh -h        - Help - You're looking at it!
    pkglink.sh           - Install ALL packages from /opt/*.
    pkglink.sh clean     - Delete all links in /usr/local/ tree.
    (Disabled by default. Use at your own risk.) pkglink.sh package - Install package from /opt/package.

  3. BE VERY CAREFUL WITH

    pkglink.sh clean

    I have in fact disabled this in the script because of the potential to accidentally delete programs. This is useful only if you want to completely redo your /usr/local.

  4. If you want to use some directory other than /usr/local, it is fairly easy to change the script by changing DESTDIR.

#!/bin/sh 
# Package Manipulation Tool.
# Copyright, 1997, Xara Networks, Ltd.
# Written by Owen Birnie, 970321.  Modified by S. Christensen.

# Modified by Marek Krawus 20.5.97
# - DESTDIR is introduced
# - The package directory name must begin with a capital letter during the bulk installation,
#   see: wholeopt() procedure.
# - pkglink -r pkg_name : Delete links for pkg_name, see: unlink_file() procedure.

DESTDIR=/usr/local

# Uncomment this only if you really want to clean out /usr/local
# utterly.  Be very careful.

#cleanup()
#{
#  rm -rf $DESTDIR/bin
#  rm -rf $DESTDIR/sbin
#  rm -rf $DESTDIR/lib
#  rm -rf $DESTDIR/man
#  mkdir $DESTDIR/bin
#  mkdir $DESTDIR/sbin
#  mkdir $DESTDIR/lib
#  mkdir $DESTDIR/man
#  cd /usr/man
#  for manfile in man*
#  do
#    mkdir $DESTDIR/man/$manfile
#  done
#}

linkfile()
{
  if [ -d $1 ]
  then
    for file in $1/*
    do
      if [ -f $DESTDIR/$file ]
      then
        echo "$0 Warning: Name clash between $pkg/$file and`ls -goa $DESTDIR/$file | cut -d '>' -f 2`."
      elif [ -d $DESTDIR/$file ]
      then
        echo "$0 Warning: Sharing directories $pkg/$file and`ls -goa $DESTDIR/$file | cut -d '>' -f 2`."
      else
        ln -s $pkg/$file $DESTDIR/$file
      fi
#      echo "ln -s $pkg/$file $DESTDIR/$file"
    done
  fi
}

unlink_file()
{
   echo "Unlinking files of the package $1 ... \n"
   for folder in bin sbin lib man
   do
	/usr/bin/find $DESTDIR/$folder -ls | grep /opt/$1 | awk '{ print $11 }' | xargs -l -t rm
   done
}

dopackage()
{
  linkfile bin
  linkfile sbin
  linkfile lib
  if [ -d man ]
  then
    for manfile in man/man?*
    do
#	echo $manfile
      linkfile $manfile
    done
  fi
}

wholeopt()
{
  for pkg in /opt/*
  do
    echo $pkg
    case "`basename $pkg`" in
	[A-Z]*)
            echo "Installing for $pkg\n" 
            cd $pkg
	    dopackage
            ;;
        *)
            echo "$pkg is not a package\n" ;;
    esac
  done
}

if [ $# -eq 0 ]
then
  if [ ! -d $DESTDIR ]
  then
    mkdir $DESTDIR
  fi
  wholeopt
elif [ $1 = "clean" ]
then
  cleanup
elif [ $1 = "-h" ]
then
  echo "Owen's Package Linker:-"
  echo "Usage:-"
  echo "$0 -h           - Help - You're looking at it!"
  echo "$0              - Install ALL packages from /opt/*."
  echo "$0 -r pkg_name  - Delete links for pkg_name"
  echo "$0 clean        - Delete all links in $DESTDIR/ tree. (Disabled by default."
  echo "$0                Use at your own risk.)"
  echo "$0 pkg_name     - Install  from /opt/."
elif [ $1 = "-r" ]
then
  shift
  for each
  do
    cd $DESTDIR
    unlink_file $each
  done
else
  for each
  do
    if [ -d /opt/$each ]
    then
      pkg=/opt/$each
      cd $pkg
      dopackage
    else
      echo "$0 Error: Unable to search /opt/$each. Does not exist."
    fi
  done
fi

Contact Information
© Copyright 2011 Steven M. Christensen and Associates, Inc.
This page was last updated on January 1, 2011.