Shebang locations

Annoyingly, that also changes the file type for file. It’s not env-aware.

POSIX in fact reccomends that you change your script’s shebang for every system you install it on:

Applications should note that the standard PATH to the shell cannot be assumed to be either /bin/sh or /usr/bin/sh, and should be determined by interrogation of the PATH returned by getconf PATH , ensuring that the returned pathname is an absolute pathname and not a shell built-in.

For example, to determine the location of the standard sh utility:

command -v sh

On some implementations this might return:

/usr/xpg4/bin/sh

Furthermore, on systems that support executable scripts (the “#!” construct), it is recommended that applications using executable scripts install them using getconf -v to determine the shell pathname and update the “#!” script appropriately as it is being installed (for example, with sed).

Which is contrary to the myth that’s often repeated when this comes up that /bin/sh is fine because sh is mandated to be available according to POSIX. Though /bin/sh will actually work on NixOS.

That means strictly, the “correct” fix is to install the scripts using buildShellApplication, writeShellScriptBin or a stdenv.mkDerivation, as all of those will replace the shebang.

Alternatively you can also symlink /bin/bash into place, of course… Here’s the development discussion on that: Add /bin/bash to avoid unnecessary pain - #3 by bhipple

To explain the argument of “purity” a bit better, the fear is that, if a package executes /bin/bash accidentally at build time, this could result in build failures due to bash version changes. Since nix doesn’t sandbox the build env on all supported platforms this is a real concern. That said, NixOS does sandbox the build env, and if you install nix on other platforms this can’t be prevented anyway, so maybe it’s a moot point nowadays?

2 Likes