web-dev-qa-db-ja.com

ホスト名、IP、ホストの合計メモリをリモートで収集するBashスクリプト

スクリプトに入力したリストから、リモートホストにインストールされているホスト名、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}を直接実行しても問題はありません。スクリプトの中だけ。

2
user315468

これが最終的なスクリプトです。私はそれがあなた方の何人かに役立つことを知っています。

#!/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
0
user315468

これは必要以上にかなり複雑です。また、なぜsshSudoで実行するのですか? 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
6
terdon

これに対する答えを見つけました。それはエスケープと関係していたので、以下のように$ 1と$ 2の前に\を追加しました:

free -m | grep Mem | awk '{print \$1,\$2}
3
user315468