`ssh foo "<command/>"` not loading remote aliases?
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?
Solution 1:
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 .bashrc
s, 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
Solution 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 "$@"
}