Search code examples
linuxnode.jsbashsshcodeship

bash doesn't load node on remote ssh command


Excuse me if the subject is vague, but I tried to describe my problem to the best of my possibilities. I have my raspberry pi which I want to deploy to using codeship. Rsyncing the files works perfectly, but when I am to restart my application using pm2 my problem occurs.

I have installed node and pm2 using the node version manager NVM.

ssh [email protected] 'source /home/pi/.bashrc; cd project; pm2 restart app.js -x -- --prod'0 min 3 sec
bash: pm2: command not found

I have even added:

shopt -s expand_aliases in the bottom of my bashrc but it doesn't help.

How can I make it restart my application after I have done a deploy? Thanks in advance for your sage advice and better wisdom!

EDIT 1: My .bashrc http://pastie.org/10529200 My $PATH: /home/pi/.nvm/versions/node/v4.2.0/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/games:/usr/games

EDIT 2: I added /home/pi/.nvm/versions/node/v4.2.0/bin/pm2 which is the full path to pm2 and now I get the following error: /usr/bin/env: node: No such file or directory

It seems that even if I provide the full path, node isn't executed.


Solution

  • I think the problem is the misinterpretation that the shell executing node has a full environment like an interactive ssh session does. Most likely this is not the case.

    When a SSH session spawns a shell it goes through a lot of gyrations to build an environment suitable to work with interactively. Things like inheriting from the login process, reading /etc/profile, reading ~/.profile. But in the cases where your executing bash directly this isn't always guaranteed. In fact the $PATH might be completely empty.

    When /usr/bin/env node executes it looks for node in your $PATH which in a non-interactive shell could be anything or empty.

    Most systems have a default PATH=/bin:/usr/bin typically /usr/local/bin is not included in the default environment.

    You could attempt to force a login with ssh using ssh … '/bin/bash -l -c "…"'.

    You can also write a specialized script on the server that knows how the environment should be when executed outside of an interactive shell:

    #!/bin/bash
    # Example shell script; filename: /usr/local/bin/my_script.sh
    export PATH=$PATH:/usr/local/bin
    export NODE_PATH=/usr/local/share/node
    export USER=myuser
    export HOME=/home/myuser
    source $HOME/.nvm/nvm.sh
    cd /usr/bin/share/my_script
    nvm use 0.12
    /usr/bin/env node ./script_name.js
    

    Then call it through ssh: ssh … '/usr/local/bin/my_script.sh'.

    Beyond these ideas I don't see how to help further.