Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"nvm: command not found" when in sub-shell #521

Closed
fresheneesz opened this issue Sep 8, 2014 · 36 comments
Closed

"nvm: command not found" when in sub-shell #521

fresheneesz opened this issue Sep 8, 2014 · 36 comments

Comments

@fresheneesz
Copy link
Contributor

After installing nvm and restarting my terminal, I can run nvm fine normally. But if I create a new shell (either with sh or bash) nvm gives me back "command not found". Why can't my inner shell see nvm?

I'm on Centos 6.5, and installed nvm with the basic curl install.

@ljharb
Copy link
Member

ljharb commented Sep 8, 2014

If you re-source nvm.sh (ie . ~/.nvm/nvm.sh) does it work?

Using a true subshell - ie, with $(foo), nvm should work - but if you just launch a brand new shell that doesn't source ~/.bashrc, I'd expect it not to have nvm available.

@fresheneesz
Copy link
Contributor Author

Hmm, if I try using ~/.nvm/nvm.sh it gives me "permission denied" with both bash and sh.

@ljharb
Copy link
Member

ljharb commented Sep 8, 2014

What's echo $NVM_DIR print out?

@fresheneesz
Copy link
Contributor Author

Prints out /home/vagrant/.nvm both in the main shell and in the sub-shell.

@fresheneesz
Copy link
Contributor Author

But that's the same location as ~/.nvm/nvm.sh - it gives me "permission denied" either way i do it (with ~ or explicitly with /home/vagrant/..). Sorry I wish I could help debug more, but I'm no linux wizard - more of a js wizard ; )

@ljharb
Copy link
Member

ljharb commented Sep 8, 2014

@fresheneesz Can you try rerunning the installation step from the README? Specifically, curl https://raw.githubusercontent.com/creationix/nvm/v0.15.0/install.sh | bash.

Hopefully you installed it this way to begin with, and not with something like homebrew, or npm (the nvm on npm is actually a different package)

@fresheneesz
Copy link
Contributor Author

@ljharb That is in fact the way I installed it (specifically with the curl command and not wget). But, I ran it again. Even tho nvm already worked after it ran, I reconnected anyways. In a sub-shell, nvm still gives me "command not found" and "~/.nvm/nvm.sh" still gives me permission denied.

@ljharb
Copy link
Member

ljharb commented Sep 9, 2014

Wait, are you trying to execute ~/.nvm/nvm.sh or source it? Note the leading dot: . ~/.nvm/nvm.sh

@fresheneesz
Copy link
Contributor Author

I don't know what you mean by "source it". When I run it with the dot, I don't get an error, but I don't get anything else either. Blank response. Its the same for both normal shell and subshell.

@ljharb
Copy link
Member

ljharb commented Sep 9, 2014

Yes, that's the exact and intended behavior. After running it with the dot, try nvm --help. It should work.

nvm.sh is not executable - "sourcing" it means, include its contents in your shell, which means, make the nvm shell functions available for use in the current shell.

@creationix
Copy link
Collaborator

Wait, nvm,sh doesn't need to be marked executable. That only confuses people thinking they should execute it instead of source it.

@ljharb
Copy link
Member

ljharb commented Sep 9, 2014

Yes, sorry, I realized my mistake and pushed for sourcing it later in the thread :-)

@fresheneesz
Copy link
Contributor Author

Holy cow it works.

bash
. ~/.nvm/nvm.sh
nvm

gives me the nvm help notes. Still wondering why "sourcing" it is necessary at all tho. Seems strange to me. Any way to upgrade nvm so that it doesn't need that?

Do you think this method would allow me to run nvm after freshly installing it without restarting my console?

@ljharb
Copy link
Member

ljharb commented Sep 9, 2014

Sourcing is the primary way nvm works - it's a suite of shell functions.

Yes, that should work without restarting your shell - doing so is just a way to guarantee that nothing weird is going on.

@ljharb ljharb closed this as completed Sep 9, 2014
@fresheneesz
Copy link
Contributor Author

@ljharb sure, it may be the primary way nvm works, but can we add something that sources nvm at the end of the install script, so people don't have to restart their console? And is there a way to automatically source nvm on creation of new shells? I'm running a shell script from a node.js program, and its very unexpected to see that nvm isn't available in that context.

@ljharb
Copy link
Member

ljharb commented Sep 9, 2014

@fresheneesz That's how the install script already works on every platform I have available to test. It's possible that it has an issue with CentOS 6.5, however. See #394 for a possible solution.

@creationix
Copy link
Collaborator

@fresheneesz nvm is not a bash script or any kind of shell script. It's a bash function. This means it only lives in your transient shell environment. Most people (and the install script) put a line in their .bashrc or .profile to have it auto-sourced every time a new interactive shell is created, but there is no way to inject itself into newly created sessions that explicitly don't inherit environment from their parent and don't source hooks like .bash_rc. If you want to use nvm in an environment that can't source your .bashrc or .profile, then you'll need to manually source nvm yourself before calling it's functions. I hope this makes sense.

@creationix
Copy link
Collaborator

