summary: Why does this fail

$ ssh foo 'R --version | head -n 1'
bash: R: command not found

but this succeeds

$ ssh foo 'grep -nHe 'bashrc' ~/.bash_profile'
/home/me/.bash_profile:3:# source the users .bashrc if it exists
/home/me/.bash_profile:4:if [ -f "${HOME}/.bashrc" ] ; then
/home/me/.bash_profile:5:  source "${HOME}/.bashrc"
$ ssh foo 'grep -nHe "\WR\W" ~/.bashrc'
/home/me/.bashrc:118:alias R='/share/linux86_64/bin/R'
$ ssh foo '/share/linux86_64/bin/R --version | head -n 1'
R version 2.14.1 (2011-12-22)

? details:

I am a (rootless) user on 2 clusters. One uses environment modules, so any given server on that cluster can provide (via module add) pretty much the same resources. The other cluster, on which I must also unfortunately work, has servers managed individually, so I get in the habit of doing, e.g.,

for S in 'foo' 'bar' 'baz' ; do
  ssh ${SERVER} "${EXEC_NAME} --version"

This works fine for packages installed normally/consistently, but often (for reasons unknown to me) packages are not: e.g. (compare alias below to alias above),

$ ssh bar 'R --version | head -n 1'
bash: R: command not found
$ ssh bar 'grep -nHe 'bashrc' ~/.bash_profile'
/home/me/.bash_profile:3:# source the users .bashrc if it exists
/home/me/.bash_profile:4:if [ -f "${HOME}/.bashrc" ] ; then
/home/me/.bash_profile:5:  source "${HOME}/.bashrc"
$ ssh bar 'grep -nHe "\WR\W" ~/.bashrc'
/home/me/.bashrc:118:alias R='/share/linux/bin/R'
$ ssh bar '/share/linux86_64/bin/R --version | head -n 1'
R version 2.14.1 (2011-12-22)

Using aliases copes well with these install differences when I interactively shell into the server, but fails when I try to script ssh commands (as above); i.e.,

# interactively
$ ssh foo
foo> R --version

calls my alias for R on remote host=foo, but

# scripting
$ ssh foo 'R --version'

doesn't. What do I need to do to make ssh foo "<command/>" load my aliases on the remote host?

  • Interesting. Aliases seem to be ignoered entirely. Even explicitly defining an alias per ssh foo 'alias ll="ls -l"; ll' won't work. – Ansgar Wiechers Sep 4 '12 at 1:42
  • Please don't update your title to change the status. Use the Accept/upvote features. – Zoredache Sep 4 '12 at 3:31

From the bash manpage:

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).

You need to shopt -s expand_aliases in your remote .bashrcs, and check that those .bashrc are processed when non-interactive; the default .bashrc for your distribution may include a check to terminate early when non-interactive, e.g. Ubuntu uses:

# If not running interactively, don't do anything
[ -z "$PS1" ] && return
| improve this answer | |
  • Note remote .bashrc had [[ "$-" != *i* ]] && return – TomRoche Sep 4 '12 at 3:12

Andrew's answer explained the reason. I only give one more solution:

In stead of using aliases, use their function equivalents.

For example:

In stead of using: alias ll='ls -lah'

Use this:

function ll{ ls -lah "$@" }

| improve this answer | |

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.