次のように、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つの質問を推測します:
スクリプト内の他のコマンド(mkdir
、cd
、git init
など)がリモートマシンで正しく機能するのに、gem list
が機能しないのはどうしてですか?
そのコマンドをエスケープしてリモートで実行するにはどうすればよいですか?
元のコードの問題は、コマンド置換式(バックティックで示される)が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のいずれかの部分が引用されている場合、delimiterはWordの引用符の削除の結果であり、ヒアドキュメントの行は引用符で囲まれていません。拡張されました。 Wordが引用符で囲まれていない場合、ヒアドキュメントのすべての行がパラメータ展開、コマンド置換、および算術展開の対象となり、文字シーケンス\ newlineは無視され、 '\'を使用して引用符を付ける必要があります。文字 '\'、 '$'、および '`'。
リダイレクト演算子が「<<-」の場合、先頭のタブ文字はすべて入力行とdelimiterを含む行から削除されます。これにより、シェルスクリプト内のヒアドキュメントを自然な方法でインデントできます。