The reason that nvm is a shell function and not a script is because it works by changing the environment of your current shell. This is a major design decision and the thing that makes nvm different from n and nave. n works by creating global symlinks to different node versions. nave works by creating a new subshell with the desired env modifications. I decided to go the less intrusive route and only modify the current shell. Mostly it just mucks around with $PATH so that the desired version of node is first on the path. Other shells can concurrently use their own local node version unmolested. I do this without the overhead of creating new subshells or changing global paths.

Only shell functions can do what I want. The major drawback obviously is it confuses people who think nvm.sh is a shell script meant to be run in a subshell like every other sh file they've seen. I'm sorry for the confusion but it is what it is. Subshells can't modify their parent's environment.

@fresheneesz
Copy link
Contributor Author

Got it, thanks for the help guys!

@daryltucker
Copy link

Hmm. On Ubuntu and noticing I have to manually chmod +x ~/.nvm/nvm.sh to get nvm and node and npm working correctly.

Edit: Don't do this.

@ljharb
Copy link
Member

ljharb commented Jul 7, 2015

@daryltucker hmm, how did you install nvm in the first place?

@daryltucker
Copy link

Hey @ljharb

Using the README. After install, I was running into issues and trying to diagnose why I had to source the file every time I opened a new terminal.

I later realized it was that I had to do nvm alias default stable (and that it was NOT a sourcing issue) in order to have a default nvm. This wasn't straight forward in other documentation and it wasn't until I used the official README that I discovered this.

I assumed nvm use WHATEVER would have set my nvm until I issued that command again. Now I understand why this isn't true.

Sorry for the confusion, and I just removed the executable flag from that file, making sure it works 100% as expected.

@ljharb
Copy link
Member

ljharb commented Jul 8, 2015

Great, thanks for the explanation.

I'm likely to soon change the default behavior so that the first nvm install without a default alias set or .nvmrc version found will set the default alias for you - that would have likely eliminated your confusion.

@shiretu
Copy link

shiretu commented Jul 17, 2017

I have found what the issue is. The nvm script has some inconsistencies inside it. here is why:

Working. The script:

#!/bin/sh

. ${NVM_ENV_SH}
nvm help

Using it:

$ sh test.sh; echo $?
......
0

Not working (blank output, error code 3). The script:

#!/bin/sh

#error on anything
set -e

. ${NVM_ENV_SH}
nvm help

Using it:

$ sh test.sh; echo $?
3

@ljharb
Copy link
Member

ljharb commented Jul 17, 2017

What's $NVM_ENV_SH?

@ljharb
Copy link
Member

ljharb commented Jul 17, 2017

Breaking when set -e is enabled isn't "inconsistencies" ftr; nvm.sh isn't yet fully compatible with set -e in all scenarios.

@shiretu
Copy link

shiretu commented Jul 17, 2017

@ljharb: $NVM_ENV_SH is a variable holding the path to the nvm.sh, the file it needs to be sourced.

The issue is that I'm trying to use it in the middle of shell script forest/stack, which are all coded with set -e. Btw, my personal opinion, that is a very good thing: crash early, rather than limping along.

@ljharb
Copy link
Member

ljharb commented Jul 17, 2017

Yes, noted, but in the meantime, set +e; . ${NVM_ENV_SH}; set -e; is a fine workaround.

@shiretu
Copy link

shiretu commented Jul 17, 2017

@ljharb: yes, was thinking at something similar. I will probably end up wrapping that into its own script, and do all the +e/-e dance in there. So when the upstream fix is in, I will not have to hunt down all occurrences.

Thanks for confirming it tho. Greatly appreciated. Feel free to close this one.

@shiretu
Copy link

shiretu commented Jul 17, 2017

Oh, it is closed :)

@junchaw
Copy link

junchaw commented Dec 27, 2017

In my case, my VPS host added these lines in .bashrc when creating the server:

# If not running interactively, don't do anything
case $- in
    *i*) ;;
      *) return;;
esac

I just comment it, hope it can help.

@chingc
Copy link

chingc commented Oct 18, 2020

I'm sorry to dig up an old thread. I just wanted to say thanks because this helped me solve my issue. That said, it's a problem that I always run into occasionally because enough time passes that I forget the solution.

I was wondering, why does nvm have to source itself through my bash profile, or manually as in the case described in this ticket, every single time? Why can't nvm set itself up as an executable script in my existing $PATH like most other programs?

@ljharb
Copy link
Member

ljharb commented Oct 18, 2020

@chingc because it needs to modify the PATH in the current shell, and that's impossible except via a sourced shell function.

@bsreddy23
Copy link

/var/lib/jenkins/workspace/node.JS-pipeline@tmp/durable-1816b816/script.sh: line 1: nvm: command not found
@ljharb can u help me pls?
Screenshot 2022-11-21 204523

@ljharb
Copy link
Member

ljharb commented Nov 21, 2022

@bsreddy23 make sure your script is sourcing nvm.sh, potentially in each stage of the pipeline.

@rrr3da
Copy link

rrr3da commented Jan 23, 2023

Correct, we use Bitbucket pipelines and had to source the file like this in order to use v18 inside a folder:
… && . /<user_dir>/.nvm/nvm.sh && nvm use 18 && …

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

9 participants