Administrative Notes - Scripts for Creating and Testing Packages


The scripts I've written to speed up the packaging/testing of software packages are run as follows:

"makepkg  usr  foo  3.1.4"
"testpkg  usr  foo  3.1.4"
"restpkg  usr  foo  3.1.4"
"dupepkg foo  3.1.4"
"donepkg  usr  foo  3.1.4"
Each of the five scripts are detailed below. I don't claim that they are the finest examples of script-writing I've ever done, but they work for me. I hope you find them useful (at least as a catalyst for thought) in your work. I apologize for not taking the time to format the HTML code to properly indent the code for readability - you may find it easier to decipher if you view the HTML page source itself...it is indented for readability.

Jay Thompson
University of Tennessee - Telecommunications and Network Services
March 1998


Creating the "PKG.tar.gz" File (makepkg) Prior to running this script, the program to be packaged must be completely installed on the local system under either /usr/local/ or /opt/. Since we are producing packages for both root locations, we start by installing and packaging for /usr/local/. This allows us to later use the dupepkg script to set the package up for /opt/. Assuming that you are packaging up version 3.1.4 of foo which has been installed to /usr/local/, you invoke the script with the command:

"makepkg  usr  foo  3.1.4"

Which will create the package, foo-3.1.4-USRPKG.tar.gz, and place it in our permanent storage area, /opt/x86pkgs/archive/final-packages/usrpkgs.

Below is the script code itself:

#!/bin/csh
# Script for making packages written by Jay Thompson - March 1998
#
# USAGE: makepkg ROOTDIR PARENTDIR VERSION
#
# WHERE: ROOTDIR = "opt" or "usr"
# PARENTDIR = top level directory for program directory tree (also name of package)
# VERSION = package version number
#
# EG: makepkg usr foo 1.3.4
#
# will expect to find /usr/local/foo-1.3.4 acting as the program
# root for version 1.3.4 of the program "foo".
#
# Script will create "pkginfo" file and "prototype" file for
# a package whose name will be "foo". It will then create the
# package and tar it up, storing it in either:
#
# /opt/x86pkgs/archive/final-packages/optpkgs
# /opt/x86pkgs/archive/final-packages/usrpkgs
#
# (depending on "rootdir" parameter)

echo " "

if ( !($1 == "") ) then
if ( $1 == "opt" ) then
set ROOTDIR = "/opt"
set TAG = "OPT"
else
if ( $1 == "usr" ) then
set ROOTDIR = "/usr/local"
set TAG = "USR"
else
goto badparam1
endif
endif
else
goto badparam1
endif
if ( !($2 == "") ) then
set PKG = $2
if ( !($3 == "") ) then
set VER = $3
set DESC = $PKG"-"$VER
set BASEDIR = $ROOTDIR"/"$DESC
if ( -e $BASEDIR ) then
goto execute
else
goto baddir
endif
else
goto badparam3
endif
else
goto badparam2
endif

goto execute

badparam1:
echo " "
echo "ERROR: Invalid ROOTDIR"
goto printuse

badparam2:
echo " "
echo "ERROR: Missing PARENTDIR"
goto printuse

badparam3:
echo " "
echo "ERROR: Missing VERSION"
goto printuse

baddir:
echo " "
echo "ERROR: Program directory "'$BASEDIR'" does not exist"

goto printuse

printuse:
echo " "
echo "USAGE: makepkg ROOTDIR PARENTDIR VERSION"
echo " "
echo " ROOTDIR = 'opt' or 'usr'"
echo " PARENTDIR = Top level directory of program tree"
echo " VERSION = Version number of package"
echo " "
echo "EG: makepkg usr foo 1.2.4"
echo " "
echo " Will build package 'foo' from '/usr/local/foo-1.2.4'"
exit 1

# EVERYTHING CHECKS - GO AHEAD AND BUILD PACKAGE
# ----------------------------------------------
execute:

echo " "
echo "Building package '$PKG' from '$BASEDIR'"

cd $BASEDIR
if ( -e "prototype" ) then
rm prototype
endif
if ( -e "pkginfo" ) then
rm pkginfo
endif
if ( -e "prototemp" ) then
rm prototemp
endif

find . -print | pkgproto > prototemp
echo "i pkginfo=$BASEDIR/pkginfo" > prototype
cat prototemp >> prototype
rm prototemp

