1. Use `env`

    We use quite a few technologies to build our products, but Gimme Bar is still primarily a PHP app.

    To support these apps, we have a number of command-line scripts that handle maintenance tasks, cron jobs, data migration jobs, data processing workers, etc.

    These scripts often run PHP in Gimme Bar land, and we make extensive use of the shebang syntax that uses common Unix practice of putting #!/path/to/interpreter at the beginning of our command-line code. Clearly, this is nothing special—lots of people do exactly this same thing with PHP scripts.

    One thing I have noticed, though, is that many developers of PHP scripts are not aware of the common Unix(y) environment helper, env.

    I put this on Twitter a while ago, and it seemed to resonate with a lot of people:

    The beauty of using /usr/bin/env php instead of just /usr/local/bin/php or /usr/bin/php is that env will use your path to find the php you have set up for your user.

    We've mostly standardized our production and development nodes, but there's no guarantee that PHP will be in the same place on each box where we run it. env, however, is always located in /usr/bin—at least on all of the boxes we control, and on my Mac workstation.

    Maybe we're testing a new version of PHP that happens to be in /opt/php/bin/php, or maybe we have to support an old install on a different distribution than our standard, and PHP is located in /bin/php instead of /usr/bin/php. The practice of using env for this helps us push environmental configurations out of our code and into the actual environment.

    If you distribute a PHP application that has command-line scripts and shebang lines, I encourage you to adopt the practice of making your shebang line #!/usr/bin/env php.

    Note that this doesn't just apply to PHP of course, but I've seen a definite lack of env in the PHP world.

    10 Responses

    Feed for this Entry
    • The one problem I have with using env is that it only ever looks on your path -- it takes nothing else into consideration. For me, I often am testing against 4 different PHP versions -- and would like to be able to do something like: export PHP=/path/to/php && ./somePhpScript. I've yet to find a good solution to that, other than simply executing the script via the PHP interpreter I choose at that moment (/path/to/php somePhpScript).

    • MWOP, I don't see how these would be different (practically speaking):

      export PHP=/path/to/php && ./somePhpScript
      # your wish

      PATH=/path/to:$PATH ./somePhpScript
      # what I would do in that situation

      This prepends `/path/to` to your path for this command, and makes `/path/to/php` the executable that `/usr/bin/env php` would execute.

      S

    • Hi Sean,

      I never use shebangs, I always call php scripts via
      php script.php
      Then I don't have to give the script executable-rights and I'm in full control of the php version I'm using from "outside". Maybe you can tell about advantages of the shebang usage?

      Great article, if I would use shebangs I would also prefer to be flexible and use env.

      Michael

    • One thing I haven't figured out yet about `env` is why the path is not always set. We usually deployed `/usr/bin/env php` as well, and I've had random issues with cronjobs where I get `env: php not found` (or similar).

      In the end, the failsafe option is to install helpers via PEAR:

      I have a private PEAR channel setup for various tools. And on installation the pear installer replaces @php_bin@  in my scripts with the actual location of the PHP cli on my system.

      And when I have to run these scripts "interactively" (e.g. in dev – without the `pear install` part), I do something like `php foo.php` and it still works.

    • Michael, shebangs are mostly valuable for two things (at least to me): 1) to remove the extra step of figuring out where the interpreter is, and 2) to allow us to change "scripts/worker/handle-thing" from bash to PHP to Python, etc., without breaking anything.

      Till: `env` will reuse your existing environment, so yes, you need a $PATH. Also, I rarely associate the word "failsafe" with PEAR. /-:

      S

    • Aww, come on. ;) A `pear install` is very robust.

      Replacement tasks are simple and always work as expected. Ping me if you need some pointers.

    • The hashbang method feels much more unix-friendly and is what I'm used to with pretty much every other standalone script regardless of language. I see no reason not to use this methodology when working with standalone PHP scripts.

      That being said, MWOP brings up a good point about versioning. Yup, shameless plug coming:

      With the tiny`php-version` add-in, you can address versioning like so:
      php-version 5.3.10 >/dev/null

      More examples here:
      https://gist.github.com/2763153#file_bash.md

    • I always create a .php file (like Michael says), but then I also site a shebang executable and a batch file beside it.

      This way you get the best of 3 worlds.

    • Thanks for the tip. Its useful when you dont know which distro or control panel is installed on the server your script will run on.

    • env is great in the shebang line IF you don't intend to execute the scripts as a cron. We had some people edit such scripts to use env and things started failing. It took a bit to realize what specifically had happened... the crons scripts were executing under a different user account, and hence a different path.