Avoid hard-coding the path to the interpreter in your scripts

In general when trying to write portable scripts don’t start them with

#!/bin/bash

, instead start them with

#!/usr/bin/env bash

. 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

#!/usr/local/bin/perl

,

#!/usr/bin/bash

, or

#!/usr/local/bin/ruby

which is not very portable. For example on Debian Linux it’s

/bin/bash

whereas on FreeBSD you might find it in

/usr/local/bin/bash

(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

#!/usr/bin/env bash

or

#!/usr/bin/env ruby

.

This entry was posted in Ruby, Systems Administration. Bookmark the permalink.

4 Responses to Avoid hard-coding the path to the interpreter in your scripts

  1. William says:

    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.

  2. Kurin says:

    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.

  3. UmberGryphon says:

    “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.

  4. Todd Huss says:

    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.

Comments are closed.