echo PKG='"'$PKG'"' > pkginfo
echo NAME='"'$PKG'"' >> pkginfo
echo ARCH='"Solaris 2.6"' >> pkginfo
echo VERSION='"'$VER'"' >> pkginfo
echo CATEGORY='"application"' >> pkginfo
echo DESC='"'$DESC'"' >> pkginfo
echo CLASSES='"none"' >> pkginfo
echo BASEDIR='"'$BASEDIR'"' >> pkginfo
echo MAXINST=1000 >> pkginfo

set PKGDIR = /var/spool/pkg/$PKG
if ( -e $PKGDIR ) then
rm -R $PKGDIR
endif

pkgmk -r $BASEDIR $PKG

set STOREDIR = /opt/x86pkgs/archive/final-packages/$1pkgs/
set TARFILE = $DESC-$TAG"PKG.tar"
set GZFILE = $TARFILE.gz
set STOREFILE = $STOREDIR$GZFILE

cd /var/spool/pkg
tar -cf $TARFILE $PKG
gzip -9 $TARFILE

if ( -e $STOREFILE ) then
echo " "
echo "Cannot store file '$STOREFILE'"
echo "File already exists"
echo " "
else
echo " "
echo "Storing file '$STOREFILE'"
echo " "
cp $GZFILE $STOREFILE
endif

echo " "
echo "Package '$PKG' from '$BASEDIR' successfully built"
echo " "
echo " "


Testing the "PKG.tar.gz" File (testpkg) Prior to running this script, the program to be tested must be packaged (using the makepkg script) and the final PKG.tar.gz file must be stored into it's appropriate storage area (which makepkg does automagically for you). Then to test the packaging, invoke the script with the command:

"testpkg  usr  foo  3.1.4"

Which will take the file, foo-3.1.4-USRPKG.tar.gz, from our permanent storage area, /opt/x86pkgs/archive/final-packages/usrpkgs, and install it to /usr/local/foo-3.1.4/.

Below is the script code itself:

#!/bin/csh
# Script for testing packages written by Jay Thompson - March 1998
#
# USAGE: testpkg ROOTDIR PARENTDIR VERSION
#
# ROOTDIR = "opt" or "usr"
# PARENTDIR = Top level directory of program tree
# VERSION = Version number of package
#
# testpkg usr foo 1.2.4
#
# Will install package "foo"
# from file "/opt/x86pkgs/archive/final-packages/usrpkgs/foo-1.2.4-USRPKGS.tar.gz"
# to directory "/usr/local/foo-1.2.4"

echo " "

if ( !($1 == "") ) then
if ( $1 == "opt" ) then
set ROOTDIR = "/opt"
set TAG = "OPT"
else
if ( $1 == "usr" ) then
set ROOTDIR = "/usr/local"
set TAG = "USR"
else
goto badparam1
endif
endif
else
goto badparam1
endif

if ( !($2 == "") ) then
set PKG = $2
if ( !($3 == "") ) then
set VER = $3
set DESC = $PKG"-"$VER
set BASEDIR = $ROOTDIR"/"$DESC
goto execute
endif
else
goto badparam3
endif
else
goto badparam2
endif

goto execute

badparam1:
echo " "
echo "ERROR: Invalid ROOTDIR"
goto printuse

badparam2:
echo " "
echo "ERROR: Missing PARENTDIR"
goto printuse

badparam3:
echo " "
echo "ERROR: Missing VERSION"
goto printuse

printuse:
echo " "
echo "USAGE: testpkg ROOTDIR PARENTDIR VERSION"
echo " "
echo " ROOTDIR = 'opt' or 'usr'"
echo " PARENTDIR = Top level directory of program tree"
echo " VERSION = Version number of package"
echo " "
echo "EG: testpkg usr foo 1.2.4"
echo " "
echo " Will install package 'foo' from file"
echo " "'/opt/x86pkgs/archive/final-packages/usrpkgs/foo-1.2.4-USRPKGS.tar.gz'"
echo " to directory '/usr/local/foo-1.2.4'"
echo " "
echo " "
exit 1

# EVERYTHING CHECKS - GO AHEAD AND INSTALL PACKAGE
# ------------------------------------------------
execute:

