次のスクリプトがあります。
#!/bin/bash
if [ "$1" == "" ]
then
echo "To start monitor, please provide the server ip:"
read STRIP
else
STRIP=$1
fi
ssh 192.168.5.209 ssh root@$STRIP "df -khP | column -t | awk '{print $5 " " $1 " " $2}'"
したがって、端末に入力すると、次のようになります。
./my_script.sh 192.168.5.210
マイポータル209にSSHとして接続し、次に210にSSHとして接続してハードドライブ情報を取得する必要があります。問題は、期待どおりに機能せず、代わりに次のように5行だけを出力することです。
192.1680.50.21
192.1680.50.21
192.1680.50.21
192.1680.50.21
192.1680.50.21
IPをスクリプトの変数またはechoパラメータの値に手動で設定しようとしましたが、正しく機能しますか?
たとえば、次はうまくいきます。
STRIP=192.168.5.210
ssh 192.168.5.209 ssh root@$STRIP "df -khP | column -t | awk '{print $5 " " $1 " " $2}'"
ただし、パラメータを使用せずに渡すと、5つの空白行が表示されます。
答え1
引用符は入れ子にされません。ssh
リモートコマンドを一重引用符引数を含む二重引用符文字列として渡し、その引数に二重引用符awk
文字列を複数含めたいとします。ただし、シェルは各二重引用符を二重引用符で囲んだ文字列の先頭または末尾として扱うため、かなり混乱する可能性があります。
特に、"df -khP | column -t | awk '{print $5 " " $1 " " $2}'"
パラメータリストでこれを使用すると、複数のssh
個別の引用符で囲まれた文字列に解析されます。最初のものはであり"df -khP | column -t | awk '{print $5 "
、$variable
置換は二重引用符で囲まれた文字列内で実行され、スクリプトは5つの引数を取得できないため、その$5
部分は何も置き換えられず、「df -khP |列-t | awk '{print」になります。以下は" $1 "
「192.168.5.210」に拡張されます(これはスクリプトの最初のパラメータであるため)。最後に、" $2}'"
2番目のパラメータがないため、「}」に拡張されます。ssh
次に、実行中のコマンドで `df -khP |column -t|awk '{print 192.168.5.210}' を指定して、スペースを空白にして貼り付けます。あなたが望むものはまったくありません。
この機能が機能するには、二重引用符で囲まれた単一の文字列内の特定の文字をエスケープ(バックスラッシュを使用)する必要があります。具体的には、すべての二重引用符(引用符付きの文字列が終わらないことを防ぐ)とドル記号(パラメータなどに展開されないようにする)です。バックティックやバックスラッシュがある場合でもエスケープする必要があります。したがって、必要なコマンドは次のようになります。
ssh 192.168.5.209 ssh root@$STRIP "df -khP | column -t | awk '{print \$5 \" \" \$1 \" \" \$2}'"
しかし、私が正しく理解しているなら、これが印刷される理由は、awk
192.168.5.210を3つの間違いである192.168、.5、および.210に解析して印刷するためです(必要に応じて前に0を追加し、次の0を追加します) (関連なし))「192.168」、「0.5」、「0.21」と同じです。ただし、2 つの間のスペースは印刷されないため、「192.1680.50.21」と表示されます。