amazon-web-services - 在ec2 userdata cloudformation中使用for循环和其他声明的变量
问题描述
我是 cloudformation yaml 的新手。
我有以下内容需要在启动配置中用作用户数据:
UserData:
Fn::Base64: !Sub
- |
#!/bin/bash -x
apt-get -y update && apt install -y awscli mysql-client libmysqlclient-dev python-pip
for item in certs user_prop config log
do
echo "... preparing ${item} database and config"
MYSQL_DB_NAME="ext_as_${item}"
LOCAL_DB_NAME=$(echo ${item}|tr -d '_')
LOCAL_DB_FILE="/path/to/db/${LOCAL_DB_NAME}"
DB_KEY="${item}_db"
#- set db configuration value
sed -i "s|${DB_KEY}=.*|${DB_KEY}==mysql://${DB_FQDN}/${MYSQL_DB_NAME}|" /path/to/config.conf
#- create mysql db
mysql --defaults-file=${MYSQL_PREF} -e "CREATE DATABASE IF NOT EXISTS $${MYSQL_DB_NAME};"
#- import local DB schema into MySql if no tables exist
mysql --defaults-file=$${MYSQL_PREF} --silent --skip-column-names \
-e "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = '${MYSQL_DB_NAME}';"|grep -e ^0 -q \
&& ./dbcvt -t ${item} -s sqlite:///${LOCAL_DB_FILE} -d mysql://${DB_FQDN}/${MYSQL_DB_NAME} -p ${MYSQL_PREF}
done
popd
-
DB_FQDN:
'Fn::ImportValue': 'OVPNConfigDbEndpoint'
现在问题DB_FQDN
得到了解决,但是LOCAL_DB_FILE
, LOCAL_DB_NAME
, DB_KEY
, MYSQL_DB_NAME
, 并MYSQL_PREF
没有得到解决。现在的问题是:
- 如果我对其他值进行硬编码,如何在 userdata shell 脚本中使用 for 循环?
- 我是否必须始终使用Alex在https://stackoverflow.com/a/54535452/4035062中提到的 Fn::Join ?
用Fn::Join
写一个简单的shell脚本似乎相当复杂。 - 是什么
+
意思!Sub |+
?
解决方案
您遇到的问题是您希望在${item}
Bash Shell 中扩展变量,而Fn::Sub
Cloudformation 内部函数也解释${item}
为要扩展的变量。
如文档中所述:
要按字面意思书写美元符号和大括号 (
${}
),请在左大括号后添加一个感叹号 (!
),例如${!Literal}
. AWS CloudFormation 将此文本解析为${Literal}
.
但是请记住,Bash 中的大括号通常是可选的。也就是说,您通常可以${item}
简单地重写为$item
.
快速查看您的代码向我建议您可以像这样重写它,它应该没问题:
UserData:
Fn::Base64: !Sub
- |
#!/bin/bash -x
apt-get -y update && apt install -y awscli mysql-client libmysqlclient-dev python-pip
for item in certs user_prop config log
do
echo "... preparing $item database and config"
MYSQL_DB_NAME="ext_as_$item"
LOCAL_DB_NAME=$(echo $item | tr -d '_')
LOCAL_DB_FILE="/path/to/db/$LOCAL_DB_NAME"
DB_KEY="${!item}_db"
#- set db configuration value
sed -i "s|$DB_KEY=.*|$DB_KEY==mysql://${DB_FQDN}/$MYSQL_DB_NAME|" /path/to/config.conf
#- create mysql db
mysql --defaults-file=$MYSQL_PREF -e "CREATE DATABASE IF NOT EXISTS $MYSQL_DB_NAME;"
#- import local DB schema into MySql if no tables exist
mysql --defaults-file=$MYSQL_PREF --silent --skip-column-names \
-e "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = '$MYSQL_DB_NAME';"|grep -e ^0 -q \
&& ./dbcvt -t $item -s sqlite:///$LOCAL_DB_FILE -d mysql://${DB_FQDN}/$MYSQL_DB_NAME -p $MYSQL_PREF
done
popd
-
DB_FQDN:
'Fn::ImportValue': 'OVPNConfigDbEndpoint'
需要注意的要点:
看到这个
DB_KEY
符号${!item}
是必需的,因为 Bash 会在${item_db}
没有大括号的情况下扩展变量。在
${DB_FQDN}
您的情况下当然需要使用${DB_FQDN}
,因为在这种情况下您确实希望替换为Fb::Sub
.另请注意,我修复了您的 Bash 中的一些拼写错误。您
$$
在 2 个地方有错字。
对于您的其他问题:
不,您不需要使用
Fn::Join
. 您正在查看的那个问题是关于是否有人出于某种原因确实想要进行插值Fn::Join
。该答案显示了您可以做到这一点的一种方法。表示法
|+
是 YAML 语言的一个特性。它只是说在块之后保留换行符。请参阅此 YAML备忘单。
推荐阅读
- reactjs - React js CRUD - 添加数据时如何自动更新表而不刷新
- javascript - 在时间段之间获得整个三个月
- javascript - 无法在 jQuery / Ajax 中使用附加成功函数
- python - 捕获 Firebase 504 网关超时
- tcp - 如何使用fluent-bit转发输出插件向tcp端口发送数据
- prolog - Prolog中的图形着色问题:程序未终止
- vb.net - 如何在VB中打开和显示word文档?
- java - 在类路径资源 [mybatis-spring.xml] 中定义名称为“sqlSessionFactory”的 bean 创建错误:
- php - Laravel 助手在 Heroku 上返回错误的路径
- python - 如何使用 OpenCv kmeans C++ 分割霍夫线