11

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 pi@server.com '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.

Ms01
  • 3,936
  • 6
  • 42
  • 75
  • is `pm2` an alias? If so it probably won't work. Your better off writing a script to handle this and executing that script. Also the ssh command you have is assuming your running in a shell however that isn't a good assumption. Perhaps starting your ssh command with `"/bin/bash -c 'source ....'"` which leads back to the write a script comment above. Finally, does the `pm2` command require a tty? with out the `-t` option a tty will not be allocated. Some programs assume you have one if it is usually executed from an interactive shell unlike the example you provided. – Sukima Oct 27 '15 at 00:53
  • Thanks for the suggestion, sadly it wouldn't do any difference. Tried what you suggested, and even added `/bin/bash -c "nvm use 4.2.0"` to try and enable node. Unfortunately it doesn't work. `/bin/bash: nvm: command not found /bin/bash: pm2: command not found` – Ms01 Nov 04 '15 at 09:16
  • Maybe the solution is to simply install node instead of using a version manager like nvm? I would favor having the nvm to work since it's much easier switching versions. – Ms01 Nov 04 '15 at 09:19
  • Please show Your `/home/pi/.bashrc` file and `echo $PATH` output. – Tomasz Jakub Rup Nov 04 '15 at 11:24
  • 3
    Nvm is a function so it must be sourced in the shell. If you did it with `bash -c` then it doesn’t work because once the -c completes the bash shell exits and any envirinment created within is gone. You have a path problem. `/bin/bash -c ’echo $PATH’` and see what is missing. (single quotes not double quotes). – Sukima Nov 04 '15 at 11:58
  • Does pm2 has its own hidden file? Try sourcing your .profile and .pm2 (if it exists) – Alan Nov 04 '15 at 13:37
  • Also, try running pm2 with full path: "/path/to/your/pm2" – Alan Nov 04 '15 at 13:39
  • @alan Thanks for the idea, I added it but got another error, check my updated question. – Ms01 Nov 04 '15 at 15:51
  • @sukima Added it, but codeship just never returned anything even if it ran in several minutes. I have my output of the $PATH (in an active ssh tty session). But when doing it remote, I don't think the path is the same.. – Ms01 Nov 04 '15 at 15:53

6 Answers6

19

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.

Sukima
  • 9,627
  • 3
  • 42
  • 58
7

Like Sukima said, the likelihood is that this is due to an environment issue - SSH'ing into a server does not set up a full environment. You can, however, get around much of this by simply calling /etc/profile yourself at the start of your command using the . operator (which is the same as the "source" command):

ssh pi@server.com '. /etc/profile ; cd project; pm2 restart app.js -x -- --prod'

/etc/profile should itself be set up to call the .bashrc of the relevant user, which is why I have removed that part. I used to have to do this quite a lot for quick proof-of-concept scripts at a previous workplace. I don't know if it would be considered a nasty hack for a more permanent script, but it certainly works, and would require minimal modification to your existing script should that be an issue.

Ieuan Stanley
  • 1,168
  • 7
  • 20
5

Try:

ssh pi@server.com 'bash -l -c "source /home/pi/.bashrc; cd project; pm2 restart app.js -x -- --prod"'
Eduardo
  • 7,069
  • 2
  • 28
  • 27
3

You should enable some environment values by "source" or dot command ".". Here is an example.

ssh pi@server.com '. /home/pi/.nvm/nvm.sh; cd project; pm2 restart app.js -x -- --prod'
Nam G VU
  • 28,311
  • 62
  • 206
  • 338
kevinYang
  • 91
  • 1
  • 1
1

What worked for me was adding this to my .bash_profile:

if [ -f ~/.bashrc ]; then
  . ~/.bashrc
fi

Source: https://stackoverflow.com/a/820533/1824444

Community
  • 1
  • 1
jhadenfeldt
  • 157
  • 2
  • 12
1

For me I have to load :nvm as I installed node and yarn using :nvm

To load :nvm when ssh remote execution, we call

ssh :user@:host 'source ~/.nvm/nvm.sh; :other_commands_here'
Nam G VU
  • 28,311
  • 62
  • 206
  • 338