Bash脚本循环修改JSON镜像名遇jq数组索引错误求助
问题:修改ECS任务定义镜像名称时触发jq错误
执行Bash脚本修改JSON格式的ECS任务定义镜像时,遇到如下错误:
jq: error (at
:1): Cannot index array with string "0"
我的Bash循环代码:
NEW_IMAGE='xxxxxxxxxx.dkr.ecr.eu-west-1.amazonaws.com/virtual-layer-robot:xxxxxx' for (( i=1 ; i<=10 ; i++ )); do NEW_IMAGE=$NEW_IMAGE$i j=$((i-1)) NEW_TASK_DEFINITION=$(echo $TASK_DEFINITION | jq -r --arg IMAGE "$NEW_IMAGE" --arg j "$j" '.taskDefinition | .containerDefinitions[$j].image = $IMAGE | del(.taskDefinitionArn) | del(.revision) | del(.status) | del(.requiresAttributes) | del(.compatibilities) | del(.registeredAt) | del (.registeredBy)') done
对应的TASK_DEFINITION JSON结构:
{"taskDefinition": {"taskDefinitionArn": "arn:aws:ecs:eu-west-1:xxxxxx:task-definition/virtual-xxxx-robot-task-xxxxxx:38","containerDefinitions": [{"name": "virtual-robot-1","image": "xxxxxxx.dkr.ecr.eu-west-1.amazonaws.com/virtual-layer-robot:xxxxxx","cpu": 0,"portMappings": [{"containerPort": 89,"hostPort": 89,"protocol": "tcp"}],"essential": false,"environment": [{"name": "CROSS_ACCOUNT_ROLE","value": "arn:aws:iam::xxxxxxx:role/xxxxxx-xxx-xxxxxx-xxxx"}],"mountPoints": [],"volumesFrom": [],"logConfiguration": {"logDriver": "awslogs","options": {"awslogs-create-group": "true","awslogs-group": "/ecs/virtual-layer-robot-2010","awslogs-region": "eu-west-1","awslogs-stream-prefix": "ecs"}}},{"name": "virtual-robot-2","image": "xxxxxxx.dkr.ecr.eu-west-1.amazonaws.com/virtual-layer-robot:xxxxxx","cpu": 0,"portMappings": [{"containerPort": 89,"hostPort": 89,"protocol": "tcp"}],"essential": false,"environment": [{"name": "CROSS_ACCOUNT_ROLE","value": "arn:aws:iam::xxxxxxx:role/xxxxxx-xxxx-xxxxxx-xxxxx"}],"mountPoints": [],"volumesFrom": [],"logConfiguration": {"logDriver": "awslogs","options": {"awslogs-create-group": "true","awslogs-group": "/ecs/virtual-layer-robot-2010","awslogs-region": "eu-west-1","awslogs-stream-prefix": "ecs"}}}]},"tags": []}
错误原因与修正方案
1. 核心错误:jq索引类型不匹配
--arg传递的参数是字符串类型,你的$j是字符串"0"、"1"等,但jq数组需要用数字索引,所以会触发"Cannot index array with string"错误。
解决方法二选一:
方法一:用tonumber转字符串为数字
修改jq命令中的索引部分:
.containerDefinitions[$j|tonumber].image = $IMAGE
方法二:用--argjson直接传递数字参数
把--arg j "$j"替换为--argjson j "$j",这样$j直接以数字类型传入,无需转换:
NEW_TASK_DEFINITION=$(echo "$TASK_DEFINITION" | jq -r --arg IMAGE "$NEW_IMAGE" --argjson j "$j" '.taskDefinition | .containerDefinitions[$j].image = $IMAGE | del(.taskDefinitionArn, .revision, .status, .requiresAttributes, .compatibilities, .registeredAt, .registeredBy)')
2. 镜像名称拼接逻辑错误
你当前的NEW_IMAGE=$NEW_IMAGE$i会导致镜像名累加:
- 第1次循环:
NEW_IMAGE变成原始值1 - 第2次循环:变成
原始值12 - 以此类推,完全不符合每个容器对应
原始值+i的预期
应该保留原始镜像前缀,每次循环重新拼接:
# 把前缀定义在循环外 IMAGE_PREFIX='xxxxxxxxxx.dkr.ecr.eu-west-1.amazonaws.com/virtual-layer-robot:xxxxxx' for (( i=1 ; i<=10 ; i++ )); do NEW_IMAGE="${IMAGE_PREFIX}${i}" # 每次生成独立的镜像名 j=$((i-1)) # 后续jq命令不变(已修复索引问题) done
3. 循环次数超出容器数量
你的JSON里只有2个容器,但循环跑10次,当i>=3时,j=2会超出数组索引范围(数组索引从0开始,最大为1),触发新的jq错误。
建议根据容器数量动态调整循环次数:
# 先获取容器总数 CONTAINER_COUNT=$(echo "$TASK_DEFINITION" | jq '.taskDefinition.containerDefinitions | length') for (( i=1 ; i<=CONTAINER_COUNT ; i++ )); do # 循环逻辑 done
优化后的完整脚本
IMAGE_PREFIX='xxxxxxxxxx.dkr.ecr.eu-west-1.amazonaws.com/virtual-layer-robot:xxxxxx' # 获取原始任务定义的容器数量 CONTAINER_COUNT=$(echo "$TASK_DEFINITION" | jq '.taskDefinition.containerDefinitions | length') # 初始化新任务定义为原始值,避免每次循环从原始数据重新修改 NEW_TASK_DEFINITION="$TASK_DEFINITION" for (( i=1 ; i<=CONTAINER_COUNT ; i++ )); do NEW_IMAGE="${IMAGE_PREFIX}${i}" j=$((i-1)) NEW_TASK_DEFINITION=$(echo "$NEW_TASK_DEFINITION" | jq -r --arg IMAGE "$NEW_IMAGE" --argjson j "$j" '.taskDefinition |= (.containerDefinitions[$j].image = $IMAGE | del(.taskDefinitionArn, .revision, .status, .requiresAttributes, .compatibilities, .registeredAt, .registeredBy))') done
内容的提问来源于stack exchange,提问作者Siddharth Kundu
相关产品推荐
相关产品推荐

