Lev*_*yle 4 scripting ssh awk shell-script quoting
运行以下脚本时出现问题,^ 意外的换行符或字符串结尾我该如何解决?
[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 ~]#
Run Code Online (Sandbox Code Playgroud)
Kus*_*nda 10
您正在尝试在单引号字符串中使用单引号。与mount | awk | sort管道位于同一行的第一个内部单引号将终止在该ssh行开始的单引号。
实际错误来自awk. 它被交给一个命令行,看起来像{print ,,}(由于$1,$3,$5被调用shell和单引号是在这一点上没有扩展到空字符串)。这被解释为awk一个语法错误(缺少的程序})要在一个名为运行,,}。
我建议将脚本放在实际的脚本文件中,然后在远程主机上运行它,以避免引用问题并允许您创建更易于维护的过程。
此外,
read在while-loop 中使用,而不是for对 的结果进行 -loop 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
Run Code Online (Sandbox Code Playgroud)
正如其他答案中提到的,问题在于在远程运行的命令中使用单引号。正如 SE 上的语法着色所示,{print $1,$3,$5}没有被引用,并且它周围的单引号不会到达远程 shell。
解决此问题的一种方法是使用 here-doc 通过 stdin 将脚本发送到远程:
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
Run Code Online (Sandbox Code Playgroud)
将 here-doc 分隔符"EOF"放在引号中,以便$1本地 shell 不会扩展变量。这应该可以解决本地 shell 的引用问题,但您仍然需要为远程引用内容,例如任何看起来像 glob ([0-9和foo*) 的东西。
tr不需要a-z参数的括号(它们不会造成任何伤害,它们只是告诉它将 a 更改[为 a[并且与 相同])。虽然我认为它的输出netstat包含接口名称,但将它们大写会使名称不同。