PROBLEM:
During a Solaris installation - either by cdrom or jumpstart - the local
harddisks/partitions are mounted at a read-writable mount point called
"/a". The running Solaris itself is mounted read-only by NFS. Equally, the BASEDIR variable is also set to "/a". "/a" therefore is the location where all packages to be installed will be written to.
If you have this in mind, then you will understand why I
strongly recommend omitting the trailing "/" when creating
a prototype file and why I _strongly_ recommend not using any kind of
absolute pathnames. As the booted system is mounted read-only in memory,
a PKG containing /usr/local in its pkgmap will fail to install as the files
_cannot_ be installed in "/"!
Therefore any installation script using special shell commands like useradd,
groupadd, mkdir or any other command should reference the commands like
CHROOTDIR="${BASEDIR}"
${BASEDIR}/usr/sbin/chroot ${CHROOTDIR} /usr/sbin/groupadd -g 80 httpd
${BASEDIR/usr/bin/mkdir $BASEDIR/tmp/foobar
Global environment variables _always_ override the definitions in the
pkginfo file!
As you may remeber from the former chapter, there are six types of
scripts you can create:
There are installation scripts and procedure scripts. Installation scripts are
request and checkinstall. Procedure scripts are preinstall, postinstall,
preremove, postremove.
Installation scripts cannot modify files. They can do global
software dependancy checks, e.g. whether a certain version of a binary is
installed or whether a needed file (database file) exists somewhere on the
harddisk. They can gather data from the system (checkinstall) or the
administrator (request). They can modify global variables like CLASSES,
so only certain files will be installed.
Procedure scripts provide a mechanism to influence the
package installation process. They can only do package-based dependancy checks.
They can modify system resources like adding users or changing permissions.
They cannot be used for gathering data interactively.
| Variable name | Description |
| CLIENT_BASEDIR | The base directory with respect to the target system. While BASEDIR is the variable to use if referring to a package on the cdrom/ install server, this variable is the path to include in files placed on the client system. |
| INST_DATADIR | The directory where the package now being read is located. |
| PATH | The search list used by sh to find commands on script invocation. |
| PKGINST | The instance identifier of the package being installed. |
| PKGSAV | The directory where files can be saved for use by removal scripts or where previously saved files can be found. |
| PKG_INSTALL_ROOT | The root file system on the target system where the package is being installed. Available for pkgadd/pkgrm only when these commands are invoked with -R option. |
| PKG_NO_UNIFIED | Is an env variable that gets set if the pkgadd/pkgrm command is invoked with the -R -M option. |
| UPDATE | This variable does not exist under most installation environments. If it does exist (with the value yes), it means that a PKG with the same name, version and architecture is already installed on the system or that the installing PKG will overwrite an installed PKG. The original BASEDIR is then used. |
There are certain restrictions which apply to the request script:
NOTE: When you include a request script in a package that you
want to add to a jumpstart server, keep in mind that noone can answer the
questions you may ask in the script. Therefore an automated package install
will maybe result in a partially installed package or the jumpstart mechanism
will halt until an administrator gives the right answer. The only solution is
to provide default values for your questions and to define those default
values in the pkginfo file. Additionally, you can check whether the
installation is taking part in an interactive environment or in a
non-interactive environment by checking the content of the ${BASEDIR} variable.
Remember: if you are running in a non-interactive environment, e.g. cdrom or
jumpstart installation, ${BASEDIR} refers to /a.
Here is an example for a request script:
#!/bin/sh
REALNAME=""
echo "Enter your realname: "
read REALNAME
# export REALNAME to global PKG environment
cat >> $1 << EOT
REALNAME=${REALNAME}
EOT
Doing like this will make the variable REALNAME and its content available to the following installation/procedure scripts. If you add a
echo "installation response file: $1"
to your request script, then you will realize that pkgadd calls the request script with the name of the temporarily response file as first parameter.
The checkinstall script is executed shortly after the optional request script.
The checkinstall script is _strictly_ a data gatherer. However, based on the
information it gathers, it can create or modify environment variables in order
to control the course of the resulting installation. It is also capable of
halting cleanly the installation process.
The checkinstall script is intended to perform basic checks on a file system
that would not be normal for the pkgadd command. For example, it can manage
general software dependancies, in contradiction to the depend file of a
package which manages only package-level dependencies.
Here is an example for a checkinstall script:
#!/bin/sh # checkinstall script for ARbc # First find which bash package has been installed pkginfo -q ARbash1 # try the older one first if [ $? -ne 0 ] then pkginfo -q ARbash # now the latest if [ $? -ne 0 ] then echo "No bash package can be found. Please install the" echo "ARbash package and try this installation again." exit 3 # Suspend else BASHROOT="`pkgparam ARbash BASEDIR`/usr/local/bin" # new one fi else BASHROOT="`pkgparam ARbash1 BASEDIR`/usr/local/bin" # old one fi # Now look for the bash executable we will need for our silly bootscript if [ $BASHROOT/bash ] then exit 0 # all OK else echo "No bash executable can be found. Please check your bash" echo "package for integrity and try this installation again." exit 3 # Suspend fi
Procedure scripts provide a set of instructions to be performed at particular point in package installation or removal. Of course there are also restrictions which apply to procedure scripts as well as they did to the installation scripts "request" and "checkinstall":
Here is an example for a preinstall script:
#!/bin/sh
CHROOTDIR="${BASEDIR}"
# Create a group for our new service
${BASEDIR}/usr/sbin/chroot ${CHROOTDIR} /usr/sbin/groupadd -g 80 httpd
# Create a user for our new service
${BASEDIR}/usr/sbin/chroot ${CHROOTDIR} /usr/sbin/useradd -u 80 -g 80 -d
/data/www -m -s /bin/sh -c "Webserver User" httpd
Here is an example for a postinstall script:
#!/bin/sh
# Create logfile directory for our webserver
${BASEDIR}/bin/mkdir -p ${BASEDIR}/data/logs/www
Here is an example for a preremove script:
#!/bin/sh # Stop our webserver first /etc/init.d/webserver stop
Here is an example for a postremove script
#!/bin/sh
LOGDIR=/data/logs
# collect all logfiles to a .tar. gz and trash the directory
cd ${LOGDIR}
/usr/local/bin/gtar cvfz ${LOGDIR}/logfiles.tar.gz && \
rm -rf ${LOGDIR}
NOTE: You may have noticed that the preremove/postremove scripts do not use the relative commandline syntax, e.g. with a ${BASEDIR} as prefix. Honestly, I never saw a package removal during Solaris installation. Additionally I think that package removal _has_ to be done interactively.