Reputation: 390
I have script like this
#!/bin/bash
# exit when any command fails
set -euo pipefail
api_key="${POWERDNS_API_KEY}"
dns_server_addr="127.0.0.1"
server_id="localhost"
zone_id="${K8S_FQDN_SUFFIX}."
prefix="$1"
ip="$2"
read -rd '' payload << EOF
{
"rrsets": [
{
"name": "$prefix.svc.${K8S_FQDN_SUFFIX}.",
"type": "A",
"changetype": "REPLACE",
"ttl": 10,
"records": [
{
"content": "$ip",
"disabled": false
}
]
}
]
}
EOF
curl -i -H "X-API-Key: $api_key" -X PATCH --data "$payload" \
"http://$dns_server_addr:8081/api/v1/servers/$server_id/zones/$zone_id"
It fails on read -rd '' payload
without message. If I remove set -euo pipefail
everything works fine. What I do wrong? Actually I don't even need set -euo pipefail
, just interesting why this happens.
Upvotes: 1
Views: 6530
Reputation: 125858
The read
command tries to read a single line from standard input. If it fails for any reason -- including hitting the end-of-file before seeing a line terminator -- it exits with a nonzero status. In your case, the -d ''
option tells read
to look for an ASCII null character as the line terminator, and since the here-document doesn't have one it reads until it hits EOF... and then exits with an error status.
read
's behavior may be a bit counterintuitive here. It read something successfully, and set the variable (payload
) just fine; but since it hit EOF it's required by the POSIX standard to return an error. The exact same thing happens when reading a text file line-by-line, and the last line isn't terminated.
Normally this wouldn't be a big deal, but the -e
option to set
makes the shell exit if any simple command exits with a nonzero (error) status (with lots of messy exceptions that aren't relevant here). When read
does that, the script exits on the spot.
So, there are a few possible solutions. You could just not use set -e
, you could put set +e
just before the read
command (and maybe set -e
again afterward), or you could make it a compound command that'll succeed, like this:
read -rd '' payload << EOF || true
...
(Here, the ||
means if the first command fails it'll run the second, and true
always succeeds, so the compound command is considered to succeed.)
Upvotes: 3