我正在通过红帽学院学习,其中一个示例脚本与我的脚本在一个关键方面存在差异,我一直无法理解:
#!/usr/bin/bash
#
USR='student'
OUT='/home/student/output'
#
for SRV in servera serverb
do
ssh ${USR}@${SRV} "hostname -f" > ${OUT}-${SRV}
echo "#####" >> ${OUT}-${SRV}
ssh ${USR}@${SRV} "lscpu | grep '^CPU'" >> ${OUT}-${SRV}
echo "#####" >> ${OUT}-${SRV}
ssh ${USR}@${SRV} "grep -v '^$' /etc/selinux/config|grep -v '^#'" >> ${OUT}-${SRV}
echo "#####" >> ${OUT}-${SRV}
ssh ${USR}@${SRV} "sudo grep 'Failed password' /var/log/secure" >> ${OUT}-${SRV}
echo "#####" >> ${OUT}-${SRV}
done
在变量扩展之后的每一行中,他们都用双引号将命令的大部分内容括起来。现在,我理解了在抑制扩展/替换时双引号和单引号的用法,但我学到的主要内容是直接从RH学院学到的:
建议使用单引号封装正则表达式,以保护任何shell元字符(如$、* 和{}字符)。封装正则表达式可确保字符由预期命令解释,而不是由shell解释。
我可以看到他们在这里这样做是为了确保正则表达式在几行中正确地传递给grep
,但我不知道双引号的用途。
- 他们为什么在那里?
- 为什么它们只在每行的一部分上换行?
- 这是一种常见的做法吗?
1条答案
按热度按时间bq9c1y661#
正如其他人所指出的,所提供的示例存在 * 格式不正确 * 的问题。特别是,第三个ssh要求对**'^$'中的“$”进行转义,以避免shell试图在您端进行替换。否则,远程主机将看到'^'!!
它们使用双引号的目的是“封装”一个 * 构造,该构造意味着在远程服务器上按原样执行,因此将目标主机引用之后的所有内容都括起来。
如果您需要在发送到远程之前展开变量值...AND...当您需要展开到NOT时,就会出现问题。单引号用于包含按原样传递的文本,但如果该文本包含在另一组双引号中,它们的内容不是**“受保护的”,并且只要遇到“$”,shell就会尝试通常的替换。
对于简单的构造,单行命令即可。
但是......当事情变得更复杂时( 使用多级“\”来转义单引号/双引号 *),最好创建一个job-script,在调用ssh之前将其传递到远程主机所需的内容中,然后让ssh以下面的方式引用它:
至于检查密码是否失败的那一行,我绝不会把它留到最后,我会把它作为第一行,检查输出,如果密码失败就放弃,避免其他命令可能失败的尝试,这在当时没有任何意义。