我试图编写一个简单的bash脚本,以使用现有问题Delete older than month AWS EC2 snapshots中建议的脚本自动删除30天以上的EBS快照
但是,我无法使其正常运行或将日期作为变量:
原始代码如下:
snapshots_to_delete=($(aws ec2 describe-snapshots --owner-ids xxxxxxxxxxxx --query 'Snapshots[?StartTime>=`2017-02-15`].SnapshotId' --output text))
我希望它运行类似:
DATE=`date --date="3 month ago" +%Y-%m-%d`
snapshots_to_delete=($(aws ec2 describe-snapshots --owner-ids xxxxxxxxxxxx --query 'Snapshots[?StartTime>=$DATE].SnapshotId' --output text))
我已经尝试过[
,"
,\
,/
,`
和'
的每种组合使其正常运行,但到目前为止还没有运气!
答案 0 :(得分:3)
解决此问题的一种简单方法是,在需要用文字表示的反引号后面的后面加上单引号,将扩展名放在双引号中,然后切换回单引号。其余命令的引用上下文:
date=$(date --date="3 month ago" +%Y-%m-%d)
IFS=$'\n' read -r -d '' -a snapshots_to_delete < <(
aws ec2 describe-snapshots \
--owner-ids xxxxxxxxxxxx \
--query 'Snapshots[?StartTime>=`'"$date"'`].SnapshotId' && printf '\0'
)
declare -p snapshots_to_delete >&2 # print the resulting value
为什么要这样写?
在'Snapshots[?StartTime>=`'"$date"'`].SnapshotId'
中,存在三个不同的子字符串,每个子字符串都以不同的方式引用,并且在引号样式之间转换语法引号:
'
以单引号引起来;它是shell语法,而不是数据。Snapshots[?StartTime>=`
是第一个子字符串;因为它在单引号中,所以它没有进行任何修改(反引号对于shell来说不是特殊的),因此成为aws
中字符串的一部分命令的参数向量完全按原样。'
,结束该单引号上下文;它也是shell语法,而不是数据。"
是shell语法,用于启动双引号上下文。这是因为在双引号中,保证参数扩展不会进行字符串拆分或glob扩展。$date
是扩展为包含子字符串的第二段-用命名变量的值替换。扩展后的结果用双引号括起来,被视为没有应用进一步解析步骤的数据。"
是结束双引号上下文的语法。'
是开始新的单引号上下文的语法。`].SnapshotId
,第三个被视为数据的子字符串,在该单引号上下文内以文字形式给出;由于这种情况,反引号文字会原样传递给aws
。'
是结束单引号上下文的语法。为date
使用小写的变量名符合POSIX准则,该准则指定全大写名称用于对Shell和OS提供的工具有意义的变量,而名称至少具有保留一个字符供应用程序使用。请参见http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html,请记住shell和环境变量共享一个名称空间。
snapshots_to_delete=( $(...) )
是出于BashPitfalls #50中所述的原因:
IFS=$'\n' read -r -d '' -a snapshots_to_delete
会使stdin从预期以单个NUL字节结尾的流的换行符处拆分为数组元素。如果该NUL字节不存在,则read
将以非零状态退出(表示错误)。&& printf '\0'
命令成功,则将aws
放在aws
命令的末尾会导致发出NUL字节。这样,我们确保将aws
成功或失败的信息传播回read
命令;除了支持替代readarray
或mapfile
命令之外,这对于较旧版本的bash也可移植。$( ... )
优于反引号,因为反引号会更改反斜杠和其中的其他反引号的含义,除非所包含的内容更改了其引号。参见http://wiki.bash-hackers.org/syntax/expansion/cmdsubst#a_closer_look_at_the_two_forms read -r -a < <(...)
代替... | read -r -a
是出于BashFAQ #24中所述的原因。有问题的语法也称为“进程替换”,记录在http://wiki.bash-hackers.org/syntax/expansion/proc_subst