NixOS / nixpkgs

Nix Packages collection & NixOS
MIT License
18.19k stars 14.19k forks source link

mkShell broken when no nixpkgs flake or in NIX_PATH, and system's bash < 4.4 #155706

Open bew opened 2 years ago

bew commented 2 years ago

Describe the bug

On a non-NixOS distrib, when there is no nixpkgs in the flake registry or in $NIX_PATH, nix-shell falls back to the bash in the system.

When the bash version is 4 (like on CentOS7), I get the error: bash: shopt: inherit_errexit: invalid shell option name (see reproduction steps for more)

NOTE: I removed nixpkgs from the registry to always ensure I use my pinned version, and I have full control on where my packages comes from. No hidden global state!

Steps To Reproduce

Steps to reproduce the behavior:

  1. Write a simple mkShell invocation:

    In a file foo.nix:

    let
     nixpkgs = builtins.getFlake "pkgs"; # this is the name of my own nixpkgs flake, pinned appropriately
     pkgs = nixpkgs.legacyPackages.x86_64-linux;
    in pkgs.mkShell {
     packages = [
       pkgs.just
     ];
    }
  2. Running nix-shell foo.nix I get:

    $ nix-shell foo.nix
    error: file 'nixpkgs' was not found in the Nix search path (add it using $NIX_PATH or -I)
    
          at «string»:1:9:
    
               1| (import <nixpkgs> {}).bashInteractive
                |         ^
    will use bash from your environment
    
    bash: shopt: inherit_errexit: invalid shell option name
  3. => I'm back to my initial shell, It didn't enter the nix-shell.

Expected behavior

Enter the nix-shell without error!

Additional context: bash version

$ bash --version   # binary is in /usr/bin/bash
GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
...

Additional context: PR introducing the failing option

The inherit_errexit shell option was added in #139508.

It's set unconditionally: https://github.com/NixOS/nixpkgs/blob/82500ee3bc3f8c36a7f95bd9b8a076139ab1039d/pkgs/stdenv/generic/setup.sh#L3-L9 And proceeds to check the bash version is >= 4 just after.

My take would be to set this option only for bash version > 4. (or whatever version this was added in)

Notify maintainers

Metadata

$ NIX_PATH=nixpkgs=channel:nixos-21.11 nix-shell -p nix-info --run "nix-info -m"
 - system: `"x86_64-linux"`
 - host os: `Linux 3.10.0-1160.2.2.el7.x86_64, CentOS Linux, 7 (Core)`
 - multi-user?: `no`
 - sandbox: `no`
 - version: `nix-env (Nix) 2.4pre20211006_53e4794`
 - channels(cloud-user): `"legacy-nixpkgs-channel-21.05.4116.46251a79f75, nixos-20.09-20.09.1884.80666202999"`
 - nixpkgs: `/nix/store/2wlj55g2gppcgr2mzsvbblsapnsqp8kd-source`
happysalada commented 2 years ago

oh and centos7 is still 2 years away from end of life. Do you want to add a guard for bash version 4 ? Sorry about the breakage!

bew commented 2 years ago

Do you want to add a guard for bash version 4 ?

Yes I think that would be enough, and maybe move this after the bash version >=4 check. The option have been added in 4.4 (ref), not sure how to test for this, maybe there's a way to check if the option exists?

I'm not familiar with making large-impact changes like this on stdenv, so i would prefer not to do/try it..

happysalada commented 2 years ago

actually the best might be to just ignore errors on that command. Probably add a comment to remove that when centos7 goes end of life.

happysalada commented 2 years ago

something like adding 2>&1 || true

bew commented 2 years ago

something like adding 2>&1 || true

This seems to work indeed when I do the change locally (and it tries to rebuild the world...)

happysalada commented 2 years ago

Just for information, usually the process to making a PR to stdenv is make a PR against the staging branch with your changes. People will review it, and then it gets added to the list of changes on the next staging-next iteration. Problems sometimes appear during the staging-next PR (which is just a group of staging changes together in a PR). You don't need to try to rebuild everything on the PR as it would build too much, usually, you try to build a basic dependency like perl and if that works, then you leave the rest of the build to the staging-next PR.

soulomoon commented 2 years ago

similar error here in m1 macos.

nix-shell -p nix-info --run "nix-info -m" -I nixpkgs=https://github.com/NixOS/nixpkgs/archive/master.tar.gz
/nix/store/2j6pxz2dk7xx0jw6jc60rizk46i4r5v1-stdenv-darwin/setup: line 20: shopt: inherit_errexit: invalid shell option name
/private/tmp/nix-shell-50792-0/rc: line 1: rm: No such file or directory

update bash solved it

happysalada commented 2 years ago

@soulomoon what is the default bash version running on m1 ? I thought they didn't have bash anymore. Just curious.

soulomoon commented 2 years ago

@happysalada that would be bash 3.2 (

happysalada commented 2 years ago

Actually now that I think about it, there are things later in stdenv that do require a modern version of bash. Perhaps the best here would be to check on the version and exit early with a helpful message. My only problem is that stdenv runs with both sh (in the bootstrapping stage) and bash (after bootstrapping). So the function would need to take the 2 things into account. I'm going to think about this and try to find time next weekend.

JaviMerino commented 2 years ago

I have run into the same issue:

$ echo ${BASH_VERSION}
4.2.46(2)-release
$ nix-shell -p nix-info
this path will be fetched (0.00 MiB download, 0.00 MiB unpacked):
  /nix/store/ym0rxxcd2kjcfbazpv7kqyk2mjfmihna-nix-info
copying path '/nix/store/ym0rxxcd2kjcfbazpv7kqyk2mjfmihna-nix-info' from 'https://cache.nixos.org'...
/nix/store/523zlfzypzcr969p058i6lcgfmg889d5-stdenv-linux/setup: line 14: shopt: inherit_errexit: invalid shell option name
/tmp/nix-shell-4449-0/rc: line 1: rm: No such file or directory

I can't update bash. Is there anything else I can do?