Bash #3 - PATH-wrapping executables
Posted February 18, 2022 ‐ 3 min read
When fixing up complex systems to our advantage we sometimes need to hook on
the intermediate execution of a program. The UNIX PATH
environment is the
venerable search path for programs available in the environment. In this post
I'll discuss how to use to wrap around the execution of a program.
Previous post: #2.
The PATH
environment variable is a :
-delimited strings of paths that are
searched in order for executables. For example, a build system may search
for the gcc
compiler in PATH
.
Let's wrap around gcc
. To create our gcc
wrapper, we need to decided
on a directory on which to place it. The name of the wrapping executable will
also be gcc
so that it gets picked by PATH
lookup. The absolute path
of that directory needs to be prepended to PATH
for the wrapper to be found.
There are various ways to do this. The most common are:
- Prepend in shell command execution
PATH="/directory/to-wrapper:$PATH" <command>
, only affecting that command. - Modify for the current shell script or interactive shell using
export PATH="/diretory/to-wrapper:$PATH"
Our wrapper can be written as such:
#!/bin/bash
# Remove ourselves from $PATH, to prevent infinite
# recursion when the wrapped executable is executed
# by us.
curdir=
path_tmp=
# Don't let Ctrl-C kill the script
# Execute the original program
e= # Save exit status
# Clear out handler
|
Notes on what is being done above:
- Important to clear out the directory in which the wrapper resides from
PATH
, otherwise we can cause an infinite recursion. - Forward the exit status of the original program.
- Allow logic to be implemented before and following execution.
- We can control how the original program is executed.
- We can wrap more than one executable with a single wrapper source.
Demo
$ ls -l bin
total 4
lrwxrwxrwx 1 dan dan 7 Feb 19 09:18 gcc -> wrapper
lrwxrwxrwx 1 dan dan 7 Feb 19 09:18 ls -> wrapper
-rwxrwxr-x 1 dan dan 389 Feb 19 09:15 wrapper
$ export PATH=$(pwd)/bin:$PATH
$ ls bin
Before execution
gcc ls wrapper
After execution
$ gcc non-existant.c
Before execution
gcc: error: non-existant.c: No such file or directory
gcc: fatal error: no input files
compilation terminated.
After execution
|
Final note
We should be careful about emitting to stdout and stderr by the wrapping code, and may want to even avoid it completely, lest we break assumptions being made by the upper-level scripts that execute the program we are wrapping.