3

One-liner question: How do I automatically source a remote file on remote host after logging in via SSH via a bastion host?

I need to source a file containing a list of aliases + shell user defined functions on a remote host after ssh-ing into it.

The file exists on remote maching in /tmp folder e.g. /tmp/my-rc

Searching other posts and internet I have found

ssh -t user@domain.com 'source /tmp/my-rc; bash -l'

The problem is that I do get a terminal, but none of the aliases are set since it's a new bash shell'

Thinking, that the source should be done after the shell is attached, tried the below but this also doesn't work. There is no error, I get the terminal but don't think the file got sourced (verified by echoing dummy message from /tmp/my-rc file)

ssh -t user@domain.com 'bash -l; source /tmp/my-rc'

Even tried with '.' instead of source, no luck.

Any help.

Note1: Bash or ZSH any shell solution would do.

Note2: The actuall ssh is via a proxy command i.e. a hop over bastion host (Just mentioning if it is relevant at all)

Note3: I don't have privilage of a profile rc or bashrc or even a home directory on the remote host.

Note4: The exact command that I used to login into the secure host is via bastion host like below

ssh -o ProxyCommand='ssh -W %h:%p ec2-3-218-12-120.compute-1.amazonaws.com' 10.0.31.122  
6
  • To be completely sure: you can create files (and directories?) in /tmp on the remote host, but you don't have a HOME directory there. Both Bash and Zsh are installed on the remote host. Is it correct? What is the value of HOME when you start an interactive shell on the remote host via SSH?
    – fra-san
    Sep 1 '20 at 10:46
  • @fra-san value of $HOME is /home/tareque, but there is no such directory. When I enter just cd, which should take me to home dir, I get message cd: no such file or directory: /home/tareque
    – mtk
    Sep 1 '20 at 14:21
  • @fra-san Yes I am able to create directories and files in /tmp. Bash and Zsh are installed on remote host already.
    – mtk
    Sep 1 '20 at 14:22
4

With bash, you can do:

ssh -t user@host '
  PROMPT_COMMAND="source /tmp/my-rc
                  unset PROMPT_COMMAND
                 " exec bash --norc'

Which would cause /tmp/my-rc to be sourced before the prompt, and only that prompt since we unset PROMPT_COMMAND afterwards.

You'll want to remove the unset PROMPT_COMMAND if /tmp/my-rc actually ends up defining it.

The above assumes the login shell of the remote user is Bourne-like, but you should be able to adapt it to most other types of shells (csh / rc / fish).

1
  • Thanks. This solution also works.
    – mtk
    Sep 8 '20 at 14:33
2
+50

Given that you can write to the remote host's /tmp, you can create a /tmp/myhome directory on it, put your shells' profile and initialization files there and then start Zsh with ZDOTIDR set to /tmp/myhome and Bash with HOME set to /tmp/myhome.

By default, Zsh searches for its initialization files in $ZDOTDIR, defaulting to $HOME if ZDOTDIR is not set.

Hence, you can start Zsh on the remote host as:

ssh -t user@host ZDOTDIR=/tmp/myhome zsh

And Bash as:

ssh -t user@host HOME=/tmp/myhome bash

Of course you can be creative with your profile/initialization files—e.g. use them to set HOME to a more suitable path, source other files (if you happened to already have dot-files somewhere on the remote host), etc.

A minimal application of this approach, condensed in one command, could be:

ssh -t user@host 'mkdir /tmp/myhome
  echo ". /tmp/my-rc" >/tmp/myhome/.bashrc
  HOME=/tmp/myhome bash'

(Use mkdir -p ... to prevent an error from being shown when /tmp/myhome already exists, e.g. if you are reconnecting to the remote host and you already know the directory is there).

Taking your ProxyCommand into account, it could be:

ssh -t -o ProxyCommand='ssh -W \
  %h:%p ec2-3-218-12-120.compute-1.amazonaws.com' \
  10.0.31.122 \
  'mkdir /tmp/myhome
  echo ". /tmp/my-rc" >/tmp/myhome/.bashrc
  HOME=/tmp/myhome bash'

Finally, about your attempts: ssh -t user@domain.com 'bash -l; source /tmp/my-rc' is not working because the source command is only executed after the interactive shell exits.

5
  • I have added the exact ssh command that I use to login via a bastion host... Your solution doesn't seem to work. Tried adding the HOME/ZDOTDIR to the ProxyCommand as well as to the outer ssh command.
    – mtk
    Sep 8 '20 at 14:01
  • To make sure we are on the same page, I added a complete command based on your edited question. Please, add some information on how it doesn't work for you, if it is the case (e.g. does it show any error messages? Does it hang?).
    – fra-san
    Sep 8 '20 at 14:22
  • Appreciate the effort.. Tried the updated proxyCommand, the terminal just hangs with output Could not chdir to home directory /home/tareque .. I have created /tmp/.mtk with .bashrc .profile The command I used ssh -o ProxyCommand='ssh -W %h:%p ec2-3-218-12-120.compute-1.amazonaws.com ' 10.0.31.122 'HOME=/tmp/.mtk bash'
    – mtk
    Sep 8 '20 at 14:22
  • You are forgetting the -t option, isn't it?
    – fra-san
    Sep 8 '20 at 14:24
  • Thanks :) bash solution tried, tested and worked. Thanks a lot.
    – mtk
    Sep 8 '20 at 14:31
1

If UsePAM is set to yes in the remote hosts's sshd_config file, then config file /etc/pam.d/sshd allows you to automize command execution upon successful login, among other events in the authentication process. Add this line of code

session    required     pam_exec.so /etc/myscripts/./sourcing-script

directly above these lines

# SELinux needs to intervene at login time to ensure that the process starts
# in the proper default security context.  Only sessions which are intended
# to run in the user's context should be run after this.
session [success=ok ignore=ignore module_unknown=ignore default=bad]        pam_selinux.so open

where /etc/myscripts/sourcing-script simply is a file on the remote host with the command to execute upon successful login.

#!/bin/bash
source /tmp/my-rc
#echo $(date) >> /etc/myscripts/sourcing-script.log
#cat /tmp/my-rc >> /etc/myscripts/sourcing-script.log

I use this method to stop a service and report it to a log file, before my ssh session is opened. Before I log out I set a crontab to start the service, so it never runs parallel with my ssh session.

0

Typically you do this in $HOME/.profile or variants.

ssh sets environments variables starting with SSH_, you can use those to determine if you logged in via ssh, or directly.

1
  • I don't have a home directory setup on remote host.. Have added this info to the question. Yes I understand this is a key point, i missed to say. Sorry. Without home directory, profile rc/bashrc is there a way to achieve my ask?
    – mtk
    Aug 18 '20 at 20:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.