loc="locationA"
usr="user1"
fw_loc=$(</home/user/Desktop/FW_RULES.txt)
ssh -A -tt [email protected] <<ABC
fw_orig="$fw_loc"
fw_cmpr=\$(ssh root@$loc -o LogLevel=ERROR uci show firewall)
wc --lines <<<"\$fw_orig"
wc --lines <<<"\$fw_cmpr"
diff -s <(echo "\$fw_orig") <(echo "\$fw_cmpr")
exit
ABC
我有一个脚本,我将本地文本文件加载到 HERE 文档中的变量中。文本文件大约有 370 行。然后我从另一台服务器获取防火墙规则,并尝试比较防火墙规则是否匹配。但是,在行之后fw_orig="$fw_loc"shell 自动扩展变量(但实际上并不需要)并且终端发出哔声并中断文本,如下所示:
[user2@jump ~]$ fw_orig="firewall.defaults=defaults
>firewall.poplanhttp3=rule
l
> firewall.poplanhttp3.name='poplanhttp3'
> firewall.lanpopchhttp2.name='lanpopahttp5'
> firewal
> firewall.lanpopchhttp2.dest='POPA'
.
firewall.poplanssh2.dest_port='27'
i
> firewall.poplanssh2.target='ACCEPT'
/
每次运行文本时,文本都会在不同的行中断。为什么会发生这些带有声音的中断?我该如何避免?有趣的是,稍后在我的脚本中,我比较了两个变量,行数匹配,但 diff 命令在“$fw_orig”的所有中断中发现变量之间的差异。
编辑 当我尝试将变量写入文件然后进行比较时:
echo "\$fw_orig">/home/user2/file
..
..
diff -s <(echo "\$fw_orig") /home/user2/file
dif 命令返回:
Files /dev/fd/63 and /home/user2/file are identical
也许它可以帮助理解发生了什么..但是,文件<>变量比较有效,变量<>变量比较无效..
答案1
让我们简化这个示例,仅关注故障线路及其一些先决条件,并消除不必要的步骤(例如 ssh)。
该fw_loc
变量包含文件的内容。它肯定有很多换行符和空格;可能还有其他特殊字符。
尽管我看不到该文件的内容,但我还是试图做坏事。因此,以下是您正在做的事情的精简版本,其中包含该文件中的一些虚构的邪恶内容:
fw_loc='foo"; rm -rf "/ouch'
cat <<ABC
fw_orig="$fw_loc"
ABC
如果你执行这个,你会看到打印
fw_orig="foo"; rm -rf "/ouch"
在您的特定情况下,它不是cat
被编辑而是被发送到远程主机来执行。
转义级别显然不够。我相信这就是您遇到奇怪行为的原因,尽管我不确定在您的情况下它在哪些特殊字符上失败。
一种可能的方法是转义该值,以便 bash 中的后续分配(在远程端)可以使用以下命令正常工作printf %q
:
fw_loc='foo"; rm -rf "/ouch'
cat <<ABC
fw_orig=$(printf %q "$fw_loc")
ABC
请注意在变量引用周围立即使用双引号$fw_loc
(否则printf
无法正常完成其工作),但不要在$(...)
命令替换周围使用双引号(因为printf %q
依赖于其输出不在引号内)!
这将打印
fw_orig=foo\"\;\ rm\ -rf\ \"/ouch
fw_loc
这与上面的定义等同。
您可能需要在脚本中再应用几次这个技巧,我还没有仔细研究过。
另一种解决方案可能是将这个复杂的逻辑分解为更小的步骤,例如使用传输文件scp
,甚至传输到本地主机并在本地进行比较。