介绍
团队希望每台新报表服务器启动后都显示正确的应用问候语。你将编写 Bash User Data 脚本,在启动 EC2 实例时传入该脚本,并检查应用响应和启动日志。
你应已了解如何启动 EC2 实例并通过 SSH 连接。这个全新环境提供自己的镜像、网络和密钥对;服务器及其启动配置由你创建。
认证备考关联
本实验练习通过程序配置资源和自动化启动,对应 AWS Certified Cloud Practitioner CLF-C02 考试领域 3 的任务 3.1。
在启动时配置应用
在本步骤中,你将编写启动脚本,使用它启动实例,并验证应用响应。
User Data(用户数据)是在启动时传给实例的信息。Linux 启动脚本可以利用它自动配置软件。默认情况下,这些脚本在首次启动时以 root 身份执行,因此脚本内部的命令不需要 sudo。EC2 User Data 官方指南 介绍了这一启动行为及日志位置。
首先进入工作目录:
cd /home/labex/project
预置镜像包含报表应用。将镜像和网络 ID 加载到当前 shell:
source launch.env
使用 here-document 创建 user-data.sh。外层 SCRIPT 标记界定完整脚本;内层 JSON 标记界定应用配置。带引号的标记会保留原样文本。第一行 #!/bin/bash 选择 Bash;set -euo pipefail 使脚本在命令失败或使用未设置变量时停止。最后的 echo 会写入一条便于检查的启动日志。
cat > user-data.sh <<'SCRIPT'
#!/bin/bash
set -euo pipefail
cat > /etc/report-app/config.json <<'JSON'
{
"message": "Started with User Data"
}
JSON
echo 'Report application configuration applied.'
SCRIPT
这会创建本地文件,尚未修改任何实例。使用 --user-data file://user-data.sh 将文件传给 run-instances。AWS CLI 会读取文件并为 API 编码,无需自行编码。将服务器命名为 bootstrap-server:
aws ec2 \
run-instances \
--image-id "$AMI_ID" \
--instance-type t3.micro \
--subnet-id "$SUBNET_ID" \
--security-group-ids "$SECURITY_GROUP_ID" \
--key-name report-key \
--count 1 \
--user-data file://user-data.sh \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=bootstrap-server}]'
保存新实例的 ID。过滤器选择它的名称标签;$(...) 捕获纯文本结果:
INSTANCE_ID=$(aws ec2 \
describe-instances \
--filters Name=tag:Name,Values=bootstrap-server \
--query 'Reservations[0].Instances[0].InstanceId' \
--output text)
检查状态和公网地址:
aws ec2 \
describe-instances \
--instance-ids "$INSTANCE_ID" \
--query 'Reservations[].Instances[].{Instance:InstanceId,State:State.Name,PublicIPv4:PublicIpAddress}'
确认状态为 running。如果仍为 pending,稍等片刻后重复查询。运行状态本身不能证明启动配置成功;接下来检查应用。
打开 AWS View,点击 Refresh resources,在 Application requests 下选择 bootstrap-server。点击 Check application,确认 HTTP 200 和消息 Started with User Data。你通过启动脚本完成了服务器配置,无需在启动后再编辑配置。

示例展示预期响应。你的实例和网络 ID 会不同。
获取公网地址,以便通过 SSH 连接:
PUBLIC_IP=$(aws ec2 \
describe-instances \
--instance-ids "$INSTANCE_ID" \
--query 'Reservations[0].Instances[0].PublicIpAddress' \
--output text)
提供的 SSH 配置会选择私钥和实验访问路径:
ssh -F ssh_config ubuntu@"$PUBLIC_IP"
现在你已进入应用实例。使用管理员权限读取启动输出日志:
sudo cat /var/log/cloud-init-output.log
找到 Report application configuration applied.,这是你提供的脚本输出。诊断启动故障时,先检查日志中的命令错误,再测试应用本身,而不是仅凭实例状态判断。
返回 LabEx 终端:
exit
你也可以取回实例上保存的 User Data。查询选择它的 Base64 值,管道将该值传给 base64 --decode,显示原始脚本:
aws ec2 \
describe-instance-attribute \
--instance-id "$INSTANCE_ID" \
--attribute userData \
--query 'UserData.Value' \
--output text | base64 --decode
确认 Bash 脚本和问候语与你的文件一致。User Data 通常只在首次启动时执行;停止后再启动实例,不会自动重复这些配置。使用启动自动化获得一致的初始配置,并避免在脚本中写入凭证。
终止初始化服务器
在本步骤中,你将移除自己创建的实例,并验证最终状态。
仅终止保存在变量中的这个实例:
aws ec2 \
terminate-instances \
--instance-ids "$INSTANCE_ID"
等待实例达到 terminated。等待器会轮询状态,成功时不输出内容:
aws ec2 \
wait instance-terminated \
--instance-ids "$INSTANCE_ID"
确认最终状态:
aws ec2 \
describe-instances \
--instance-ids "$INSTANCE_ID" \
--query 'Reservations[].Instances[].{Instance:InstanceId,State:State.Name}'
结果应显示 terminated。刷新 AWS View,确认 bootstrap-server 已不再是运行中的应用目标。保留预置网络和密钥对。
总结
你编写了 Bash User Data 脚本,并在启动 EC2 时传入它。你通过 AWS View 验证了应用自动配置,检查了启动输出日志,并取回了保存的脚本。最后,你终止服务器并确认了最终状态。



