18

I recently noticed that many scripts are using /usr/bin/env in their shebang. I have seen that mainly using Bash and Python, but thus far never in conjunction with POSIX sh (ash, dash,...).

I wonder why, and if my, meant-to-be highly portable, POSIX shell scripts might benefit from the env approach?


Is there a general concensus on whether to use:

  • standard:

    #!/bin/sh
    
  • environment:

    #!/usr/bin/env sh
    

Let me stress this enough:

I never have seen this with sh.

  • 3
    On macOS, for example, /bin/bash is an antiquated POC, but one can get newer bash via homebrew. So I use #!/usr/bin/env bash if write a script for both my MBP and my Linux PC. But if I'm going to stick to POSIX, then /bin/sh is fine for both; I don't see much of a use case except in some outdated system where /bin/sh might not be a POSIX shell, in which case I doubt /usr/bin/env will work either. – muru Feb 27 '20 at 03:51
  • 9
    https://unix.stackexchange.com/a/77586/70524: "There are two programs whose location you can rely on on almost every unix variant: /bin/sh and /usr/bin/env. Some obscure and mostly retired Unix variants had /bin/env without having /usr/bin/env, but you're unlikely to encounter them. Modern systems have /usr/bin/env precisely because of its widespread use in shebangs. /usr/bin/env is something you can count on." – muru Feb 27 '20 at 03:52
  • "There are two programs whose location you can rely on on almost every unix variant: /bin/sh and /usr/bin/env" except that neither path is standard and the most used unix variant ever (like >99% of existing installations) doesn't have either of them. –  Feb 27 '20 at 04:41
  • @muru FYI POSIX doesn't say anything about either /bin/sh or shebang-ed scripts. Both are non-standard extensions. –  Feb 27 '20 at 04:48
  • 2
    @mosvy Which most used unix variant ever doesn't have /bin/sh? – Oskar Skog Feb 27 '20 at 06:34
  • @OskarSkog didn't some Solaris have the Bourne shell for /bin/sh and an actual POSIX sh somewhere else? – muru Feb 27 '20 at 07:02
  • 1
    A unix variant based on the Linux kernel, which is also the most used operating system, period, not just the most used unix variant. And despite preconceived notions, it is a regular Unix system, more similar to eg. Ubuntu or FreeBSD 12 than those are to Unix version 7 or Sys III ;-) –  Feb 27 '20 at 07:04
  • Android? Really? Does it by default have anything that resembles a unix-like userland? I know I can install stuff, but does it have that by default? – Oskar Skog Feb 27 '20 at 08:43
  • 1
    @OskarSkog Yes. Really. Android is using a C library based on Open/NetBSD (rather than glibc or musl), base utilities based on toybox (rather than GNU coreutils or busybox) and the mksh shell (rather than dash or bash). Those may not all be the most felicitous choices, but they easily clear the "unix-like" criterium. Also notice that its "java" UI also builds on Linux interfaces and concepts (it does NOT run like a vm, only using the Linux kernel for low-level chores; apps map to unix user ids, selinux / capabilities / namespaces are used to contain them, etc, etc). –  Feb 27 '20 at 09:58
  • 3
    @muru be vary careful: a bash compiled with default parameters is not POSIX compliant, this is why Apple offers a special bash version in /bin/sh that e.g. treats echo correctly. BTW: /bin/sh is not part of POSIX. POSIX rather requires you to do: export PATH=$(getconf PATH) followed by sh to get a POSIX shell. – schily Feb 27 '20 at 15:46
  • Never seen it with #!/bin/sh, because the POSIX standard mandates that /bin/sh is the standard (Bourne) shell. – vonbrand Feb 28 '20 at 16:26
  • @mosvy, which "99% of Unix installed" has no /bin/sh?! First off, that won't be able to get certified as Unix... And sorry, no Linux distribution has been certified as "Unix". Too much hassle for little gain. – vonbrand Feb 28 '20 at 16:28
  • 2
    @vonbrand 1. POSIX does NOT mandate the existence of /bin/sh. 2. Except for some obscure Chinese SUSE (or Centos?) fork(s) (iirc), no Linux system has ever been "certified" as Unix. –  Feb 28 '20 at 16:31
  • @mosvy.There are no Unix-certified OSes. There are OSes that have the UNIX brand. – fpmurphy Mar 04 '20 at 02:14
  • @mosvy Given that the use of a shebang is "unspecified" in POSIX: If the first line of a file of shell commands starts with the characters "#!", the results are unspecified. here. It is highly irrelevant what POSIX say or doesn't say about /bin/sh. But, for the record, it does specify in the APPLICATION USAGE od sh that the utility sh must be found with command -v sh. –  Jun 11 '20 at 20:42

2 Answers2

21

Setting to #!/bin/sh will go directly to that file /bin/sh.

Setting to #!/usr/bin/env sh will execute /usr/bin/env with an argument of sh. This will cause the script to be executed by sh in your PATH variable rather than explicitly with /bin/sh.

0

Many other posts (like the accepted answer of this one) mentioned that bin/sh in Solaris system (10 or older) is NOT a POSIX-compliant shell, instead, it is under /usr/xpg4/bin/sh.

In this case #!/bin/sh might not work properly if it meant to be POSIX-compliant. However, I doubt #!/usr/bin/env sh would point to the desired shell.