在 ec2 userdata cloudformation 中使用 for 循环和其他声明的变量
Using for loop and other declared variables in ec2 userdata cloudformation
我是 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
没有解决得到解决。现在的问题是:
- 如果我对其他值进行硬编码,我该如何在用户数据 shell 脚本中使用 for 循环?
- 我是否必须始终使用 Alex 在 中提到的 Fn::Join?
使用 Fn::Join
编写一个简单的 shell 脚本似乎相当复杂。
+
在!Sub |+
中是什么意思?
您遇到的问题是您希望 ${item}
等变量在 Bash Shell 中扩展,而 Fn::Sub
Cloudformation 内在函数也解释 ${item}
作为变量展开。
如docs所述:
To write a dollar sign and curly braces (${}
) literally, add an exclamation point (!
) after the open curly brace, such as ${!Literal}
. AWS CloudFormation resolves this text as ${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 cheatsheet.
我是 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
没有解决得到解决。现在的问题是:
- 如果我对其他值进行硬编码,我该如何在用户数据 shell 脚本中使用 for 循环?
- 我是否必须始终使用 Alex 在 中提到的 Fn::Join?
使用Fn::Join
编写一个简单的 shell 脚本似乎相当复杂。 +
在!Sub |+
中是什么意思?
您遇到的问题是您希望 ${item}
等变量在 Bash Shell 中扩展,而 Fn::Sub
Cloudformation 内在函数也解释 ${item}
作为变量展开。
如docs所述:
To write a dollar sign and curly braces (
${}
) literally, add an exclamation point (!
) after the open curly brace, such as${!Literal}
. AWS CloudFormation resolves this text as${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 cheatsheet.