Is there an argument against having /bin/bash that I’m not thinking of? It seems like dogmatism over pragmatism, but perhaps there’s a previous discussion that I did not find with a search.
Edit: is there any reason not to do sudo ln -s /run/current-system/sw/bin/bash /bin/bash?
IIRC, /bin/sh and /usr/bin/env were added due to POSIX compliance.
Pretty dogmatic, but it’s a form of global system state. Could have issues with bash_4 vs bash_5, etc. Ultimately, most programs shouldn’t assume filepaths (Yes, I’m aware shebangs needs an absolute path).
Not sure how persistent this is with nixos-rebuild.
If you want a quick hack, you could always do nix-shell -p steam; steam-run <prog>
It can be a pain, but most upstream maintainers are willing to accept a patch that moves them from /bin/bash to /usr/bin/env bash, and if they aren’t a great thing about Nix is that it’s trivial to patch their software That’s the sort of patch that’s unlikely to bitrot with merge conflicts, as well.
Unfortunately it’s not always that simple. For example, in the issue I linked it’s a .jar file, which as I understand means re-compiling from scratch. My symbolic link was a few second fix, while packaging this software for NixOS would take me at least an hour. Upstream maintainers are often incredulous when this issue is reported. Even with upstream willingness, there are often valid reasons not to switch to /usr/bin/env bash–namely lack of support for multiple arguments.
POSIX specifies that env should exist, but not the path itself, so /usr/bin/env is usually present, just as /bin/bash is usually present.
A quick search shows more than 5,000 issues on github for NixOS & /bin/bash. It seems like this is just a waste of everyone’s time with no derived benefit, outside of some noble feeling of purity.
Java .jar files are just archives (Java ARchive) so extract, change and repack, but the problem in this case might require at least recompiling that file, as the string is embedded in a compiled .class file (as opposed to say a text file in a .jar archive).
But I do also feel like we might be more than a bit annoying with not having /bin/bash. However, I think if we do end up with having ‘/bin/bash’, it needs to be compatible with the macOS bash which is version 3.2.57 (due to licensing issues with newer bash)
I think a good design decision would be to have a user configurable /bin/bash. That way those that care for macOS compatibility could choose 3, most of us could choose 5, and those that were so inclined could elect to have none at all.
I wholeheartedly like and appreciate that NixOS’s /bin is so sparse, but bash is a special case used by many in the same way as /bin/sh
The problem with that is then we won’t be reproducible, e.g. suppose we have /bin/bash in one computer, and none in another. If the package maintainer uses /bin/bash and the user doesn’t then the package won’t work. Worse with multiple versions, supposing (this is a silly conjecture but the principle holds) that the only terminal emulator requires bash 3 at runtime, and the only text editor requires bash 5 at runtime and both are incompatible… In reality it’s probably not this serious, but we still want to avoid stuff like this.
Caveat: We probably do some of this by using /bin/sh but perhaps in theory only rely on a minimum compatible set of features?
In reality the Bash API is highly stable and backwards compatible. The vast majority of scripts that ran on bash 4.4 will also run on Bash 5.0. I’ve personally never encountered a situation where a script didn’t run because it was designed for an earlier version of bash. You do occasionally hear issues with mac users, but that’s a very different situation of being on an old version of bash lacking features used in modern scripts.
On the reproducibility spectrum between instruction set versions and python versions, bash is much closer to instruction sets.
True, but the mac issue will happen, especially if we make the bash version selectable. What I am saying, is that if we make this a thing, we then have to make it a thing for all installations with the same bash version[1]. And we need version compatibility both ways[1]. Otherwise I could write a derivation that works on my system because I have /bin/bash, but won’t work on your system if you don’t have /bin/bash (either build time or run time)!
[1] Okay, the same version thing is an impurity we already have, i.e. the caveat of /bin/sh can be different on non-NixOS installations. E.g. if I do
$ nix-shell --pure -A bash # or something
nix-shell $ /bin/sh --version
# I get 3.2.57(1)-release on mac
# I get 4.4.23(1)-release on NixOS 19.09
@KoviRobi we could still require that submissions to nixpkgs do not depend on /bin/bash for purity reasons if we want users to be able to ‘opt-in’ to /bin/bash on NixOS without forcing it on everyone.
Otherwise, defaulting to Bash 4.4 seems reasonable given that all of nixpkgs uses this. bash_5 is not used anywhere, and Bash 3 is not in nixpkgs.
@KoviRobi we could still require that submissions to nixpkgs do not depend on /bin/bash for purity reasons if we want users to be able to ‘opt-in’ to /bin/bash on NixOS without forcing it on everyone.
The problem is that then PR feedback from people who opted in to having /bin/bash will become slightly suspect, sometimes without the person doing the testing realising it.
Completely agreed. One thing I really appreciate about NixOS is reproducibility on bug reports. I think /bin/bash and things like that which compromise reproducibility would have such a big impact that in the worst possible way. It’s almost as if NixOS becomes 2 distros at that point.
Sure, but then it still applies for a program’s runtime, should that use /bin/bash. Arguably we should have replaced all /bin/bash instances in the fixupPhase.
In reality the Bash API is highly stable and backwards compatible. The
vast majority of scripts that ran on bash 4.4 will also run on Bash
5.0. I’ve personally
never encountered a situation where a script didn’t run because it was
designed for an earlier version of bash.
I have, and it was in fact the Nixpkgs stdenv, which doesn’t work (or
didn’t at the time, with Bash 5).
We actually need to go the other way and explicitly allow /bin/bash in the sandbox on macOS in order to fix sandbox compatibility with macOS Catalina as /bin/sh on Catalina now executes /bin/bash (it’s got a mechanism by which it can execute bash or zsh depending on certain other global configuration; if that other config is unreachable, e.g. because the sandbox is on, it defaults to /bin/bash).
eew, that‘s kinda disgusting. So that means #!/bin/sh doesn‘t necessarily mean a script needs to be strictly POSIX-compliant?
Anyway it would be great if there was a way to restrict anything in /nix from touching /bin/bash, while stuff anywhere else can use it.
Maybe make /bin/bash a wrapper script which does something like
if [ comesfromnix ]; then
echo "programs from the nix store aren't allowed to use this file, please patch the code!"
exit 1
fi
/run/current-system/sw/bin/bash "$@"
This could also easily be extended to e.g. warn the user when this wrapper is used for the first time…
When /bin/sh invokes /bin/bash on macOS it still does so with argv[0] == "sh", meaning bash still runs in POSIX sh mode.
Edit: I also forgot to mention, on macOS 10.14 and below, /bin/sh is literally just bash with a different name (for some reason it’s 64 bytes larger than /bin/bash though). You can verify this with /bin/sh -c 'echo $BASH_VERSION'. So what macOS 10.15 is doing now isn’t functionally different except in that the sandbox needs to allow access to /bin/bash.