如何在Bash脚本中处理卷曲响应失败

时间:2018-05-11 19:27:37

标签: bash curl

在这个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 :(得分:1)

首先,我们假设我们有一个函数来进行单个API调用。

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

我还假设预期的输出是一个JSON对象,其至少两个字段data1data2。现在,我们可以编写一个包含三个阶段的简单管道:

  1. $CONFIG
  2. 读取密钥
  3. 为每个密钥进行API调用
  4. 从所有API调用的组合输出生成所需的输出。
  5. 这不是太复杂:

    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"
        }
      }
    }