In general when trying to write portable scripts don’t start them with
, instead start them with
. The only caveat is that you DO NOT want to do this for critical security scripts because it opens you up to path based exploits.
Scripts are often written with the path to the interpreter hard-coded such as
,
, or
which is not very portable. For example on Debian Linux it’s
whereas on FreeBSD you might find it in
(thanks for the correction Kurin). With Ruby, Perl, and Python it varies even more from sysem to system so we really need a way to start the interpreter from anywhere in your path. Enter env!
In almost all Unix inspired systems you’ll find the env command at /usr/bin/env which uses the path to find the interpreter so if you’re writing scripts to run across systems you’ll greatly improve portability by using
or
.
There is no way you can reasonably assert that the path to ‘env’ is any more stable than the path to bash or bourne shell on a Linux system. I’ll fully agree with you on the issue with regard to python, perl, ruby, tcl, but for shell scripts /bin/sh is *the* way to ensure portability.
On FreeBSD it’s never /usr/bin/bash unless your admin is doing something wrong (like trying to get a script to run that’s hardcoded to /usr/bin/bash). It’s /usr/local/bin/bash, if it’s there at all, which it isn’t by default.
“The only caveat is that you DO NOT want to do this for critical security scripts because it opens you up to path based exploits.”
I would extend this to say “The only caveat is that you DO NOT want to do this for any script that root or any user that is in a critical group might ever run.” And what does that leave, exactly?
Things going wrong with differing paths to bash/perl/ruby/etc. are a problem, but things going wrong with path based exploits are several orders of magnitude worse.
William: you are correct that /bin/sh is “the most portable” way to write but I was speaking more generally about using more feature rich interpreters which can be found all over the system.
Kurin: On our FreeBSD 4 systems at work it’s in /usr/bin but I didn’t install the systems so it could have been a mistake. Regardless the point is really that it varies from system to system.
UmberGryphon: Once you take in all the user written perl, python, and ruby scripts that run under non-priveleged accounts on production system they well outweight the volume of /bin/sh scripts being run by root. If you’re a sysadmin this tip doesn’t really apply, hence the caveat, but if you’re a programmer at an ISV then scripts running under non-priveleged accounts are pretty much your world and that’s where the advice applies.