Default Bash 3 overriding shebang /bin/bash with brew installed bash 4
Solution 1:
This is the main reason nowadays for using a different shebang:
#!/usr/bin/env bash
- Why is #!/usr/bin/env bash superior to #!/bin/bash? - Stack Overflow
This will use the first bash in the PATH, which will most likely be the latest version. Since /bin is in the standard path (getconf PATH
), this falls back gracefully for those without a custom bash.
Solution 2:
Firstly, you could consider simply replacing /bin/bash
with a more uptodate version.
Secondly, if you're not comfortable voiding your warranty doing that, and where you already have a problem with an existing script, bypass its #!
line by invoking it as:
/path/to/bash4
/path/to/script.bash
args...
(You can just use bash
rather than its full path if your $PATH
is in the right order.)
Thirdly, if this script is specific to Apple devices and must have Bash version 4, then always set it explicitly to #!
/path/to/bash4
, as there's no benefit to setting it to anything else. (This does not mean changing it in your source repo, but rather choosing it at installation time; see below.)
Fourthly, consider using https://gist.github.com/kurahaupo/8130030 - note that you need the "source" version of the script to be outside the intended bin
directory; eg, leave it in your source repo, or in a temporary directory (which can be deleted after this "installation").
Fifthly, if you really don't want to touch the original script, make a stub script that invokes it:
#!/bin/sh
exec /path/to/bash4 /path/where/you/stashed/the/original/script "$@"
and install that in a suitable bin
directory.
Source vs Deploy
Your query about setting the #!
line in the source repo highlights an extremely prevalent misapprehension about scripts: the idea that a script, simply because it is "text", should not need to be "prepared for use" in any sense.
For other types of programs it's obvious: they have to be compiled. And if they're large python or perl scripts, they need a package or installer that will include any module dependencies.
But even a shell script needs, at minimum, to have its ownership and permissions set, and to be placed into a bin
directory. Typically this would be either when a package is built for a class of device, or when the script is installed on a target device. This is also the appropriate time to set the #!
line to match the deployment environment.
I do not recommend #!/usr/bin/env bash
The widespread promotion of #!/usr/bin/env
slightly weakens overall security, but in a way that's not likely to bite the people who write it, only the users somewhere down the track. Therefore I do not recommend it; indeed I predict that eventually it's going to come back and bite your clients, or your clients' clients, or your clients' clients' ... clients.
It's promoted as "portable", but that's not actually true: Android and OpenWRT devices do not even have /usr
much less /usr/bin/env
, so it's quite useless there. So in practice the main beneficiaries are Apple users.
If the script requires a new version of bash, then the system version simply won't do, so it's pointless using it as a fallback. But if you don't need the latest version, then having it fixed as /bin/bash is fine.
In short, if you're deploying a script to Apple that requires Bash version 4, then you should use #!
/path/to/bash4
, either when you build the script into an installable package, or when the script is installed on a particular device.
EDIT
I replaced /usr/local/bin/bash
with /path/to/bash4
because that was causing some confusion. The point isn't that /usr/local/bin/bash
must be used, but rather that the full path to bash4, whatever it is, should be specified explicitly. If you don't know it before installation, looking in $PATH
then is a reasonable thing to do, but you'd want to run a short test like
bash_path=$( type -p bash )
if ! "$bash_path" -c '[[ $BASH_VERSION > 4.2 ]]'
then
echo "ERROR: $bash_path isn't new enough"
exit 1
fi
{
printf '#!%s\n' "$bash_path"
tail -n+2 "$downloaded_file"
} > "$installpath"
chmod a=rx "$installpath"