【发布时间】:2023-03-13 03:16:01
【问题描述】:
我需要在 heredoc 中嵌入一段 shell 脚本,作为创建 cloud-init 脚本的一部分,以配置 Ubuntu 14.04 LTE 机器。演示该问题的脚本的简化版本如下:
#!/bin/bash
cloudconfig=$(cat <<EOF
if host \$NAMESERVER 1>/dev/null 2>&1; then
case \$reason in
BOUND|RENEW|REBIND|REBOOT) nsupdate -k /var/lib/dhcp/nsupdate.key << EOX
server \$NAMESERVER
update delete \$HOST_NAME A
update add \$HOST_NAME \$TTL A \$HOST_ADDR
send
EOX
;;
esac
fi
EOF
)
echo "${cloudconfig}"
运行上述脚本失败如下:
Little-Net:orchestration minfrin$ bash /tmp/test.sh
could not read key from /var/lib/dhcp/nsupdate.{private,key}: file not found
couldn't get address for '$NAMESERVER': not found
有问题的字符是“REBOOT”右侧的右括号,显而易见的解决方案是转义字符:
BOUND|RENEW|REBIND|REBOOT\) nsupdate -k /var/lib/dhcp/nsupdate.key << EOX
这个反斜杠字符最终出现在最终的 cloudconfig 变量中,这反过来又破坏了输出:
Little-Net:orchestration minfrin$ bash /tmp/test.sh
if host $NAMESERVER 1>/dev/null 2>&1; then
case $reason in
BOUND|RENEW|REBIND|REBOOT\) nsupdate -k /var/lib/dhcp/nsupdate.key << EOX
server $NAMESERVER
update delete $HOST_NAME A
update add $HOST_NAME $TTL A $HOST_ADDR
send
EOX
;;
esac
fi
上面的这个特定片段是正在编写的依赖于变量插值的较大文件的一部分,因此用 >>"EOF" 引用 heredoc 将破坏我们脚本的其余部分。
如何在不通过heredoc 泄漏转义字符的情况下转义“)”字符?
【问题讨论】:
-
问题显然是不是 “REBOOT”右边的右括号。请注意,如果您认为
)是问题所在,请创建一个最基本的示例,该示例仅显示该问题,并且不要在此处发布您的全部内容。让我补充一下,在这种情况下,它会告诉您)不是问题。 -
@hek2mgl
)绝对不是问题所在。 /var/lib/dhcp/nsupdate.key 显然不存在或看不到,因为错误清楚地表明,不知道为什么 OP 会认为它是括号。@OP 你为什么要在 cat 中这样做 -
不,
)是问题所在。 shell 将其视为关闭$(...)并尝试在本地运行nsupdate命令,这是不正确的。 -
@EtanReisner 你错了,请试试
-
@hek2mgl 我做到了。它失败了。这似乎是一个 bash 版本问题。它适用于here,但对我来说使用 bash 3 失败了。