set STOREDIR = /opt/x86pkgs/archive/final-packages/$1pkgs/
set TARFILE = $DESC-$TAG"PKG.tar"
set GZFILE = $TARFILE.gz
set STOREFILE = $STOREDIR$GZFILE

if ( !( -e $STOREFILE ) ) then
echo " "
echo "ERROR: Cannot continue with package install"
echo " File '$STOREFILE' does not exist"
echo " "
echo " "
exit 1
endif

echo " "
echo "Installing package '$PKG' to '$BASEDIR'"

cd $ROOTDIR

if ( -e $PKG-hold.tar) then
rm $PKG-hold.tar
endif

if ( -e $BASEDIR ) then
tar -cf $PKG-hold.tar $DESC
rm -R $DESC
endif

cd /pkgtmp

if ( -e $PKG ) then
rm -R $PKG
endif

if ( -e $GZFILE ) then
rm $GZFILE
endif

if ( -e $TARFILE ) then
rm $TARFILE
endif

cp $STOREFILE .
gunzip $GZFILE
tar -xof $TARFILE
pkgadd -d /pkgtmp $PKG
rm $TARFILE

echo " "
echo "Package '$PKG' installed to '$BASEDIR'"
echo "If no errors were reported, then the installation was successful"
echo " "
echo " "


What if it Didn't Work? (restpkg) If the packaging/testing process did not work for some reason (which may require that you "massage" the files manually), you can restore the installed software in it's form prior to packaging with the restpkg script. Then, depending on what you have to do to get it working, you may be able to simply start again with the makepkg script, or you may have to carry out the packaging/testing process manually.

That is, if the packaging process failed because of something inherent in the installed software itself (which you are able to correct), then you can start again with the makepkg script after you have corrected the problem.

However, if resolving the problem requires some kind of "tweak" to the pkginfo or prototype files, then you will have to carry out the packaging process manually (since the makepkg script automatically creates these files and does not allow massaging prior to the packaging operation).

You invoke the restore script with the command:

"restpkg  usr  foo  3.1.4"

Which will untar a "hold" file, created by the makepkg script called /usr/local/foo-hold.tar. Once untarred, the software will be returned to its pre-packaged state except that it will have both the pkginfo and prototype files in place for your review.

Below is the script code itself:

#!/bin/csh
# Script for restoring software after a packaging process has been initiated with
# the "makepkg" script. - Written by Jay Thompson - March 1998
#
# USAGE: restpkg ROOTDIR PARENTDIR VERSION
#
# WHERE: ROOTDIR = "opt" or "usr"
# PARENTDIR = top level directory for program directory tree
# (also name of package)
# VERSION = package version number
#
# EG: restpkg usr foo 1.3.4
#
# will expect to find the file, "/usr/local/foo-hold.tar", will untar to
# a directory tree rooted at "/usr/local/foo-1.3.4".

echo " "

if ( !($1 == "") ) then
if ( $1 == "opt" ) then
set ROOTDIR = "/opt"
set TAG = "OPT"
else
if ( $1 == "usr" ) then
set ROOTDIR = "/usr/local"
set TAG = "USR"
else
goto badparam1
endif
endif
else
goto badparam1
endif

if ( !($2 == "") ) then
set PKG = $2
if ( !($3 == "") ) then
set VER = $3
set DESC = $PKG"-"$VER
set BASEDIR = $ROOTDIR"/"$DESC
goto execute
endif
else
goto badparam3
endif
else
goto badparam2
endif

goto execute

badparam1:
echo " "
echo "ERROR: Invalid ROOTDIR"
goto printuse

badparam2:
echo " "
echo "ERROR: Missing PARENTDIR"
goto printuse

badparam3:
echo " "
echo "ERROR: Missing VERSION"
goto printuse

printuse:
echo " "
echo "USAGE: restpkg ROOTDIR PARENTDIR VERSION"
echo " "
echo " ROOTDIR = 'opt' or 'usr'"
echo " PARENTDIR = Top level directory of program tree"
echo " VERSION = Version number of package"
echo " "
echo "EG: restpkg usr foo 1.2.4"
echo " "
echo " Will use file 'usr/local/foo-hold.tar' and untar to a"
echo " directory tree rooted at 'usr/local/foo-1.2.4'"
echo " "
echo " "
exit 1

# EVERYTHING CHECKS - GO AHEAD AND RESTORE PACKAGE
# ------------------------------------------------
execute:

