如何遍历AWS Describe-Instances的PowerShell JSON对象并比较启动时间?
关于AWS CLI EC2实例输出遍历与日期比较的问题
我用PowerShell ISE执行以下AWS CLI命令:
aws ec2 --profile $profile --region $region describe-instances --query "Reservations[*].Instances[*].[InstanceId,LaunchTime,State]"
得到的JSON输出为:
[ [ [ "i-abc0123456789", "2023-07-17T04:00:18+00:00", { "Code": 8, "Name": "running" } ] ], [ [ "i-xyz9876543210", "2023-07-17T04:00:16+00:00", { "Code": 16, "Name": "running" } ] ] ]
尝试用以下遍历代码但无输出:
$objects = aws ec2 --profile $awsProfile --region $awsRegion describe-instances --query "Reservations[*].Instances[*].[InstanceId,LaunchTime,State]" | ConvertFrom-Json $objects | ForEach-Object { # Construct and implicitly output a [pscustomobject] # instance from the elements of each nested array. $a = [pscustomobject] @{ instanceid = $_[0][0] launchdateb = [datetimeoffset] $_[0][1] code = $_[0][2].Code name = $_[0][2].Name } Write-Output ("instanceid :"+$a) }
问题1:遍历方式的正确性与优化方案
你的遍历方式有问题,导致无输出。AWS CLI返回的JSON是三层嵌套数组:最外层是Reservations数组,每个Reservation里是Instances数组,每个Instance里是你指定的属性数组。你当前只遍历了最外层的Reservation数组,直接取$_[0][0],但每个Reservation对应的$_是第二层的Instances数组,里面的每个元素才是单个实例的属性数组。
修正后的遍历代码
$objects = aws ec2 --profile $awsProfile --region $awsRegion describe-instances --query "Reservations[*].Instances[*].[InstanceId,LaunchTime,State]" | ConvertFrom-Json # 先展开两层嵌套数组,拿到每个实例的属性数组 $objects | ForEach-Object { $_ } | ForEach-Object { $instanceProps = $_ $instanceObj = [pscustomobject]@{ InstanceId = $instanceProps[0] LaunchTime = [datetimeoffset]$instanceProps[1] StateCode = $instanceProps[2].Code StateName = $instanceProps[2].Name } # 直接输出对象,或格式化输出 $instanceObj # 格式化字符串输出示例: # Write-Output "InstanceId: $($instanceObj.InstanceId), 启动时间: $($instanceObj.LaunchTime.LocalDateTime)" }
更易理解的优化思路
直接修改AWS CLI的--query参数,减少嵌套层级:
# 用[]展开Reservations和Instances,直接返回实例属性的一维数组 $objects = aws ec2 --profile $awsProfile --region $awsRegion describe-instances --query "Reservations[].Instances[].[InstanceId,LaunchTime,State]" | ConvertFrom-Json # 现在直接遍历每个实例的属性数组即可 $objects | ForEach-Object { [pscustomobject]@{ InstanceId = $_[0] LaunchTime = [datetimeoffset]$_[1] StateCode = $_[2].Code StateName = $_[2].Name } }
--query里的Reservations[]和Instances[]会自动展开嵌套,返回的JSON是一维数组,遍历逻辑更直观。
问题2:LaunchTime与其他日期的比较
只要把LaunchTime转换为DateTimeOffset或DateTime类型,就能直接和其他日期对象比较。
示例:筛选启动时间早于指定日期的实例
# 目标日期(UTC时区) $targetDate = [datetimeoffset]"2023-07-18T00:00:00+00:00" # 也可以用本地时间:$targetDate = [datetime]"2023-07-18" $objects = aws ec2 --profile $awsProfile --region $awsRegion describe-instances --query "Reservations[].Instances[].[InstanceId,LaunchTime,State]" | ConvertFrom-Json $objects | ForEach-Object { $launchTime = [datetimeoffset]$_[1] $instanceObj = [pscustomobject]@{ InstanceId = $_[0] LaunchTime = $launchTime StateName = $_[2].Name } # 判断启动时间早于目标日期 if ($launchTime -lt $targetDate) { $instanceObj } }
注意事项
- AWS返回的
LaunchTime是UTC时区字符串,用[datetimeoffset]转换可保留时区信息,避免本地时区转换误差。 - 如果要和本地日期比较,可转换为本地时间:
$launchTime.LocalDateTime,再和本地DateTime对象比较。
内容的提问来源于stack exchange,提问作者Money Times
相关产品推荐
相关产品推荐

