for a pretty copy see http://www.enteract.com/~rslomkow/distrib/distrib.html
This is a system I developed that I thought I would share with the the world
as it is a very helpfull way of keeping your system in order. I personally
had lots of trouble tracking software version on my linux box. The script at
the end is in perl because shell script was too slow and it was simple and
easy to just write.
The Distrib System
This article is to discuss a method of distributing software for a small to
moderate sized organizations to keep your software versions under control.
The core idea is that software should be in discrete identifiable bundles,
that can be identified by version, yet are still convenient to add to user
paths and easy to find current version of software. It is furthermore
important that multiple version can co-exist on a system without
interfering with each other.
The traditional plan has been to install all locally compiled utilities in
/usr/local. Installing everything in /usr/local/ makes it impossible to
distinguish versions and to remove all components of a particular application
as they have been spread everywhere. Solaris has a pkg system that allows the
OS to keep a database of where all the files of a particular package are.
The Solaris pkg approach is difficult to write the pkg scripts, and does not
work well with having multiple version of something with the same name.
The Distrib idea is that you have a directory full of software packages named
the software packages name followed by the version number. Then you make a
series of symbolic links of all the files and sub-directories to /usr/local/
as that is the traditional place users look for local applications.
Here is an example and explanation.
Take a software package called myapp version 12.3.4. The first thing to do is
install the software into the package location. In a sys-5 system should be
installed in /opt/myapp-12.3.4 ( or in a BSD derivative perhaps
/usr/local/pkg/myapp-12.3.4 ). That directory you would have sub directories
as follows.
/opt/myapp-12.3.4/bin/
/opt/myapp-12.3.4/bin/myapp
/opt/myapp-12.3.4/bin/myapp-converter
/opt/myapp-12.3.4/lib/
/opt/myapp-12.3.4/lib/libmyapp.so
/opt/myapp-12.3.4/lib/myapp/libmyapp.cf
/opt/myapp-12.3.4/lib/myapp/libmyapp_defaults
/opt/myapp-12.3.4/man/
/opt/myapp-12.3.4/man/man1/
/opt/myapp-12.3.4/man/man1/myapp.1
/opt/myapp-12.3.4/man/man1m/
/opt/myapp-12.3.4/man/man1m/myappadmin.1m
/opt/myapp-12.3.4/sbin/
/opt/myapp-12.3.4/sbin/myappadmin
Now you have all of the parts of the application in one place with a name that
makes it easy to distinguish which version of the application is installed.
The next step is to create symbolic link to the /usr/local/ directory
structure so that users do not need to add /opt/myapp-12.3.4 to their paths to
have access to these tools.
The script distrib will create this parallel symbolic link directory structure
for you.
distrib /usr/local/ /opt/myapp-12.3.4/
Then you will now have real directories
/usr/local/bin/
/usr/local/lib/
/usr/local/man/
/usr/local/man/man1/
/usr/local/man/man1m/
/usr/local/sbin/
and these directories will contain symbolic links to the original
applications and files.
/usr/local/bin/myapp -> /opt/myapp-12.3.4/bin/myapp
/usr/local/bin/myapp-converter -> /opt/myapp-12.3.4/bin/myapp-converter
/usr/local/lib/libmyapp.so -> /opt/myapp-12.3.4/lib/libmyapp.so
/usr/local/lib/myapp/libmyapp.cf -> /opt/myapp-12.3.4/lib/myapp/libmyapp.cf
/usr/local/lib/myapp/libmyapp_defaults -> /opt/myapp-12.3.4/lib/myapp/libmyapp_defaults
/usr/local/man/man1/myapp.1 -> /opt/myapp-12.3.4/man/man1/myapp.1
/usr/local/man/man1m/myappadmin.1m -> /opt/myapp-12.3.4/man/man1m/myappadmin.1m
/usr/local/sbin/myappadmin -> /opt/myapp-12.3.4/sbin/myappadmin
Now if you decide to install myapp version 12.3.5, you can now identify which
version of it you had, you can easily remove the previous version and all of
its parts because it is on directory structure in /opt/, furthermore
if you just run
distrib /usr/local/ /opt/myapp-12.3.5/
you will replace all the symbolic links with the new version, and the old
version installed in /opt/myapp-12.3.4 if any of your users need it for there
applications if the new version is not fully backwards compatible. But in
/usr/local/ so most of your users are using the latest version without
having to change their environment.
/usr/local/bin/myapp -> /opt/myapp-12.3.4/bin/myapp
has been replaced by
/usr/local/bin/myapp -> /opt/myapp-12.3.5/bin/myapp
*note* the current distrib script will remove all symbolic links in /usr/local/
*note* but will not touch any real files when used in this way. The distrib
*note* script also has a -r for remove that will clean up all of that packages
*note* symbolic links of the source directory and it will remove empty dirs.
In conclusion the distrib method has given us a way to keep track of the
components of an application, given us a way make those components easily
accessible to users, and allows us to keep multiple versions of software.
Practical Considerations:
This takes additional time when installing software packages as you now need
to force them into the package directory. I use this system quite extensively
with third party applications and development tools, Cobol compilers for
Unix, third party object libraries such as roguewave, etc.. I untar the
software into a directory named the product hyphen the version name.
Programs with the GNU configure script you can give the
--prefix=/opt/application-version flag when you run configure. Also you can
modify makefiles, in cases where it is an extreme pain to compile, I have
installed under a userid install then do a
find /usr/local/ -user install -depth -print \ | cpio -pvdum
/opt/application-version
so it can now be easily kept track of and distributed to other systems.
I am offering this system to the UNIX admin community to be used and improved
upon. It is free, you may modify re-write use, sell your implementation.
Though I ask you do not sell the idea as your idea. And please contact me
with improved versions or conceptual improvements to the system.
Robin * Slomkowski
rslom...@enteract.com
-- the distrib script -- CUT - HERE --
#!/usr/local/bin/perl
#
# Robin * Slomkowski
# Wed May 21 09:03:38 CDT 1997
# This is distrib Versiion 2.1
#
# USAGE: distrib [-(v|r)] destination_dir [source_dir]
#
# -v is verbose mode that has additional error messages from
# the system. -r is reverse mode, and it will take away everything
# that is a link of the source_directory. The script defaults to
# using the user's current directory as the source from wich to link.
#
# This is a re-write of an earlier script by the same name. It is
# deseigned to aide in revision control. It will safely and effectivly
# generate a parrellel structure of real directories and symbolic links
# in a place of your choice.
# Example you have /opt/myapp-12.34.56 with lib, bin, man
# subdirectories. with distrib you could create /usr/local/ bin lib
# man that will contain symbolic links to all the originals so your
# users don't have to have complicated paths.
#
# When going forward it will unlink any existing symbolic links in its
# destination, but if it is anything other than a symbolic link it will
# just leave it.
#
# When removeing it will only remove links that connect to the source
# from which you are removing, it also will only remove empty
# directories.
#
# defaults
#
$MODE = "FORWARD" ;
$VERBOSE = "FALSE" ;
$SOURCE_DIR = $ENV{PWD} ;
$USAGE_MSG = "USAGE: distrib [-(r|v)] destination_dir [source_dir]\n" ;
#
# Define some subroutines
#
sub usage_error {
print "$USAGE_MSG" ;
exit 1 ;
if ( -l $_[1] ) {
if ( $VERBOSE eq "TRUE" ) {
print "UNLINKING $_[1] and replacing \n" ;
}
unlink "$_[1]" ;
}
if ( ( -e $_[1] ) && ( $VERBOSE eq "TRUE" ) ) {
print "FILE $_[1] exist can't place link there\n" ;
}
else {
symlink $_[0] , $_[1] ;
}
if ( -l $_[1] ){
if ( "$_[0]" eq readlink("$_[1]") ) {
unlink $_[1] ;
}
}
else {
if ( ( -e $_[1] ) && ( $VERBOSE eq "TRUE" ) ) {
print "UNLINK: $_[1] is not a symbolic link \n" ;
}
}
unless ( -e "$_[0]" ) {
mkdir "$_[0]" , 511 ;
}
else {
if ( $VERBOSE eq "TRUE" ) {
print "MKDIR: $_[0] exists, will use existing dir\n"
}
}
local ( @LINKDIR ) ;
opendir LINKDIR , "$_[0]" ;
if ( -e "$_[0]" ) {
@LINK_DIR = readdir LINKDIR ;
close LINKDIR ;
splice @LINK_DIR , 0 , 2 ;
if ( $#LINK_DIR < 0 ) {
if ( $VERBOSE eq "TRUE" ) {
print "$_[0] is empty, cleaning up\n" ;
}
rmdir "$_[0]" ;
}
}
local ( @DIR_LIST , @FILES , $BASE_NAME , $ENTRY , $OUTPUT ) ;
$BASE_NAME = "$_[0]" ;
if ( -d $BASE_NAME ) {
opendir DIR , "$BASE_NAME" ;
@DIR_LIST = readdir DIR ;
splice @DIR_LIST , 0 , 2 ;
foreach $ENTRY ( @DIR_LIST ) {
unless ( -d "$BASE_NAME/$ENTRY" ) {
push @FILES , "$ENTRY" ;
}
}
return @FILES ;
}
else {
if ( $VERBOSE eq "TRUE" ) {
print "ERROR: $BASE_NAME not a directory\n" ;
}
}
local ( @DIR_LIST , @DIRS , $BASE_NAME , $ENTRY , $OUTPUT ) ;
$BASE_NAME = "$_[0]" ;
if ( -d $BASE_NAME ) {
opendir DIR , "$BASE_NAME" ;
@DIR_LIST = readdir DIR ;
splice @DIR_LIST , 0 , 2 ;
foreach $ENTRY ( @DIR_LIST ) {
if ( -d "$BASE_NAME/$ENTRY" ) {
push @DIRS , "$ENTRY" ;
}
...
read more »