Executing your Executables
No I am not about to go on some right-wing rant to excise evil programs. Rather I am going to discuss a nice way to use Bash to launch your executables. For those of us that write *nix programs for a living we often use Bash (or other shell) script to manage the launch of the program but not always in the most flexible manner. We use a script because the actual program launch is complicated and involves executing multiple programs. Or we use one because launching our program requires a tedious number of arguments. And finally, and most importantly, we often use a script to isolate users from the complication of executing something that isn't trivially simple (and even moderately simple ones such as a java-based application).So one common issue that launch scripts have is that they typically need to know the path to associated program files, whether that is other executables and scripts, configuration files, resource files, etc. Issues arise if users install the application and call the launch script in unexpected ways. Examples include: putting a symbolic link to the launch script, calling it through a relative or fully-qualified path, adding the launch script's parent folder to PATH, adding a symbolic link to the launch script's parent folder and putting it in the PATH, creating a directory and putting a symbolic link to the launch script and then putting a symbolic link to the directory holding the symbolic link to the launch script and then putting THAT symbolically linked directory in the PATH (Yikes!), etc. etc.
However, with a little Bash-Foo we can protect our scripts and ensure they know how to find its true installation home. I.e. we want them to be able to "phone-home". Once home is known (which in my case is set in a QUALIFIED_PATH variable), we can simply move relatively from QUALIFIED_PATH to load or reference other files. Easy peezy, mac and cheesy (as my kids like to say)!
Boom: There It Is
The short version of this (but that doesn't work on BSD variants of UNIX such as OSX):#!/bin/bash
######################################################
################# BLOCK TO PHONE HOME ################
# This can be used to find installation directory
# no matter how this script is referenced/linked or
# put in the PATH or whatever
BASENAME=$(basename "$0")
if [ "$0" == "${0#/}" ] ; then
QUALIFIED_PATH="$PWD"/"${0%/*}"
else
QUALIFIED_PATH="${0%/*}"
fi
# NOTE: the following doesn't work on OSX and other BSD (on non-Gnu) derivatives
# Download tarball with portableReadlink function for a universal alternative
PATH_TO_EXEC=$(readlink -f "${QUALIFIED_PATH}/${BASENAME}")
QUALIFIED_PATH=$(dirname "${PATH_TO_EXEC}")
############### END BLOCK TO PHONE HOME ##############
######################################################
echo "My Path Home is: ${QUALIFIED_PATH}"
Additionally, a version that includes a "portableReadlink" function to compensate for lacking "readlink -f" is downloadable from this tarball package. The actual useful block is at the top of boomThereItIs/phoneHome.sh, while the tarball also includes a test program called testPhoneHome.sh in a parent directory that demonstrates its utility in a number of ways. That tarball is located on my Google Drive here: Download phoneHomeDemo.tar.bz2
Enjoy!