5

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

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

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?

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

2 Answers 2

6

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
1
  • Note remote .bashrc had [[ "$-" != *i* ]] && return
    – TomRoche
    Sep 4, 2012 at 3:12
2

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 "$@" }

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .