web-dev-qa-db-ja.com

sshにローカルではなくリモートシステムでコマンドを実行させる方法

次のように、SSHでスクリプト内のいくつかのコマンドを実行しています。

#!/bin/bash

REMOTEUSER=$1
REMOTEHOST=$2    
newVh=$3

ssh "$REMOTEUSER"@"$REMOTEHOST" << EOF

cd

if [ ! -d "/data/web/someDirectory" ]
then
  echo -e "There is no vhost setup for someDirectory"
  exit 1
fi


if [ ! -d "git" ]
then
  echo -e "Home git directory not found. Creating it now."
  mkdir git
fi

if [ ! -d "git/$newVh.git" ]
then
  echo -e "Bare git repository not found for $new. Creating it now."
  mkdir git/"$newVh".git
  git init --bare git/"$newVh".git
fi


EOF

これはうまく機能し、私が望むことをします。 compass Ruby gemがリモートマシンにインストールされているかどうかを確認しようとしていますが、インストールされていない場合はインストールしたいと思います。この行をの下部に追加しましたスクリプト:

.
.
.
if [ `gem list compass -i` == 'false' ]
then
  echo -e "Compass not installed... Installing it now."
  gem install compass -V
fi


EOF

しかし、`gem list compass -i`。事前にローカルマシンで評価されています(コンパスをインストールしています)。スクリプトで引用符なしでgem list compass -iを実行して出力を確認しても、trueが返されますがこれは正しくありません。いくつかの\sを使用してコマンドをエスケープしようとしましたが、機能しませんでした。

私は2つの質問を推測します:

スクリプト内の他のコマンド(mkdircdgit initなど)がリモートマシンで正しく機能するのに、gem listが機能しないのはどうしてですか?

そのコマンドをエスケープしてリモートで実行するにはどうすればよいですか?

4
Brandon

元のコードの問題は、コマンド置換式(バックティックで示される)がsshコマンドの実行前に評価されることです。別の状況では、ヒアドキュメントでのパラメータ拡張を防ぐためにヒアドキュメントキーワード(「EOF」など)を引用することを検討できますが、この場合、実際にはクライアント側でパラメータ置換を実行する必要があります。したがって、ここでの解決策は、コマンド置換を回避することです。代わりにこれを試してください:

if [ \`gem list compass -i\` == 'false' ]
then
  echo -e "Compass not installed... Installing it now."
  gem install compass -V
fi

エスケープされたバックティックは、コマンド置換が評価されないようにします。

また、コマンド置換のバックティック構文はレガシー機能であると広く考えられており、最近ではドル記号構文が一般的に好まれていることにも言及します。代わりにドル記号構文を使用すると、上記のスニペットは次のようになります。

if [ \$(gem list compass -i) == 'false' ]
then
  echo -e "Compass not installed... Installing it now."
  gem install compass -V
fi

2つの表記法の違いの詳細については、次のStackExchangeの投稿を参照してください。

コマンド置換に関するGNU Bashのマニュアルページ も参照してください。

また、 リダイレクトに関するGNU Bashのマニュアルページ

特に、here-docsの次のサブセクションに注意してください。

3.6.6ヒアドキュメント

このタイプのリダイレクトは、Word(末尾の空白なし)のみを含む行が表示されるまで、現在のソースからの入力を読み取るようにシェルに指示します。その時点までに読み取られたすべての行は、コマンドの標準入力(または、nが指定されている場合はファイル記述子n)として使用されます。

ヒアドキュメントの形式は次のとおりです。

[n]<<[-]Word
    here-document
delimiter

Wordでは、パラメーターおよび変数の展開、コマンド置換、算術展開、またはファイル名の展開は実行されません。 Wordのいずれかの部分が引用されている場合、delimiterWordの引用符の削除の結果であり、ヒアドキュメントの行は引用符で囲まれていません。拡張されました。 Wordが引用符で囲まれていない場合、ヒアドキュメントのすべての行がパラメータ展開、コマンド置換、および算術展開の対象となり、文字シーケンス\ newlineは無視され、 '\'を使用して引用符を付ける必要があります。文字 '\'、 '$'、および '`'。

リダイレクト演算子が「<<-」の場合、先頭のタブ文字はすべて入力行とdelimiterを含む行から削除されます。これにより、シェルスクリプト内のヒアドキュメントを自然な方法でインデントできます。

5
igal