On Shells and Static PathsHow static paths are actively harming the industry.
In a previous post, I told people not to start their scripts with
#!/bin/bash. In this post, I will explain in more detail why you shouldn’t do this if you want your script to be portable!
Operating systems, they are neat, aren’t they? So much diversity, so many options! Don’t like the shell that comes stock on your OS because it doesn’t connect to the internet, download a list of packages that might be similar to a mistyped command you haphazardly pasted into your terminal? Great, you can install one that does! So many options!
With all these options available to us, how can someone settle on a
single PATH to contain all this greatness? Why put
Well.. lets not get crazy here… That’s clearly a terrible location
bash, no way it’s standard!
It’s true that not all Unixie operating systems conform to these
standards, but all of them implement enough to solve the problem of a
given shell not being installed in
The wisdom of The Grey Ones
Long ago, the Great Grey Ones knew that not everyone would put things
/bin. They also knew that for a script/binary to be usefull.. it
needed to be in your PATH environment variable! Because of this.. they
made statements like:
Applications should note that the standard PATH to the shell cannot be assumed to be either /bin/sh or /usr/bin/sh, and should be determined by interrogation of the PATH returned by getconf PATH, ensuring that the returned pathname is an absolute pathname and not a shell built-in.
Both POSIX and SUS define this.
I know what you are thinking: “Surely this applies only to
is the new standard,
bash is everywhere! Anything that doesn’t have
bash is old and therefore not used! My
bash is in
yours MUST be as well!”
What if I told you, some systems like OpenBSD and
FreeBSD do things a little differently. They have
a clear distinction between “base” applications and applications that
are installed via their respective
For various reasons, things like
zsh are not included in
“base”. This means they will be installed outside of the typical “/bin,
/usr/bin” directory structure. Which means when you put lines like:
#!/bin/bash at the top of your script you are ensuring that your
script will not run on OpenBSD or FreeBSD (or any other system that has
bash installed somewhere else)!
Back to The Grey Ones
They planned for this! They gave us nifty tools that allow us to invoke these these shells without knowing the explicit path for said shell!
executes utility after modifying the environment as specified on the command line.
env will spit out a list of all your currently set
variables! These vars get passed to
utility when you execute
env bash (where
bash is the utility).
This means if we have our scripts execute
#!/usr/bin/env bash as the
first line of our script, the PATH variable will be set to something
that is more likely to contain
bash than an explicit declaration
/bin/bash which, as we learned, doesn’t exist on some systems!
Don’t be that guy. If your script is meant to run on a variety
of systems, follow the advice of The Grey Ones, use something like
env to make your scripts portable. I have yet to see a *NIX OS that
/usr/bin/env. This includes things like True64.