You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于条件使用Bash脚本在YAML文件中编辑插入Targets节点(含删除功能需求)

如何编写Bash脚本在Prometheus配置YAML中按type和group管理targets?

我有一份Prometheus的scrape配置YAML文件,内容如下:

scrape_configs:
  # The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
  - job_name: 'prometheus'
    static_configs:
      - targets: ['localhost:9090']
  - job_name: 'node-exporter'
    relabel_configs:
      - source_labels: [__address__]
        target_label: instance
        regex: '([^:]+)(:[0-9]+)?'
        replacement: '${1}'
    static_configs:
      - labels:
          type: 'YYY'
          group: 'Bar'
        targets:
          - '192.168.1.134:80'
          - '192.168.1.146:80'
      - labels:
          type: 'YYY'
          group: 'Foo'
        targets:
          - '192.168.2.136:80'
      - labels:
          type: 'ZZZ'
          group: 'Foo'
        targets:
          - '192.168.2.100:80'

我想要写一个Bash脚本,能根据type和group这两个标签字段,给对应的targets列表添加或删除条目。比如执行./manage_targets.sh add 192.168.1.17:80 YYY Bar就能把这个目标添加到type=YYY且group=Bar的targets里;如果执行./manage_targets.sh remove 192.168.1.146:80 YYY Bar就会把这个目标从对应组里删掉。

我之前试过用jq和sed来处理,但都没成功:

  • jq本身是处理JSON的,虽然能转YAML,但处理嵌套结构的匹配和修改很麻烦;
  • sed是基于文本匹配的,没法准确识别YAML的块结构,很容易把内容插错地方。

推荐使用yq工具处理YAML

yq是专门用于YAML文件处理的命令行工具(类似jq但针对YAML),它能轻松解析和修改YAML的嵌套结构,完美解决你的需求。首先确保你已经安装了yq(v4版本,不同版本语法差异大,这里用v4)。

下面是实现的脚本manage_targets.sh,支持添加和删除两种操作:

#!/bin/bash

# 检查参数数量
if [ $# -lt 4 ]; then
    echo "用法: $0 <add|remove> <target> <type> <group>"
    echo "示例: $0 add 192.168.1.17:80 YYY Bar"
    echo "示例: $0 remove 192.168.1.146:80 YYY Bar"
    exit 1
fi

ACTION=$1
TARGET=$2
TYPE=$3
GROUP=$4
YAML_FILE="prometheus.yml" # 替换成你的配置文件路径

# 检查yq是否安装
if ! command -v yq &> /dev/null; then
    echo "错误: 请先安装yq工具(v4版本)"
    exit 1
fi

case $ACTION in
    add)
        # 检查目标是否已存在,避免重复添加
        if yq e ".scrape_configs[] | select(.job_name == \"node-exporter\") | .static_configs[] | select(.labels.type == \"$TYPE\" and .labels.group == \"$GROUP\") | .targets[]" "$YAML_FILE" | grep -q "$TARGET"; then
            echo "目标 $TARGET 已经存在于 type=$TYPE group=$GROUP 中,无需重复添加"
            exit 0
        fi
        # 添加目标到对应组的targets列表
        yq e ".scrape_configs[] |= (select(.job_name == \"node-exporter\") | .static_configs[] |= (select(.labels.type == \"$TYPE\" and .labels.group == \"$GROUP\") | .targets += [\"$TARGET\"]))" -i "$YAML_FILE"
        echo "成功添加目标 $TARGET 到 type=$TYPE group=$GROUP"
        ;;
    remove)
        # 检查目标是否存在
        if ! yq e ".scrape_configs[] | select(.job_name == \"node-exporter\") | .static_configs[] | select(.labels.type == \"$TYPE\" and .labels.group == \"$GROUP\") | .targets[]" "$YAML_FILE" | grep -q "$TARGET"; then
            echo "目标 $TARGET 不存在于 type=$TYPE group=$GROUP 中,无需删除"
            exit 0
        fi
        # 从对应组的targets列表中删除目标
        yq e ".scrape_configs[] |= (select(.job_name == \"node-exporter\") | .static_configs[] |= (select(.labels.type == \"$TYPE\" and .labels.group == \"$GROUP\") | .targets |= (del(.[] | select(. == \"$TARGET\")))))" -i "$YAML_FILE"
        echo "成功删除目标 $TARGET 从 type=$TYPE group=$GROUP"
        ;;
    *)
        echo "无效的操作,请使用 add 或 remove"
        exit 1
        ;;
esac

脚本说明

  1. 参数校验:先检查输入参数是否符合要求,给出清晰的用法提示;
  2. 依赖检查:确认yq已安装,避免脚本运行失败;
  3. 添加逻辑:
    • 先检查目标是否已经存在,防止重复添加;
    • 使用yq精准定位到job_name=node-exporter的scrape配置,再匹配type和group对应的static_configs块,最后把目标追加到targets列表;
  4. 删除逻辑:
    • 先检查目标是否存在,避免无意义的报错;
    • 同样定位到对应块,删除targets中匹配的条目;
  5. 原地修改:使用-i参数让yq直接修改原文件,不需要额外处理临时文件。

使用方法

  1. 给脚本添加执行权限:chmod +x manage_targets.sh
  2. 添加目标:./manage_targets.sh add 192.168.1.17:80 YYY Bar
  3. 删除目标:./manage_targets.sh remove 192.168.1.146:80 YYY Bar

为什么不用jq或sed?

  • jq:虽然可以通过转换格式处理YAML,但来回转换容易丢失YAML的注释和原有格式,而且嵌套结构的匹配修改语法非常繁琐;
  • sed:YAML的缩进和块结构是语义化的,sed的文本匹配无法理解这些结构,很容易把内容插入到错误的缩进位置,或者破坏原有配置格式。

内容的提问来源于stack exchange,提问作者Maxim_united

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 20:02:43