bash: nvm command not found
eyekelly opened this issue · comments
Describe the bug
hello, I'm not sure if this is a "bug", but I don't know where else to ask.
I'm trying to install a specific version of nvm, node, npm on a machine image using packer, however it keeps failing no matter what I try.
Expected behavior
that it installs and passes
To Reproduce
---
- hosts: all
become: yes
become_method: sudo
roles:
- role: ansible-role-nvm
nodejs_version: "8.16.0"
nvm_install: "curl"
nvm_version: "0.34.0"
nvm_profile: "/home/nodejs/.bashrc"
nvm_dir: "/home/nodejs"
nvm_commands:
- "nvm install 8.16.0"
- "nvm alias default 8.16.0"
- "nvm exec default npm install"
Shell [e.g. Bash, Dash, ksh, tcsh, zsh]
bash
Desktop (please complete the following information):
- OS: Debian stretch
- Ansible Version: 2.2.1.0
- Hypervisor Type and Version packer image on aws
Debugging output
amazon-ebs:
amazon-ebs: PLAY [all] *********************************************************************
amazon-ebs:
amazon-ebs: TASK [setup] *******************************************************************
amazon-ebs: ok: [default]
amazon-ebs:
amazon-ebs: TASK [ansible-role-nvm : Check if wget or curl is installed] *******************
amazon-ebs: changed: [default]
amazon-ebs:
amazon-ebs: TASK [ansible-role-nvm : Determine if install type wget] ***********************
amazon-ebs: skipping: [default]
amazon-ebs:
amazon-ebs: TASK [ansible-role-nvm : Determine if install type curl] ***********************
amazon-ebs: ok: [default]
amazon-ebs:
amazon-ebs: TASK [ansible-role-nvm : Create destination dir if it does not exist] **********
amazon-ebs: changed: [default]
amazon-ebs:
amazon-ebs: TASK [ansible-role-nvm : Install NVM] ******************************************
amazon-ebs: changed: [default]
amazon-ebs:
amazon-ebs: TASK [ansible-role-nvm : Check if git is installed] ****************************
amazon-ebs: skipping: [default]
amazon-ebs:
amazon-ebs: TASK [ansible-role-nvm : Remove NVM nvm_profile] *******************************
amazon-ebs: skipping: [default]
amazon-ebs:
amazon-ebs: TASK [ansible-role-nvm : Install via git] **************************************
amazon-ebs: skipping: [default]
amazon-ebs:
amazon-ebs: TASK [ansible-role-nvm : Add NVM to nvm_profile] *******************************
amazon-ebs: skipping: [default]
amazon-ebs:
amazon-ebs: TASK [ansible-role-nvm : Check NVM Version] ************************************
amazon-ebs: fatal: [default]: FAILED! => {"changed": true, "cmd": "bash -ic \"nvm --version\"", "delta": "0:00:00.004018", "end": "2020-01-29 16:08:19.774321", "failed": true, "rc": 127, "start": "2020-01-29 16:08:19.770303", "stderr": "bash: cannot set terminal process group (12602): Inappropriate ioctl for device\nbash: no job control in this shell\nbash: nvm: command not found", "stdout": "", "stdout_lines": [], "warnings": []}
amazon-ebs: to retry, use: --limit @/home/admin/eu-sysops-packer/unified-API/unified-api-nodejs.retry
amazon-ebs:
amazon-ebs: PLAY RECAP *********************************************************************
amazon-ebs: default : ok=5 changed=3 unreachable=0 failed=1
amazon-ebs:
Additional context
this may be an issue with packer, the problem seems to occur whatever I do, I need to install all this under a specific user created earlier on in the AMI creation process
any advice gratefully received.
Many thanks
Thanks for the detailed report. I've finally been able to recreate part of the issue. There are actual bugs and some misunderstanding going on here.
First things first
- role: ansible-role-nvm
nodejs_version: "8.16.0"
nvm_install: "curl"
nvm_version: "0.34.0"
nvm_profile: "/home/nodejs/.bashrc"
nvm_dir: "/home/nodejs"
nvm_commands:
- "nvm install 8.16.0" <= NOT NEEDED
- "nvm alias default 8.16.0" <= NOT NEEDED
- "nvm exec default npm install"
- If you specify a
nodejs_version
it will be installed. You don't need to install it again. - If you are only installing one version of node with the role, it will automatically be the default version
The role will create a folder when explicitly declaring the nvm_dir
variable if it doesn't exist . The role was missing become: true
when creating the directory as part of the task, which would have thrown an error (BUGFIX 1)
I suspect that you are adding:
become: yes
become_method: sudo
to get around that error.
Now here comes the tricky part. .bashrc
files are sourced when a user logs into the box. Whatever is inside the .bashrc file (in our case the NVM goodness) becomes part of the users context/session/profile/shell for as long as that user is logged in. That is how the nvm
command works under the hood. Unfortunately, by setting become: true|yes|1
on the role, it forces the login context to change from the user you expect/want to the *root user. The nvm installation script just does what it does and adds the NVM goodness to the /root/.bashrc
file IF THAT FILE EXISTS! otherwise it will dump it where it thinks is best which might not be where we expect it to be.
Now the role ensures the .bashrc file (or whatever file you've specified) is there when nvm_profile
is explicitly declared so the nvm installation script knows where to add it's goodness. (BUGFIX 2)
You can check the fixes a798f47
However, here is where I believe there is a bit of confusion. With the information you've provided above, I can probably presume that there is no real nodejs user on the Debian box and that you are just storing the nodejs stuff at /home/nodejs
for simplicity. This is a little confusing as /home/nodejs
would suggest that there is a real nodejs user account on the machine in which you expect VNM and Node to run as (more on this below)
Because the command to check the nvm version forces the login context to be interactive (the -i
in bash -ic
command), the command is running in the context of the user you're logging in as/running the role as, in your case the root user. The updates that I've made to the role now provide the correct context so nvm install script will put the .bashrc file in /home/nodejs/.bashrc
path as you specified. You would need to remove the become: yes
and become_method: sudo
from the role to see the result
However, I believe this is not really what you want anyway; the error above is an underlying symptom of a larger issue.
So there are a couple of options to fix the issue. I welcome any feedback
-
You remove the
nvm_profile: "/home/nodejs/.bashrc"
andnvm_dir: "/home/nodejs"
variables, the role will automatically will place the .bashrc file in the appropriate context, as the user running the playbook and the eventual user you expect NVM and Node to run as (vagrant, ec2-user, amazon-ebs etc.) and the role will work as you expect -
The nvm --version command is supposed to be run the same context in which Node will be running (you shouldn't be running Node as root). To fix the underlying issue you would need to create a real nodejs user on the box e.g.
sudo useradd nodejs
with appropriate sudoers access or with the ansible user module. You can then install the role withbecome_user: nodejs
in which the correct context for nvm will be used and thebash -ic "nvm --version"
and any NVM commands will work as expected. I believe this is technically what you are looking for. The role adding users to satisfy thenvm_profile
variable is a little outside the scope of the role, but technically possible. At the very least some documentation would be needed to detail this. -
The role can sort of fudge the results a little by sourcing the .bashrc file (wherever it lives) before running the
bash -ic "nvm --version"
command (or any commands like it), something likebash -ic "source {{ nvm_profile }} && nvm --version"
if thenvm_profile
variable is explicitly declared. This solves the problem with the error but leaves some clarity issues fior when a user doesn't really exist, the login context is different than location of the .bashrc file or when running NVM or Node commands elsewhere or when actually logging into a machine as a default/different user. Not ideal -
The role can add a script to the /etc/environment folder that will source the
nvm_profile
variable (.bashrc file) if it is explicitly declared. Something likealways_available: true
. It would make it available to anyone logging in. A side effect being thebash -ic "nvm --version"
should always work regardless of which user it was installed with. I am not sure this is a good thing or not. I'm leaning towards it not being good as it forgoes what user accounts are good for (sand boxing). -
The role could also add the NVM goodness to the global .bashrc profile and have the same effect as above but more explicit. This is something nvm install does out of the box when
nvm_profile: "/home/nodejs/.bashrc"
andnvm_dir: "/home/nodejs"
variables are empty. Documentation would be needed to detail this.
Ok, I believe I have fulfilled the essence of what you are attempting to do by fixing the actual bugs and providing greater details in the documentation to prevent a misunderstanding of what is happening under the hood in regards to users context/session/profile/shells. If you believe that what I have done does not address your particular issue, please feel free to open a new issue.