I have a need to embed a fragment of a shell script in a heredoc as part of the creation of a cloud-init script to provision an Ubuntu 14.04 LTE machine. A simplified version of the script demonstrating the problem is as follows:
#!/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}"
Running the above script fails as follows:
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
The problematic character is the closing bracket to the right of "REBOOT", and the obvious solution is to escape the character:
BOUND|RENEW|REBIND|REBOOT\) nsupdate -k /var/lib/dhcp/nsupdate.key << EOX
This backslash character however ends up in the final cloudconfig variable, which in turn breaks the output:
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
This particular fragment above is part of a larger file that is being written that relies on variable interpolation, so quoting there heredoc with >>"EOF" is going to break the rest of our script.
How do I escape the ")" character without the escape character leaking through the heredoc?