首页 > 解决方案 > 循环遍历 bash 数组以使用 jq 添加新数据——只看到最后的更改

问题描述

我有一个 Bash 脚本,它使用 jq 和一个 for 循环来遍历数组,获取我需要由 Amazon CloudWatch 监控的目录,并将其粘贴到后者的 JSON 配置文件中。但是,由于某种原因,实际上只写入了数组中的最后一项。我假设我的逻辑中有一些东西没有附加我的更改,而是在特定位置覆盖它们,但我无法完全弄清楚修复。

这是我的代码:

logPaths=("/shared/logs/application/application1"
          "/shared/logs/application/application2" 
          "/shared/logs/application/application3")

# Loop through array to create stanzas and export them to the temp file
for i in ${logPaths[@]}; do
    jq "
      .logs.logs_collected.files.collect_list[-1] |= . + {
        \"file_path\": \"$i\",
        \"log_group_name\": \"/aws-account/aws/ec2/syslogs\",
        \"log_stream_name\": \"$definedElsewhere\",
        \"timestamp_format\": \"%b %d %H:%M:%S\"}" \
      /opt/aws/amazon-cloudwatch-agent/amazon-cloudwatch-agent.json \
      > /opt/aws/amazon-cloudwatch-agent/amazon-cloudwatch-agent.json.tmp \
      && cp /opt/aws/amazon-cloudwatch-agent/amazon-cloudwatch-agent.json.tmp /opt/aws/amazon-cloudwatch-agent/amazon-cloudwatch-agent.json
done

执行此操作时,我查看 amazon-cloudwatch-agent.json,配置文件中仅显示数组 (/application3) 中第三个条目的记录。

标签: bashjqamazon-cloudwatch

解决方案


我无法重现您的错误-但这无关紧要,因为如果正确编写,则根本不需要任何循环。

Usingjq --args允许将logPaths数组作为一组位置参数传入,并在相关 jq 代码中以$ARGS.positional. 因此:

#!/usr/bin/env bash

logPaths=("/shared/logs/application/application1"
          "/shared/logs/application/application2"
          "/shared/logs/application/application3")

# Make up some sample input, since the OP didn't provide any
cat >old.json <<'EOF'
{
  "logs": {
    "logs_collected": {
      "files": {
        "collect_list": [
          {"test": "make sure this old data is retained"}
        ]
      }
    }
  }
}
EOF

jq --arg definedElsewhere "Other Value" '
  ($ARGS.positional | [
    .[] | { "file_path": .,
            "log_group_name": "/aws-account/aws/ec2/syslogs",
            "log_stream_name": $definedElsewhere,
            "timestamp_format": "%b %d %H:%M:%S"
          }]) as $newLogSinks |
    .logs.logs_collected.files.collect_list += $newLogSinks
' --args "${logPaths[@]}" <old.json >new.json && mv new.json old.json

...正确地作为输出发出:

{
  "logs": {
    "logs_collected": {
      "files": {
        "collect_list": [
          {
            "test": "make sure this old data is retained"
          },
          {
            "file_path": "/shared/logs/application/application1",
            "log_group_name": "/aws-account/aws/ec2/syslogs",
            "log_stream_name": "Other Value",
            "timestamp_format": "%b %d %H:%M:%S"
          },
          {
            "file_path": "/shared/logs/application/application2",
            "log_group_name": "/aws-account/aws/ec2/syslogs",
            "log_stream_name": "Other Value",
            "timestamp_format": "%b %d %H:%M:%S"
          },
          {
            "file_path": "/shared/logs/application/application3",
            "log_group_name": "/aws-account/aws/ec2/syslogs",
            "log_stream_name": "Other Value",
            "timestamp_format": "%b %d %H:%M:%S"
          }
        ]
      }
    }
  }
}

推荐阅读