Сбой чтения с помощью set -eou pipefail - PullRequest
0 голосов
/ 18 апреля 2020

У меня есть такой скрипт

#!/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"

Сбой на read -rd '' payload без сообщения. Если я удаляю set -euo pipefail все работает нормально. Что я делаю не так? На самом деле мне даже не нужно set -euo pipefail, просто интересно, почему это происходит.

1 Ответ

1 голос
/ 18 апреля 2020

Команда read пытается прочитать одну строку из стандартного ввода. Если по какой-либо причине происходит сбой - включая попадание в конец файла перед тем, как увидеть терминатор строки - он завершается с ненулевым состоянием. В вашем случае, опция -d '' указывает read искать нулевой символ ASCII в качестве ограничителя строки, и поскольку у документа здесь нет ни одного, который он читает, пока не достигнет EOF ... и затем завершится с статус ошибки. Поведение

read может быть немного нелогичным. Он успешно что-то прочитал и установил переменную (payload) просто отлично; но так как он достиг EOF, стандарт POSIX требует возврата ошибки. То же самое происходит при построчном чтении текстового файла, и последняя строка не заканчивается .

Обычно это не будет большим делом, но * Параметр 1012 * для set заставляет оболочку завершиться, если любая простая команда завершается с ненулевым статусом (ошибка) (с большим количеством грязных исключений , которые здесь не актуальны). Когда read делает это, скрипт сразу же выходит.

Итак, есть несколько возможных решений. Вы можете просто не использовать set -e, вы можете поставить set +e непосредственно перед командой read (и, возможно, set -e снова после), или вы можете сделать ее составной командой, которая будет успешной, например:

read -rd '' payload << EOF || true
...

(Здесь || означает, что если первая команда завершится неудачно, будет запущена вторая, и true всегда будет успешной, поэтому составная команда считается успешной.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...