set TARFILE = $PKG-hold.tar

cd $ROOTDIR

if ( !( -e $TARFILE) ) then
echo "ERROR: Cannot restore '$PKG' - file '$ROOTDIR/$TARFILE' not found"
echo " "
echo " "
exit 1
endif

if ( -e $DESC ) then
rm -R $DESC
endif

tar -xof $TARFILE
rm $TARFILE

echo "'$PKG' successfully restored"
echo " "
echo " "


Duplicating the Work for /opt/ (dupepkg) Once the package has been successfully created and tested for installation to /usr/local/, it must then be created and tested for installation to /opt/. Assuming that you have just finished the testing for installation to /usr/local/, then you have a working version of the software installed to /usr/local/.

You can now invoke the dupepkg script with the command:

"dupepkg foo  3.1.4"

Which will duplicate the software installation copying from /usr/local over to /opt/ after which, you can repeat the package creation/testing process for /opt/.

Below is the script code itself:

#!/bin/csh
# Duplicate the /usr/local/ installation to /opt/
# Written by Jay Thompson - March 1998
#
# USAGE: dupepkg PARENTDIR VERSION
#
# PARENTDIR = Top level directory of program tree
# VERSION = Version number of package
#
# dupepkg foo 1.2.4
#
# Will duplicate directory tree usr/local/foo-1.2.4 to /opt/foo-1.2.4

echo " "

if ( !($1 == "") ) then
set PKG = $1
if ( !($2 == "") ) then
set VER = $2
set DESC = $PKG"-"$VER
else
goto badparam2
endif
else
goto badparam1
endif

goto execute

badparam1:
echo " "
echo "ERROR: Missing PARENTDIR"
goto printuse

badparam2:
echo " "
echo "ERROR: Missing VERSION"
goto printuse

printuse:
echo " "
echo "USAGE: dupepkg PARENTDIR VERSION"
echo " "
echo " PARENTDIR = Top level directory of program tree"
echo " VERSION = Version number of package"
echo " "
echo "EG: donepkg foo 1.2.4"
echo " "
echo " Will duplicate directory tree 'usr/local/foo-1.2.4' to '/opt/foo-1.2.4'"
echo " "
echo " "
exit 1

# EVERYTHING CHECKS - GO AHEAD AND DUPLICATE
# -------------------------------------------------
execute:

set SRCDIR = "/usr/local"
set DSTDIR = "/opt"

set TARFILE = $DESC"-temp.tar"
set GZFILE = $TARFILE".gz"

cd $SRCDIR
if ( !( -e $DESC ) ) then
echo "ERROR: Cannot duplicate '$PKG' - '$DESC' does not exist in /usr/local/"
echo " "
echo " "
exit 1
else
echo "Duplicating '$PKG' from /usr/local/ to /opt/"
endif


if ( -e $TARFILE ) then
rm $TARFILE
endif
if ( -e $GZFILE ) then
rm $GZFILE
endif
tar -cf $TARFILE $DESC

cd $DSTDIR
if ( -e $DESC) then
rm -R $DESC
endif
if ( -e $TARFILE ) then
rm $TARFILE
endif
if ( -e $GZFILE ) then
rm $GZFILE
endif
mv $SRCDIR"/"$TARFILE .
tar -xof $TARFILE
rm $TARFILE

echo " "
echo "Package '$PKG' successfully duplicated from /usr/local/ to /opt/"
echo " "
echo " "


Final Cleanup (donepgk) Once completed, you will have two versions of the package installed, one to /usr/local/ and one to /opt/. Additionally the "hold" files that allow you to run restpkg will still be out there. This script will clean out the hold files and one version of the installed package.

You invoke the script with the command:

"donepkg  usr  foo  3.1.4"

Which will delete the /usr/local/foo-hold.tar and /opt/foo-hold.tar files. Additionally, since you specified "usr", it will KEEP the package installed to /usr/local as the final installed version (removing the one installed to /opt/). Finally, it will search all pre-determined work areas and clean out whatever "residual" files may be left that are no longer needed now that the packaging of foo-3.1.4 is complete.

Below is the script code itself:

