以下のスクリプトの実行中に問題が発生しました、^予期しない改行または文字列の終わりこれを解決するにはどうすればよいですか?
[root@emrbldbgdapd2 ~]# ./collectdata.sh
collect the data of 10.209.61.124
awk: cmd. line:1: {print
awk: cmd. line:1: ^ unexpected newline or end of string
collect the data of 10.209.61.125
awk: cmd. line:1: {print
awk: cmd. line:1: ^ unexpected newline or end of string
[root@emrbldbgdapd2 ~]#
==========
[root@emrbldbgdapd2 ~]# more collectdata.sh
for i in `cat test`
do echo "collect the data of $i"
ssh -o LogLevel=error -o ConnectTimeout=5 $i 'hostname;
echo "############################";
free -g;
echo "######################################";
echo "######################################";
netstat -nr | grep [0-9] | tr [a-z] [A-Z];
echo "######################################";
echo "######################################";
mount|awk '{print $1,$3,$5}'|sort;
echo "######################################";
echo "######################################";
ip a s | grep -i eth*;
echo "######################################"'>output/$i-`date "+%d%b%Y"`
done
[root@emrbldbgdapd2 ~]#
単一引用符で囲まれた文字列内で単一引用符を使用しようとしています。 mount | awk | sort
パイプラインと同じ行にある最初の内部単一引用符は、ssh
行で開始された単一引用符を終了します。
実際のエラーはawk
が原因です。 {print ,,}
のようなコマンドラインが渡されます($1
、$3
、$5
は、呼び出し側のシェルによって空の文字列に展開され、一重引用符がないためこの時点で)。これは、awk
プログラムとして解釈され、}
というファイルで実行される構文エラー(,,}
がない)が発生します。
スクリプトを実際のスクリプトファイルに入れて、代わりにリモートホストで実行することをお勧めします。これにより、引用の問題を回避し、より保守しやすい手順を作成できるようになります。
さらに、
read
の結果に対してwhile
ループを実行するのではなく、for
ループでcat
を使用します。grep [0-9]
はファイル名のグロビングをトリガーしません。grep eth*
は奇妙に見えます。もしかしてgrep -e 'eth.'
?現在のディレクトリでeth
で始まるすべての名前を取得するファイル名グロビングパターンとして機能することとは別に、パターン(正規表現として解釈される場合)はet
の後にゼロまたはその他h
。変更されたスクリプト:
#!/bin/sh
now=$( date +%d%b%Y )
if [ -d output ]; then
echo 'Output directory missing' >&2
exit 1
fi
while read Host; do
printf 'Collecting data from "%s"...\n' "$Host"
ssh -n -o LogLevel=error -o ConnectTimeout=5 "$Host" \
sh <<'END_SCRIPT' >output/"$Host-$now"
echo '## HOSTNAME:'
hostname
echo '## FREE:'
free -g
echo '## NETSTAT:'
netstat -nr | grep '[0-9]' | tr 'a-z' 'A-Z'
echo '## MOUNT:'
mount | awk '{ print $1, $3, $5 }' | sort
echo '## IP:'
ip a s | grep -i 'eth.*'
END_SCRIPT
done <hosts.txt
他の回答で述べたように、問題は、リモートで実行しているコマンドで単一引用符を使用することです。 SEの構文の色分けが示すように、{print $1,$3,$5}
は引用符で囲まれておらず、その周りの単一引用符はリモートシェルに到達していません。
これを回避する1つの方法は、ヒアドキュメントを使用して、標準入力を介してスクリプトをリモートに送信することです。
ssh somehost /bin/sh > outputfile <<"EOF"
hostname
free -g
netstat -nr | grep "[0-9]" | tr "[a-z]" "[A-Z]"
mount | awk '{print $1,$3,$5}' | sort
# and so on
EOF
ヒアドキュメントの区切り記号"EOF"
を引用符で囲んで、$1
変数がローカルシェルによって展開されないようにします。ローカルシェルでの引用の問題はこれで対処できますが、グロブ([0-9
およびfoo*
)のように見えるもののように、リモート用のものを引用する必要があります。
tr
はa-z
引数に角かっこを必要としません(これらは何の害もありません。[
を[
に変更し、 ]
と同じ)。そのnetstat
の出力にはインターフェース名が含まれていると思いますが、それらを大文字にすると名前が異なります。
行を変更します。
mount|awk '{print $1,$3,$5}'|sort;
に:
mount|awk '\''{print $1,$3,$5}'\''|sort;