Как изменить ответ скручивания в скрипте Bash - PullRequest
0 голосов
/ 11 мая 2018

Как я могу обработать запрос неудачно в этом примере запросов bash curl.Т.е. если все серверы отвечают JSON, то все в порядке, и у меня есть файл JSON в конце цикла.Но если один из этих серверов не отвечает JSON или не отвечает вообще, у меня ничего нет в файле "/data.json", даже все остальные серверы работают отлично.Как я могу поймать сбой сервера и пропустить его?

#!/bin/bash

CONFIG=config.json

jsondata=data.json

i=1
echo "{ \"success\": \"OK\", \"servers\": {" > $jsondata
jq -r '.servers|keys[]' $CONFIG | while read key ; do
    if [ "$i" -ne "1" ]; then
        echo "," >> $jsondata
    fi
    echo "\"server$i\": {" >> $jsondata

    RESPONSE=$(curl -s $HTTP://$IP:$PORT/api)
    DATA1=$(echo $RESPONSE | jq '.data1')
    DATA2=$(echo $RESPONSE | jq '.data2')

    echo "  \"data1\": $DATA1", >> $jsondata
    echo "  \"data2\": $DATA2", >> $jsondata
    echo "}" >> $jsondata
    ((i++))
done

echo "}," >> $jsondata

1 Ответ

0 голосов
/ 11 мая 2018

Во-первых, давайте предположим, что у нас есть функция для выполнения одного вызова API.

do_api () {
  key=$1
  curl $HTTP://$IP:$PORT/api  # Presumably, key is needed here somewhere
}

Я также предполагаю, что предполагаемый вывод - это объект JSON, имеющий как минимум два поля, data1 и data2.Теперь мы можем написать простой конвейер с тремя этапами:

  1. Чтение ключей из $CONFIG
  2. Выполнение вызова API для каждого ключа
  3. Создание требуемого выводаиз объединенного вывода всех вызовов API.

Это не слишком сложно:

jq -r '.servers | keys[]' |                       # stage 1
  while read key; do do_api "$key"; done |        # stage 2
  jq -s 'to_entries |         
          map({key: "server(\.key+1)", 
               value: {data1: .value.data1, 
                       data2: .value.data2}
              }) |
         {success: "OK", servers: from_entries}'  # stage 3

do_api не должно ничего выводить для определенного ключа curl, но не удается, ноВы можете изменить его, чтобы получить какие-то данные по умолчанию, если хотите:

do_api () {
  key=$1
  curl --fail ... || jq -n '{data1: null, data2: null}'
}

jq -s 'to_entries' принимает данные типа

{ "data1": ..., "data2": ... }
{ "data1": ..., "data2": ... }

(что мы и ожидаем отcurl) и выдает в качестве вывода

[ { "key": 0, "value": { "data1": ..., "data2": ... } },
  { "key": 1, "value": { "data1": ..., "data2": ... } }
]

Фильтр map(...) берет предыдущий массив и создает ключи и значения, которые мы хотим добавить к объекту servers в конечном результате, которыйсозданный путем вызова from_entries.


Вот полный пример.tmp.json содержит смоделированный вывод do_api, дополненный дополнительным полем data3, которое будет отфильтровано из окончательного вывода.

$ cat tmp.json
{
    "data1": "foo",
    "data2": "bar",
    "data3": "baz"
}
{
    "data1": "hello",
    "data2": "world",
    "data3": "bye"
}

$ jq -s 'to_entries | map({key: "server\(.key+1)", value: {data1: .value.data1, data2: .value.data2}}) | {success: "OK", servers: from_entries}' tmp.json
{
  "success": "OK",
  "servers": {
    "server1": {
      "data1": "foo",
      "data2": "bar"
    },
    "server2": {
      "data1": "hello",
      "data2": "world"
    }
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...