#!/bin/csh
# Final cleanup script after packages have been successfully created/tested
# Written by Jay Thompson - March 1998
#
# USAGE: donepkg ROOTDIR PARENTDIR VERSION
#
# ROOTDIR = "opt" or "usr"
# PARENTDIR = Top level directory of program tree
# VERSION = Version number of package
#
# donepkg usr foo 1.2.4
#
# Will delete un-needed files left over from creating package "foo".
# Will leave the version installed to /usr/local/ if "usr" is specified as ROOTDIR
# Will leave the version installed to /opt/ if "opt" is specified as ROOTDIR

echo " "

if ( !($1 == "") ) then
if ( $1 == "opt" ) then
set ROOTDIR = "/opt"
set ALTDIR = "/usr/local"
set TAG = "OPT"
else
if ( $1 == "usr" ) then
set ROOTDIR = "/usr/local"
set ALTDIR = "/opt"
set TAG = "USR"
else
goto badparam1
endif
endif
else
goto badparam1
endif

if ( !($2 == "") ) then
set PKG = $2
if ( !($3 == "") ) then
set VER = $3
set DESC = $PKG"-"$VER
set BASEDIR = $ROOTDIR"/"$DESC
else
goto badparam3
endif
else
goto badparam2
endif

goto execute

badparam1:
echo " "
echo "ERROR: Invalid ROOTDIR"
goto printuse

badparam2:
echo " "
echo "ERROR: Missing PARENTDIR"
goto printuse

badparam3:
echo " "
echo "ERROR: Missing VERSION"
goto printuse

printuse:
echo " "
echo "USAGE: donepkg ROOTDIR PARENTDIR VERSION"
echo " "
echo " ROOTDIR = 'opt' or 'usr'"
echo " PARENTDIR = Top level directory of program tree"
echo " VERSION = Version number of package"
echo " "
echo "EG: donepkg usr foo 1.2.4"
echo " "
echo " Will delete un-needed files left over from creating package 'foo'"
echo " Will leave the version installed to /usr/local/ if 'usr' is specified as ROOTDIR"
echo " Will leave the version installed to /opt/ if 'opt' is specified as ROOTDIR"
echo " "
echo " "
exit 1

# EVERYTHING CHECKS - GO AHEAD AND COMPLETE CLEANUP
# -------------------------------------------------
execute:

set TARFILE = $DESC"-USRPKG.tar"
set GZFILE = $TARFILE.gz
set STOREDIR = /opt/x86pkgs/archive/final-packages/usrpkgs/
set STOREFILE = $STOREDIR$GZFILE

if ( !( -e $STOREFILE ) ) then
echo "ERROR: Cannot continue with final cleanup - Cannot find storage file:"
echo " '$STOREFILE'"
echo " "
echo " "
exit 1
endif

set TARFILE = $DESC"-OPTPKG.tar"
set GZFILE = $TARFILE.gz
set STOREDIR = /opt/x86pkgs/archive/final-packages/optpkgs/
set STOREFILE = $STOREDIR$GZFILE

if ( !( -e $STOREFILE ) ) then
echo "ERROR: Cannot continue with final cleanup - Cannot find storage file:"
echo " '$STOREFILE'"
echo " "
echo " "
exit 1
endif

echo " "
echo "Cleaning up files after completion of packaging '$PKG'"

cd $ROOTDIR

if ( !( -e $DESC) ) then
echo "ERROR: Cannot continue with cleanup - '$DESC' does not exist in '$ROOTDIR'"
echo " "
echo " "
exit 1
endif

if ( -e $PKG-hold.tar) then
rm $PKG-hold.tar
endif

cd $ALTDIR

if ( -e $PKG-hold.tar) then
rm $PKG-hold.tar
endif

if ( -e $DESC ) then
rm -R $DESC
endif

cd /var/spool/pkg

if ( -e $PKG ) then
rm -R $PKG
endif

if ( -e $GZFILE ) then
rm $GZFILE
endif

if ( -e $TARFILE ) then
rm $TARFILE
endif

cd /pkgtmp

if ( -e $PKG ) then
rm -R $PKG
endif

if ( -e $GZFILE ) then
rm $GZFILE
endif

if ( -e $TARFILE ) then
rm $TARFILE
endif

echo " "
echo "Finished with '$PKG' cleanup"
echo "Final working version is in '$BASEDIR'"
echo " "
echo " "


Please send comments to x86admin@sunsite.utk.edu