0

I need to run an ssh sudo command.

command is as follows:

ssh -i keyfile ubuntu@10.65.21.253  'sh -v /opt/dir/script'

the script contains the following:

sudo -E node some.js

the reason I use the -E argument is that the command is being run by userA AND the process being started needs to load definitions from

/user/userA/.bashrc

the above command does NOT load the variables defined in /user/userA/.bashrc

it is running really as though the -E is not doing anything. i.e all the variables show as undefined.

If I log in to the remote machine interactively as userA and run the same command, namely,

sudo -E node some.js

the variables are loaded correctly and I see the expected behavior.

Can anyone see what I need to do differently?

reza
  • 355
  • 4
  • 5
  • 11
  • ssh -i keyfile ubuntu@10.65.21.253 "ubuntu" is userA on target machine. Your original answer was spot on. I was just unclear about option of creating a special_env file or using the ~./bashrc as is – reza Jan 09 '21 at 02:01

1 Answers1

1

You're expecting the shell to source ~/.bashrc, so I assume the shell is Bash.

Twist number 1: SSH server passes the shell code to a non-interactive shell. Non-interactive Bash does not read ~/.bashrc.

Twist number 2: Bash attempts to determine when it is being run with its standard input connected to a network connection, as when executed by a SSH server. If bash determines it is being run in this fashion, it does read and execute commands from ~/.bashrc.

Twist number 3: In many distros (including Ubuntu) the default (skeletal) ~/.bashrc starts with code that returns if the shell is non-interactive. In effect the rest of the file is not sourced.

I guess in your case the relevant environment variables are defined after this piece of code. The code may look like this:

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

A straightforward solution is to move the assignments so they are before this code. If you'd like to move commands that do more (e.g. echo something, run something) then be very careful because you may break remote file transfers. Read Why does bashrc check whether the current shell is interactive? If it's about variables only then you should be safe.

In general the environment should be defined in ~/.profile rather than in ~/.bashrc, but if you moved the assignments to ~/.profile then you would experience this: ~/.profile is not loaded when using SSH. It's not unreasonable to have them in ~/.bashrc then.

Alternatively you can place them in a separate file, e.g. ~/.special_env, and source the file from ~/.bashrc or ~/.profile or whatever. The advantage is you can source the file on demand regardless of quirks and twists:

ssh -i keyfile ubuntu@10.65.21.253  '. ~/.special_env; sh -v /opt/dir/script'
Kamil Maciorowski
  • 69,815
  • 22
  • 136
  • 202
  • I think the simplest thing to do would be to move them vars defined in ~/.bashrc to another file namely ~/.special_env. and then load those before the script is run. Is that what you are implying? Agree? – reza Jan 09 '21 at 00:15
  • @reza Well, it's a matter of opinion if rearranging `~/.bashrc` is not simpler. Pick a method that works best for you. If I were you I would start with modifying `~/.bashrc` only. If I didn't encounter any problems then there would be little point in creating `~/.special_env` and sourcing manually while `~/.bashrc` does the job automatically. – Kamil Maciorowski Jan 09 '21 at 00:24
  • either create a new env file or source ~/.bashrc? So 'source ~/.bashrc ; sh -v /opt/dir/script'. Do I have that correct? – reza Jan 09 '21 at 00:53
  • @reza Sourcing `~/.bashrc` happens automatically. If there's code that returns in a non-interactive shell then it will return even if you explicitly source the file in a non-interactive shell. Is there such code in your `~/.bashrc`? – Kamil Maciorowski Jan 09 '21 at 00:59
  • I tried the above suggestion of ssh -i keyfile ubuntu@10.65.21.253 '. ~/.special_env; sh -v /opt/dir/script' and the application run from the bash script does not see the env variables defined and it is not propagated – reza Jan 12 '21 at 16:42
  • Does that answer your last question Kamil ? the ~.bashrc only contains exports nothing else at all, nothing interactive... – reza Jan 14 '21 at 16:34
  • @reza I wasn't responding because I'm out of ideas. Try to provide an example as close to [mcve](https://meta.stackoverflow.com/a/367019/10765659) as possible. My advice: (1) Maintain one question, not two. (2) Stick to one command. At this point `ssh -i keyfile ubuntu@ip '. /full/path/to/special_env; sh -v /test/script'` seems to be the one. (3) Post the content of `special_env` and the script. (4) Instead of `node some.js` or `myApp` run `env` which will show you what the environment is (and we can run it). (5) Make sure `sh` on the server is what you think. What if you use `bash` instead? – Kamil Maciorowski Jan 14 '21 at 22:08
  • thanks for all the help and sticking with me... The final working command looks like ssh -ubuntu@10.65.21.253 '. /home/ubuntu/myenvs && cd /opt/imei-lookup && bash -v -v deploy.sh; export -p' This way I can finally pass along the env variables to the deploy script I think the most relevant part of the original error was not including the full path to the new env file AND not saying bash myscript ... Again thank you so very much – reza Jan 19 '21 at 18:42