Hacker News new | ask | show | jobs
by silverlyra 1373 days ago
I used to work at a startup where one (1) engineer ran FreeBSD. When he joined, he sent a pull request editing the shebangs of all our shell scripts from #!/bin/bash to #!/usr/bin/env bash – because evidently FreeBSD has bash under /usr/bin, but all our systems agreed on where to put env.

I still write env bash shebangs to this day, in his honor. Happy to hear there's progress towards ending this archaic separation.

7 comments

The main reason to use env shebangs is versioning. MacOS ships Bash v3, but Homebrew installs Bash v5. Which shebang will you use - #!/bin/bash, #!/usr/bin/bash, #!/opt/homebrew/bin/bash, #!/usr/local/homebrew/bin/bash ? Same for different versions of Python (in venvs, pyenvs, etc) and other applications where you may want to run different versions. With the env shebang you can always change your PATH to choose your version.
If your script relies on specific version of bash you're doomed anyway.

It does make sense for your pythons and rubies but not really for bash.

Side note: zsh allows for #!bash but that's only interpreter I found that does that

That’s probably a good practice anyway. /bin/sh is guaranteed to exist, but there’s no reason to assume bash is installed at all. If it is installed, /usr/bin, /usr/local/bin, /opt/bin are all reasonable locations.
Even /bin/sh is not guaranteed to exist, and when it does exist, it is not guranteed to be useful. It is not a location specified by POSIX, and implementations exist that do not place the standard sh utility in /bin. The big one was SunOS/Solaris, where /bin/sh did exist but was the pre-POSIX implementation, and /usr/xpg4/bin/sh existed for when you wanted POSIX sh. Android puts it in /system/bin/sh and not all of them have the compatibility symlink /bin -> /system/bin. There are probably other special cases as well.

POSIX explicitly says "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 [...]"

And that’s the way it is in FreeBSD… /bin/sh exists, but it isn’t bash. Instead, bash must be installed by the user, and is thus installed in /usr/bin.
minor nit: /usr/local/bin as it comes from ports
It's sort of funny, AFAIK the usual way to effect the merger is to place a symlink from /bin to /usr/bin. This is how e.g. Arch Linux does it. So ironically, the archaic #!/bin/bash continues to work normally on /usr merged systems.
As a NixOS user, I thank you.
On slightly related subject what’s the best way to solve the shell path problem when you are using LDAP with the userShell attribute? If I create a user and set its shell to /bin/bash but that user logs into a system where bash is on another location (say MacOS or wathever)?
> FreeBSD has bash under /usr/bin

Worse: it’s in /usr/local/bin now (as ports are installed in /usr/local, by archaic convention).

How is that archaic? It's making a distinction between the operating system and add-on software. Bash is add-on software (not part of FreeBSD).
...the addon is distributed by FreeBSD. It's not 3rd part software.
Bash is distributed by GNU, not FreeBSD. FreeBSD distributes instructions for fetching, compiling, and packaging Bash (the ports tree and the Makefile for the bash package), but that is not the same as distributing Bash. Additionally, Bash is developed by GNU without being sponsored by FreeBSD; it is neither first- nor second-party software, leaving third-party software as the only option left.

To assume otherwise would have to assume that all ports come from FreeBSD and that's a bit absurd. I don't think anyone's going to say that Bash, or say KDE, is a "FreeBSD project" any time soon.

And all that just to point out that /usr/local on FreeBSD is intended for non-OS software installs (it's not the only option you have on the system, /opt isn't unheard of, but mixing up /usr/bin with non-OS software is a fast recipe for disaster).

Same for NixOS