web-dev-qa-db-ja.com

`ssh foo" <command /> "`はリモートエイリアスをロードしていませんか?

要約:なぜこれが失敗するのか

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

しかし、これは成功します

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

?詳細:

私は2つのクラスターの(ルートレス)ユーザーです。 1つは環境モジュールを使用するため、そのクラスター上の任意のサーバーは(module addを介して)ほぼ同じリソースを提供できます。残念ながら私も作業しなければならないもう1つのクラスターでは、サーバーが個別に管理されているため、次のような作業を行う習慣があります。

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

これは、正常に/一貫してインストールされたパッケージでは正常に機能しますが、多くの場合(私にはわからない理由で)パッケージはそうではありません。 (以下のエイリアスを上記のエイリアスと比較してください)、

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

エイリアスを使用すると、サーバーにインタラクティブにシェルインするときにこれらのインストールの違いにうまく対処できますが、(上記のように)sshコマンドをスクリプト化しようとすると失敗します。つまり、

# interactively
$ ssh foo
...
foo> R --version

リモートホスト= Rfooのエイリアスを呼び出しますが、

# scripting
$ ssh foo 'R --version'

そうではありません。 ssh foo "<command/>"にエイリアスをリモートホストにロードさせるにはどうすればよいですか?

5
TomRoche

bashのマンページから:

シェルが対話型でない場合、shoptを使用してexpand_aliases Shellオプションが設定されていない限り、エイリアスは展開されません(以下のShell BUILTIN COMMANDSのshoptの説明を参照してください)。

必要がある shopt -s expand_aliasesリモコンで.bashrcs、そしてそれらの.bashrc非対話型の場合に処理されます。デフォルト .bashrcディストリビューションには、非対話型の場合に早期に終了するためのチェックが含まれる場合があります。 Ubuntuは以下を使用します:

# If not running interactively, don't do anything
[ -z "$PS1" ] && return
6
Andrew

アンドリューの答えはその理由を説明しました。私はもう1つの解決策を与えるだけです:

aliasesを使用する代わりに、function equivalentsを使用してください。

例えば:

使用する代わりに:alias ll='ls -lah'

これを使って:

function ll{ ls -lah "$@" }

2
biocyberman