Unable to execute "npm" command with "exec"

Hello!

I cannot execute the command with exec :

$ lxc exec mycontainer -- sudo --user ubuntu --login npm -v
-bash: npm: command not found

.

$ lxc exec mycontainer -- sudo --user ubuntu --login bash -c "npm -v"
bash: npm: command not found

But from inside the container:

ubuntu@mycontainer:~$ npm -v
6.14.11

Environment:

$ lxc exec mycontainer -- sudo --user ubuntu --login env
...
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin
...

.

ubuntu@mycontainer:~$ env
...
NVM_INC=/home/ubuntu/.nvm/versions/node/v14.15.5/include/node
NVM_DIR=/home/ubuntu/.nvm
NVM_CD_FLAGS=
PATH=/home/ubuntu/.nvm/versions/node/v14.15.5/bin:/usr/local/sbin:/usr/local/bin:/usr/NVM_BIN=/home/ubuntu/.nvm/versions/node/v14.15.5/bin
...

NPM inside the container installed via NVM.

How to correctly execute the command using exec (without “hardcoding” the path)?

Hi!

When you get a shell into the container, the system may run ~/.profile or ~/.bashrc or both.
You can check this out if you add some echo statement in those files to verify which ones run in each case. I did this and here is the result.

$ lxc exec mycontainer -- sudo --user ubuntu --login npm
Running ~/.profile
NPM...
$ lxc exec mycontainer -- sudo --user ubuntu --login 
Running ~/.bashrc
Running ~/.profile
ubuntu@mycontainer:~$ 

Therefore, can you check that you have setup the $PATH in ~/.profile for NPM?

Thanks for the echo tip, may be useful in the future debugging :slight_smile:

ubuntu@mycontainer:~$ which npm
/home/ubuntu/.nvm/versions/node/v14.15.5/bin/npm

.

ubuntu@mycontainer:~$ cat ~/.profile
echo "profile"
...

.

ubuntu@mycontainer:~$ cat ~/.bashrc
echo "bashrc"
...
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"  # This loads nvm bash_completion

And nothing related to NPM in both files above, as far as I can see.

$ lxc exec mycontainer -- sudo --user ubuntu --login
profile
bashrc

.

$ lxc exec mycontainer -- sudo --user ubuntu --login npm
profile
bashrc
-bash: npm: command not found

I could not replicate this. That is, in my case, the above command did not source the .bashrc file.
Here is the verbatim output,

$ lxc exec mycontainer -- sudo --user ubuntu --login
Running ~/.bashrc
Running ~/.profile
ubuntu@mycontainer:~$ logout
$ lxc exec mycontainer -- sudo --user ubuntu --login npm
Running ~/.profile
NPM...
$ 

I suggest to copy the NVM/NPM related lines to the ~/.profile file.

ubuntu@mycontainer:~$ cat ~/.profile
...
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"  # This loads nvm bash_completion

.

$ lxc exec mycontainer -- sudo --user ubuntu --login npm -v
profile
bashrc
6.14.11

Hmm… It works now. But why?
(famous developer quote, I guess) :slight_smile:

I mean, in my case (for some reason) there is “bashrc” output too, before actual command output…

UPD:
If I move the NVM related lines to the top of ~/.bashrc it works too. I wonder if it possible to wait until the ~ / .bashrc file has finished executing and only then execute the command specified in exec (it would be more general solution to this case I think)

The .bashrc file has these lines at the start,

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

That is the reason why .bashrc is not meant to run when the shell is not interactive.
In my case, I added the echo line at the very end of the .bashrc file, hence they did not run when the shell was non-interactive. If you added your echo at the very beginning, then you got the echo as well.

In terms of Unix/Linux semantics, it is suitable to add and $PATH changes to the end of the .profile. As you can see, this file already has other cases with additions to the $PATH.

1 Like

Oh. So that’s why! Thank you for the explanation!

P.S. Love your blog :slight_smile: