【问题标题】:for loop with batch of 5 in the loop循环中包含 5 个批次的 for 循环
【发布时间】:2016-01-13 05:52:40
【问题描述】:

我正在编写一个 shell 脚本,将我们的 AWS EBS 快照从一个区域复制到另一个区域。这是我正在做的一件简单的事情,它从存储在文件(snap_id)中的 ID 列表中运行带有以下命令的 for 循环。

for SID in `cat snap_id`
do
    aws --region us-east-1 ec2 copy-snapshot --source-region us-west-2 --source-snapshot-id $SID --description "copy to us-west"
done

这是一个示例 snap_id 文件(100 行 snap-id)

snap-5ddffd59
snap-9c054999
snap-d94496d9
snap-er2df342
snap-234as234
snap-as234asd
......
......
......

现在我遇到的问题是,我只能在任何给定时间运行其中的 5 个,因为 AWS 限制了您可以同时复制到另一个区域的快照数量。

所以基本上我必须创建一个 5 个队列,并且我必须等到这 5 个完成后才能发送下一个 5 个批次。我可以运行类似下面的命令来获取当前副本的状态(应该被“完成”,如果事情完成,我们将完成 5 个)

aws ec2 describe-snapshots --snapshot-ids (LIST OF CURRENT 5 BATCH) --query Snapshots[].State --output text

那么关于如何使用 bash 构建这样的队列有什么想法吗?

更新 2:根据@jyvet 的建议

我将我的 waitbatch 更改为以下,这样我的超时时间为 1800 秒,如果计数为 5,我会查找所有 5 个(在该批次中)具有完整状态并将计数器增加到 5 (当前批次中的 5 个中有 5 个)我爆发了...欢迎提出建议...

waitbatch() {
count=0

if [ ${ibatch} -gt 0 ]; then
  END=$((SECONDS+1800))
  while [ $SECONDS -lt $END ]; do
    while [ "$count" -le 5 ]; do
    # look for errors ??? and put retries/timeout
      aws ec2 describe-snapshots --snapshot-ids ${list} --query Snapshots[].State --output text > completed_list
      count=0
      for i in `cat completed_list`
      do
        if [ "$i" = "completed" ]
        then
          count=$((count+1))
        fi
      done
      if [ "$count" = "5" ]
      then
        echo count is good, ready to move to next batch
        break
      fi
    echo "sleeping 5 seconds"
    sleep 5
    done
    if [ "$count" = "5" ]
    then
      break
    fi
  done
fi
}

【问题讨论】:

  • 使用 gnu 并行,您只需执行 parallel -P 5 aws --region us-east-1 ec2 copy-snapshot --source-region us-west-2 --source-snapshot-id {} --description "copy to us-west" < snap_id

标签: bash shell amazon-web-services


【解决方案1】:

是这样的:

#!/bin/bash

BATCH=5      # nb of snap ids in a batch 
TIMEOUT=10   # seconds to wait for completion of a batch

ibatch=0

waitbatch() {
    retries=0

    if [ ${ibatch} -gt 0 ]; then
        while [ `aws ec2 describe-snapshots --snapshot-ids (${list}) --query Snapshots[].State --output text | grep -o 'completed' | wc -w` -lt ${BATCH} ]; do
            sleep 1

            retries=$(( ${retries} + 1))

            # Give up if TIMEOUT
            if [ ${retries} -eq ${TIMEOUT} ]; then
                >&2 echo "timeout for ${list}"
                break
            fi
        done
    fi
}


# Loop over all snap ids
for SID in `cat snap_id`
do
    aws --region us-east-1 ec2 copy-snapshot --source-region us-west-2 --source-snapshot-id ${SID} --description "copy to us-west"
    list="${list} ${SID}"

    ibatch=$(( ${ibatch} + 1 ))

    # Check if BATCH is reached
    if [ ${ibatch} -eq ${BATCH} ]; then

        # Wait for completion
        waitbatch

        ibatch=0
        list=""
    fi
done


# Wait for completion
waitbatch

【讨论】:

  • 我确实必须等待最后一批,因为我在任何给定时间只能运行其中的 5 个。这就是复制快照 ..
  • 我在最后添加了一个等待调用
  • 我认为这解决了我的大部分批处理问题,但我认为我仍然需要等待更好的等待来定义 waitbatch。原因是在该批次中的任何给定时间,我的列表可能会输出“已完成已完成待处理已完成待处理”,因此在此等待条件下,它将让下一批通过,我必须等待所有 5 个在让下一批去之前处于完成状态......因为我们在这里使用 grep 并且即使 5 个中有 1 个处于“完成”状态,如果你知道我的意思的话,下一批会通过..
  • 我通过修改 waitbatch 在我的原始帖子中添加了一个更新...欢迎提出建议...
  • 好的,我更新了 while 条件。它应该检查回复是否包含 5 个“已完成”的单词。
猜你喜欢
  • 2021-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-09
  • 2011-01-30
  • 1970-01-01
相关资源
最近更新 更多