Closed n8henrie closed 2 years ago
@toonn you had an uninstallation gist somewhere?
Short of fully uninstalling and reinstalling (whether via a gist from toon, or via iterative masochism...), I guess the other option is just logically stepping through and debugging things. Some ~starting thoughts:
/nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh
exists (I'm not 100% certain from phrasing if you confirmed that it is getting sourced, or just that the source line is in your rc). If it doesn't exist, I guess you don't have a default profile for some reason./Users/<username>/.nix-profile/bin:/nix/var/nix/profiles/default/bin:
. You might also find /run/current-system/sw/bin
in here, from nix-darwin.
env -i /bin/bash -x
, or editing set -x
into the top of /etc/bashrc and opening a new terminal tab/window (and then go remove set -x
before you forget). It should be enough to just search this for each instance of PATH=
./nix/var/nix/profiles/default/bin
) IS where your nix binaries should be after install, so confirm it exists and contains them. (/nix/var/nix/profiles/default
is a symlink into the store; I assume this will exist if the path in step 1 is present.)Thanks for your help!
Short of fully uninstalling and reinstalling
Isn't that what I'm doing? That's what I'm aiming for, and I'm following the official uninstall process AFAICT.
verify /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh exists
Yes, as noted it exists and I am manually sourcing it just to be sure (thought it's also in my ~/.bashrc
).
If it's getting sourced, it should be modifying your PATH (ref: https://github.com/NixOS/nix/blob/2.3-maintenance/scripts/nix-profile-daemon.sh.in#L38), so verify that it starts with /Users/
/.nix-profile/bin:/nix/var/nix/profiles/default/bin:.
This is not working.
$ source /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh && echo "$PATH" | grep -i nix || echo "not found"
not found
If PATH doesn't start with these, either nix-daemon.sh isn't actually getting sourced or something is over-writing the PATH later.
As a less spammy alternative, I just added the following to my .bashrc
and launched a new terminal window, which outputs "not found" at the top.
if [ -e '/nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh' ]; then
. '/nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh'
echo "$PATH" | grep -i nix || echo "not found"
fi
That should mean that /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh
exists, is getting sourced, and isn't updating the path (since I'm checking immediately afterward). Right?
Here's the Gist but I think you're getting everything relevant, only missing the build users but they shouldn't interfere with a reinstall.
Maybe set -x
in one of the rc files can help verify nix-daemon.sh
is being sourced properly?
EDIT: I'd missed that second LaunchDaemon you found btw, thanks : )
Maybe set -x in one of the rc files can help verify nix-daemon.sh is being sourced properly?
I'm sourcing it manually with no change. I've also added a few debug echo
s to nix-daemon.sh
; I can see that they are getting run, and that the PATH
does get changed (EDIT: PATH
is getting changed within the script, not outside).
Ok, I think I'm on to something -- the problem is:
# Only execute this file once per shell.
if [ -n "${__ETC_PROFILE_NIX_SOURCED:-}" ]; then return; fi
__ETC_PROFILE_NIX_SOURCED=1
I do override PATH
in my .bashrc
(adding a bunch of stuff to it for pyenv, rust, go, etc.). And I was sourcing this in my .bashrc
.
But it looks like on a multi-user build, it's sourcing /etc/bashrc
, which sources nix-daemon.sh
, then sources ~/.bashrc
, which I have set to source nix-daemon.sh
, and then overrides PATH
, which I didn't think would be an issue since it's also sourcing nix-daemon.sh
. However, I'm guessing the second source isn't working because of the above. Let me tinker.
Yup, that seems to be the issue.
In my .bashrc
, I start near the top with PATH=$(getconf PATH)
, then build up the PATH
, then finally export it at the end. I do it this way because otherwise $PATH
gets longer and longer every time I re-source my .bashrc
, which drives me nuts.
Sourcing nix-daemon.sh
manually (or in ~/.bashrc
) isn't working because __ETC_PROFILE_NIX_SOURCED
is set.
I think I should be able to sort out a workaround, though I wonder if less surprising mechanism than __ETC_PROFILE_NIX_SOURCED
might be just checking for .nix-profile/bin
in PATH
; if it's not there, then continue. It doesn't look like any of the other variables are appended (only set); if mutating PATH
is the only side effect of sourcing this script, shouldn't checking PATH
be a reasonable indicator of whether it should run again?
Here's my workaround, put in my ~/.bashrc
, which allows me to keep the PATH
modifications.
# Nix
if [ -e '/nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh' ]; then
# if PATH does *not* contain `~/.nix-profile/bin`
if [ -n "${PATH##*.nix-profile/bin*}" ]; then
# If this flag is set, `nix-daemon.sh` returns early
# https://github.com/NixOS/nix/issues/5298
unset __ETC_PROFILE_NIX_SOURCED
. '/nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh'
fi
fi
# End Nix
Fixed.
$ nix-env --version
nix-env (Nix) 2.3.15
Thanks again!
This discussion prompted me to evaluate my own ${PATH}
because none of the nix-*
commands were available after what looked like a successful installation. Sure enough, my dotfiles were doing something to my path to ensure it started from scratch and would be built manually, because in the past some undesirable software insisted on automatically adding itself to the path. Thanks for the research!
By the way, @n8henrie, you wrote:
In my .bashrc, I start near the top with PATH=$(getconf PATH), then build up the PATH, then finally export it at the end. I do it this way because otherwise $PATH gets longer and longer every time I re-source my .bashrc, which drives me nuts.
I do something similar, but for other reasons. Nevertheless, it sounds like you want to use a general pathmunge
function, that is common on a lot of Linux distributions. Here's a conversation that may be of interest to you: https://unix.stackexchange.com/a/124461
For those also using nix-darwin, nix-darwin uses __NIX_DARWIN_SET_ENVIRONMENT_DONE
in a similar way. Additionally, /etc/static/bashrc
looks for __ETC_BASHRC_SOURCED
; if this is set, it never even gets to the point of checking for the former.
Unfortunately, if you just unset
these additional vars like I recommended above, nix-darwin completely resets your path in /nix/store/wj547wd30qdpjy6kmm1fx4a6p46j0dp8-set-environment
:
export PATH=$HOME/.nix-profile/bin:/run/current-system/sw/bin:/nix/var/nix/profiles/default/bin:/usr/local/bin:/usr/bin:/usr/sbin:/bin:/sbin
To work around all this (without my PATH growing longer and longer), I initially tried putting a PATH
deduplicator (in spirit like @danemacmillan recommended above) at the end of my .bashrc
:
PATH=$(awk -v RS=: '!seen[$0]++' <<< "${PATH}" | sed '/^$/d' | paste -s -d:)
export PATH
This was taking ~5ms on my machine. Eventually, I figured out that a likely more robust / future-proof method would be to just spawn a clean subshell, source /etc/static/bashrc
, and output the PATH
EDIT: Resetting the enivornment unfortunately meant that ~/.nix-profile/bin
wasn't getting added to my PATH
(due to lack of HOME
), so I added HOME
back to the env and it works better now.
# Nix
if [ -e '/nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh' ]; then
NIXPATH=$(
env --ignore-environment HOME="${HOME}" sh -c '
source /etc/static/bashrc
echo "${PATH}"
'
)
PATH+=${NIXPATH}
fi
# End Nix
It looks like this adds roughly the same amount of time, perhaps just a smidge faster
hyperfine $'env --ignore-environment sh -c \'source /etc/static/bashrc; echo "${PATH}"\''
Benchmark 1: env --ignore-environment sh -c 'source /etc/static/bashrc; echo "${PATH}"'
Time (mean ± σ): 4.1 ms ± 0.7 ms [User: 1.0 ms, System: 1.4 ms]
Range (min … max): 2.8 ms … 9.8 ms 351 runs
Also, please note that I am appending the nix path to the end of my path: PATH+=${NIXPATH}
whereas others probably want to follow the recommended approach of prepending: PATH=${NIXPATH}:${PATH}
; I'm doing so because as noted above nix-darwin
includes /usr/local/bin:/usr/bin:/usr/sbin:/bin:/sbin
; prepending this to my PATH
would put the MacOS BSD utils before the homebrew GNU utilities I'm used to.
EDIT: Alternatively, I suppose I could replace my getconf PATH
from above with the PATH-overwriting command from this comment, which would serve the same purpose and shave off a couple ms.
EDIT2: For some reason EDIT1 doesn't work; MacOS is persisting the relevant environment variables even when I completely close out tmux, kill all sessions, and close out Terminal.app, so that nothing is re-sourced with a new shell. I don't get it.
A little oblique, but I've been trying to think out loud about improvements when opportunities present:
Describe the bug
I had a previous single-user install. I couldn't get nix-darwin working, so I wanted to retry with a multi-user install. After an uninstall and reinstall, when I try
nix-shell -p nix-info --run "nix-info -m"
I get-bash: nix-shell: command not found
.I have confirmed that I am sourcing
/nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh
and that the launchdaemon is running.Steps To Reproduce
For uninstallation: https://nixos.org/manual/nix/stable/#sect-multi-user-installation
launchctl list | grep -i nix; sudo launchctl list | grep -i nix
showed a straggler, so I also added:Also, after my first few attempts I started adding the below to avoid issues in the installation step:
Afterwards, from https://nix.dev/tutorials/install-nix#macos:
Expected behavior
Installation process at https://nix.dev/tutorials/install-nix#macos and https://nixos.org/manual/nix/stable/#sect-multi-user-installation to result in a working installation.
nix-env --version
outputAdditional context
I ran
diff /etc/bashrc /etc/bashrc.backup-before-nix
and added the following to my~/.bashrc
to see if that would fix a suspectedPATH
issue:I can see several relevant envvars in
$ env | grep NIX
, but still command not found.It ends up on my path if I run:
Also works with
$ /opt/homebrew/bin/bash --noprofile --norc
, or withsudo su
, sourcing thenix-daemon.sh
afterward each time, so it's obviously a problem with my local configuration. It doesn't work withsudo /bin/bash
, so it seems less likely to be a permission / root profile thing. I think.I thought it might be related to
~/.nix-profile
(which was deleted in the uninstall step) being a broken symlink;/nix/var/nix/profiles/per-user/n8henrie/profile
doesn't exist, only/nix/var/nix/profiles/per-user/root
, butsudo nix-env --version
also doesn't work, and when I use the--noprofile --norc
workaround, it is still a symlink to nowhere.Trying to pick through the MacOS threads at https://discourse.nixos.org/t/anyone-up-for-picking-at-some-nix-onboarding-improvements/13152/6, not much luck yet.
Searching the issues shows a lot of open / unresolved / marked stale problems with MacOS. The most relevant handful I've found: