NixOS / nixpkgs

Nix Packages collection & NixOS
MIT License
18.28k stars 14.26k forks source link

`/bin/sh` & `/run/current-system/sw/bin/sh` is symlinked to a shell with bash-isms #74627

Open 06kellyjac opened 4 years ago

06kellyjac commented 4 years ago

Describe the bug

Why is /bin/sh linked to bash instead of a "real" sh? https://github.com/NixOS/nixpkgs/blob/0c3a28f08f207a0b074d5ecbbed21b5b045f690f/nixos/modules/config/shells-environment.nix#L139-L140

If bash is truly needed it should refer to /usr/bin/env bash or I guess /bin/bash if it was added alongside existing /bin/sh?

I've seen several explanations saying /bin/sh exists because POSIX requires it (sounds like compliance to me) but /bin/bash isn't required so it doesn't exist on nixos systems to make it visible when things try to hit /bin/bash and help map dependencies ... https://discourse.nixos.org/t/thoughts-from-a-new-nixos-user/2135/14 But then /bin/sh isn't the actual POSIX compliant sh and is in-fact non-POSIX compliant GNU Bash. So you can erroneously list a sh dependency but due to using double square brackets [[ you'd actually have a bash (or some other shell that supports [[).

If someone could give me an explanation as to why this is the case that'd be great.

To Reproduce Steps to reproduce the behavior:

[x@nixos:~]$ sh -c 'if [[ $HOSTNAME == test ]]; then echo fail &> foo; fi'

[x@nixos:~]$ bash -c 'if [[ $HOSTNAME == test ]]; then echo fail &> foo; fi'

[x@nixos:~]$ dash -c 'if [[ $HOSTNAME == test ]]; then echo fail &> foo; fi'
dash: 1: [[: not found

[x@nixos:~]$ docker run -it debian:buster-slim /bin/sh -c 'if [[ $HOSTNAME == test ]]; then echo fail &> foo; fi'
/bin/sh: 1: [[: not found

Expected behavior

I expect /bin/sh (and /run/current-system/sw/bin/sh) to not have bash-isms. If bash is needed can't we just use /usr/bin/env bash or add a /bin/bash symlink etc... (I have seen methods to change /bin/sh [with the warnings] but it seems like there's no official way to swap out /run/current-system/sw/bin/sh and I'd guess it'd be even more potentially destructive)

It seems very arbitrary that /bin/bash shouldn't exist to help map dependencies but if I have a module with bash scripts hitting sh everything will still run just fine and there's no proper dependency mapping there. And that's excluding the principal that POSIX required shell should probably be a POSIX shell so that I can easily swap it out for something else like dash as you'd expect if all dependencies are mapped. The fact that I can't put a POSIX shell in the position of /bin/sh means that dependencies simply are not being mapped in this case.

Anyway I'd love to hear peoples thoughts. I haven't been around nixos that long so I can't exactly waltz in and assert this is now nixos should be to meet its mission statement. If nixos is commited to treating /bin/sh as a bash shell then I guess I'll just swap out sh at the level of my user rather than at the system level.

danbst commented 4 years ago

As far as I know this is more of pragmatic convention, rather than principal decision. Related https://github.com/NixOS/nixpkgs/issues/1424#issuecomment-60229282

Purifying nixpkgs from bashisms is fine in what you've described. The main problem is actually make it work, and to find nixpkgs maintainers who would like to review such purifications. For example, to test this one should setup an extra Hydra jobset to rebuild world with /bin/sh pointed to dash.

We occasionally get /bin/sh problems with some packages, which don't expect Bash being there. So far it wasn't very common issue, maybe that's why it is not pursued by maintainers.

I haven't tried replacing /bin/sh with dash. Have you tried? Does system build/work fine?

7c6f434c commented 4 years ago

We occasionally get /bin/sh problems with some packages, which don't expect Bash being there. So far it wasn't very common issue, maybe that's why it is not pursued by maintainers.

All problems I have seen were caused by /bin/sh not being Bash, and they were numerous enough that the decision was to not care and use Bash again.

I haven't tried replacing /bin/sh with dash. Have you tried? Does system build/work fine?

Note that one can replace the normal /bin/sh and the build sandbox /bin/sh separately

stale[bot] commented 4 years ago

Thank you for your contributions.

This has been automatically marked as stale because it has had no activity for 180 days.

If this is still important to you, we ask that you leave a comment below. Your comment can be as simple as "still important to me". This lets people see that at least one person still cares about this. Someone will have to do this at most twice a year if there is no other activity.

Here are suggestions that might help resolve this more quickly:

  1. Search for maintainers and people that previously touched the related code and @ mention them in a comment.
  2. Ask on the NixOS Discourse.
  3. Ask on the #nixos channel on irc.freenode.net.
emilysnow2477 commented 4 years ago

This is still important to me, symlinking /bin/sh to something like dash would yield better system performance. Ubuntu has done this since version 6.10 (though the process for NixOS would undoubtedly be a bit different).

https://wiki.archlinux.org/index.php/Dash#Use_DASH_as_/bin/sh https://wiki.ubuntu.com/DashAsBinSh https://askubuntu.com/questions/976485/what-is-the-point-of-sh-being-linked-to-dash

rnhmjoj commented 4 years ago

Do you know where is the symlinking of /bin/sh happening in NixOS? I couldn't find it anywhere in the sources. I'd like to switch to dash as default and try to identify and solve portability problems in scripts.

06kellyjac commented 4 years ago

There's this option that lets you replace the /bin/sh symlink on your nixos machine

https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/config/shells-environment.nix#L129-L143

But every file that was #!/bin/sh or #!/usr/bin/env sh etc will still be patched to go to #!/nix/store/BLAH-bash-BLAH/bin/sh when installed from nixpkgs

IIRC when I had the option on even sh in my env still went to the one inside bash's nix store. So the only thing that would actually use dash are scripts you write to point at #!/bin/sh, even #!/usr/bin/env sh would go to the bash one

rnhmjoj commented 4 years ago

Thank you, I'll give it a try.

stale[bot] commented 3 years ago

I marked this as stale due to inactivity. → More info