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

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.

About this issue

  • Original URL
  • State: closed
  • Created 10 years ago
  • Reactions: 3
  • Comments: 36 (23 by maintainers)

Most upvoted comments

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?

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

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 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.

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.

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

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.

Oh, it is closed 😃

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