17

I want to ssh into a remote Ubuntu computer, source my .bashrc and run a command that depends on parameters set by that .bashrc. All that in an interactive shell that doesn't close after the command is done.

What I tried until now is

ssh user@remote_computer -t 'bash -l -c "my_alias;bash"'

or just

ssh user@remote_computer -t "my_alias;bash"

This works for general commands (like ls for example) but when I try to run an alias defined in .bashrc I get an error:

bash: my_alias: command not found

But then when I write it manually again and run it, it works!

So how can I make sure the the .bashrc is sourced before the command is called?

Mehdi
  • 374
  • The post is confusing. I recommend not to abuse running commands like that ; nevertheless if bash or a bash command is being invoked I would say .bashrc is supposed to run. There are evidently some differences or peculiarities of running a command like that, and for more serious applications, I would recommend Ansible or puppet. – Rui F Ribeiro Nov 18 '15 at 11:19
  • I edited my question. The second command is more simple and does the same, but still without sourcing .bashrc before. – Mehdi Nov 18 '15 at 12:15
  • @RuiFRibeiro Abuse?? how can you call such a simple thing abuse?? automatically running a command after logging into a remote machine with ssh, it is as simple as that. Any external tool that would be deployed for such a ridiculously small task would be an overkill – Mehdi Nov 18 '15 at 12:24
  • 1
    Just a figure of speaking, was not intended to be used in a broader term. Use them when you need it, however using them is a not as peaceful as it seems. Nevertheless, for future references, have a look at Ansible, you would be amazed how lightweight it is actually. I often do run also commands via ssh. – Rui F Ribeiro Nov 18 '15 at 13:34

2 Answers2

21

The problem is that you are trying to run an alias in a non-interactive shell. When you run ssh user@computer command, command is run non-interactively.

Non interactive shells don't read aliases (from man bash):

Aliases are not expanded when the shell is not interactive, unless the expand_aliases shell option is set using shopt (see the description of shopt under SHELL BUILTIN COMMANDS below).

It works if you run it again manually because the final bash command starts an interactive shell so your aliases are now available.

As an alternative, you could launch an interactive shell (bash -i) instead of a simple login shell (bash -l) on the remote machine to run your alias:

ssh user@remote_computer -t 'bash -ic "my_alias;bash"'

This seems a very complicated approach though. You haven't explained why exactly you need to do this but consider these alternatives:

  1. Just start a normal login interactive shell on the remote machine and run the command manually:

    user@local $ ssh user@remote
    user@remote $ my_alias
    
  2. If you always want that alias to be run when you connect to this computer, edit the ~/.profile (or ~/.bash_profile, if present) of the remote computer and add this line at the end:

    my_alias
    

    Because ~/.profile is read each time a login shell is started (so, each time you connect via ssh, for example), that will cause my_alias to be run each time you connect.

    Note that by default, login shells read ~/.profile or ~/.bash_profile and ignore ~/.bashrc. Some distributions (Debian and its derivatives and Arch, for example) distributions like Ubuntu have their default ~/.profile or ~/.bash_profile files source ~/.bashrc which means that your aliases defined in ~/.bashrc will also be available in a login shell. This isn't true for all distributions, so you might have to edit your ~/.profile manually to have it source ~/.bashrc. Also note that if ~/.bash_profile exists, ~/.profile will be ignored by bash.

terdon
  • 242,166
  • So would you suggest having the aliases defined in a alias_profile and call them from .profile or .bash_profile? – Mehdi Nov 18 '15 at 13:13
  • @Mehdi that will depend on what you want to do. On your Ubuntu system, ~/.basyrc is automatically read by ~./profile, so any aliases defined in ~/.bashrc will also be available to any shells reading ~/.profile. All you really needed to do to get this to work was to explicitly start an interactive shell (-i). – terdon Nov 18 '15 at 13:49
5

I had to comment a part of my .bashrc that prevented aliases from being used and add a expand_aliases command. This was commented

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

And this was added

if [ -z "$PS1" ]; then
  shopt -s expand_aliases
fi

Then my command worked:

ssh user@remote_computer -t "my_alias;bash"
Mehdi
  • 374