如何在AWS EC2/Lightsail实例重启后自动执行后续脚本?
Got it, let's walk through how to set up this multi-stage automated deployment on AWS Lightsail and EC2. Since you already know about the initial boot scripts, the core trick here is tracking which deployment stage we're in so we don't re-run steps unnecessarily. Here are two solid approaches:
AWS instances (both Lightsail and EC2) use cloud-init by default for initial configuration, so this is the most straightforward method. We'll use a marker file to track our deployment stage, so each boot runs only the steps for the current stage, then updates the marker and triggers a restart if needed.
Step-by-Step Implementation
- Write a cloud-init YAML config (this goes into your instance's User Data during creation):
#cloud-config runcmd: - | # Define our stage marker file path STAGE_FILE="/var/lib/cloud/instance/deployment_stage" # First boot: Install Docker if [ ! -f "$STAGE_FILE" ]; then # Adjust package manager for Amazon Linux (use yum/dnf instead of apt) apt update && apt install -y docker.io systemctl enable --now docker # Mark stage 1 and restart echo "stage1" > "$STAGE_FILE" shutdown -r now # Second boot: Install Component A elif [ "$(cat "$STAGE_FILE")" = "stage1" ]; then apt install -y component-a-package # Add any post-install steps for Component A here # Mark stage 2 and restart echo "stage2" > "$STAGE_FILE" shutdown -r now # Third boot: Install and run Component B elif [ "$(cat "$STAGE_FILE")" = "stage2" ]; then apt install -y component-b-package systemctl enable --now component-b-service # Add any post-setup steps for Component B here # Mark deployment as complete (optional: delete the file instead) echo "completed" > "$STAGE_FILE" fi - Paste this config into your instance's User Data when creating the Lightsail/EC2 instance. Cloud-init will run this script on every boot, but the marker file ensures each stage only runs once.
If you need more control over dependencies or want to split stages into separate manageable units, systemd services are a great option. We'll create one-shot services for each stage, which only run when the previous stage is done.
Step-by-Step Implementation
- Initial cloud-init script (runs on first boot to set up Docker and the first stage service):
#cloud-config runcmd: # Install Docker first - apt update && apt install -y docker.io - systemctl enable --now docker # Create Stage 1 service file - | cat > /etc/systemd/system/deploy-stage1.service << EOF [Unit] Description=Deployment Stage 1 - Install Component A After=network.target [Service] Type=oneshot ExecStart=/bin/bash -c "apt install -y component-a-package && systemctl enable --now deploy-stage2.service && shutdown -r now" RemainAfterExit=yes [Install] WantedBy=multi-user.target EOF # Enable Stage 1 service and restart - systemctl daemon-reload - systemctl enable deploy-stage1.service - shutdown -r now - Stage 2 service (created via Stage 1 or cloud-init):
You can either include this in the initial cloud-init (write it to disk but don't enable it) or have Stage 1 create it. Here's what it looks like:
Once Stage 2 runs, it disables itself so it won't execute on future boots.[Unit] Description=Deployment Stage 2 - Install and Run Component B After=network.target [Service] Type=oneshot ExecStart=/bin/bash -c "apt install -y component-b-package && systemctl enable --now component-b-service && systemctl disable deploy-stage2.service" RemainAfterExit=yes [Install] WantedBy=multi-user.target
- Make scripts idempotent: Ensure each step can safely run multiple times (e.g., use
apt install -ywhich skips already installed packages, or check if a component exists before installing). - Log debugging: Check cloud-init logs at
/var/log/cloud-init.logand/var/log/cloud-init-output.log, or systemd service logs withjournalctl -u deploy-stage1.serviceif you hit issues. - Package manager adjustments: Swap
aptforyumordnfif you're using Amazon Linux instead of Ubuntu/Debian.
内容的提问来源于stack exchange,提问作者Kiksen

