スクリプトに入力したリストから、リモートホストにインストールされているホスト名、IP、および総メモリを収集するスクリプトを記述しようとしています。スクリプトはRedhatおよびSolarisマシンから情報を収集します。以下は私のスクリプトの例です。
#!/bin/bash
echo > ip_info.output
echo -e "\n"
for Host in `cat ip_adds`
do
echo "Hostname:" $Host
Sudo ssh -o BatchMode=yes -o ConnectTimeout=5 $Host "echo IP Address:; ip route get 1 | awk '{print $NF;exit}'; free -m | grep Mem | awk '{print $1,$2}'"
echo -e "\n"
done
スクリプトを実行すると、以下のエラーが発生します。
awk: {print ,}
awk: ^ syntax error
awk: {print ,}
awk: ^ syntax error
awk: cmd. line:1: {print ,}
awk: cmd. line:1: ^ unexpected newline or end of string
問題はfree -m | grep Mem | awk '{print $1,$2}
にあると思いますが、それを修正する方法がわかりません。シェルでfree -m | grep Mem | awk '{print $1,$2}
を直接実行しても問題はありません。スクリプトの中だけ。
これが最終的なスクリプトです。私はそれがあなた方の何人かに役立つことを知っています。
#!/bin/bash
for Host in `cat ip_adds2`
do
echo "Hostname:" $Host
Sudo ssh -t -o BatchMode=yes -o ConnectTimeout=5 $Host 'echo IP: `hostname -i`;read junk total used free shared buffers cached junk < <(free -g | grep ^Mem);echo Memory: $total GiB'
echo -e "\n"
done
これは必要以上にかなり複雑です。また、なぜssh
をSudo
で実行するのですか? rootとしてリモートにログインする必要がある場合は、それを行うことができます(ssh root@$Host
)。ただし、sshキーがすべてrootに属していない限り、Sudo
を使用してsshを実行する必要はほとんどありません。これはかなり悪い考えです。
また、私のArchシステムでは、IPを取得するために使用しているように見えるコマンドがユーザーのUIDを返します。
$ ip route get 1
1.0.0.0 via 192.168.1.1 dev enp0s31f6 src 192.168.1.111 uid 1000
cache
$ ip route get 1 | awk '{print $NF;exit}';
1000
私がテストしたUbuntuで期待どおりに動作します。
$ ip route get 1
1.0.0.0 via 123.456.7.8 dev eth0 src 123.456.7.9
$ ip route get 1 | awk '{print $NF;exit}';
123.456.7.9
したがって、おそらくこれのよりポータブルなバージョンは、src
の後にフィールドを出力することです:
$ ip route get 1 | sed -nE 's/.* src ([0-9.]+).*/\1/p'
192.168.1.111
あなたが見たエラーは確かに引用によるものでした。 ssh $Host "command"
を実行していたので、command
を二重引用符で囲むと、シェルはコマンド内で見つかった変数を展開します(awkの$2
など)。これを回避し、シンボルを展開せずにawkに渡すには、$
をエスケープする必要があります。
スクリプトのより単純なバージョン:
#!/bin/bash
sshOpts="BatchMode=yes -o ConnectTimeout=5"
echo > ip_info.output
echo ""
while read Host; do
printf "Hostname:%s" $Host
ssh -o $sshOpts $Host "printf 'Hostname: %s\nIP: %s\nMem: %s\n' $Host "$(ip route get 1 | sed -nE 's/.* src ([0-9.]+).*/\1/p')" "$(free -m | awk '/Mem/{print $2}')""
done < ip_adds
これに対する答えを見つけました。それはエスケープと関係していたので、以下のように$ 1と$ 2の前に\を追加しました:
free -m | grep Mem | awk '{print \$1,\$2}