Linux
用於遠端收集主機名、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}
直接執行到 shell 我沒有問題。就在劇本里面。
這比它需要的要復雜得多。
ssh
另外,你為什麼要跑sudo
?如果您需要以 root 身份登錄到遠端,那麼您可以這樣做 ( ),但除非您的 ssh 密鑰都屬於 root ,否則您ssh root@$host
不太可能需要執行 ssh 。sudo
這是一個非常糟糕的主意。此外,在我的 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
會導致 shell 擴展在命令中找到的任何變數(例如 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 and $ 2 如下:
free -m | grep Mem | awk '{print \$1,\$2}