I recently needed to add a cleanup service that runs at shutdown to a hundred AWS servers. My requirements were:
- Run the script
/usr/local/sbin/ec2-cleanup.shwhen a VM shuts down (poweroff or reboot). - Send the output from the script to the
syslogservice.
So I needed to create a systemd service file that would call the script when the VM shuts down. This is the ec2-cleanup.service file I created:
# ec2-cleanup.service
[Unit]
Description=Run cleanup at shutdown
After=syslog.service network.target
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStop=/usr/local/sbin/ec2-cleanup.sh
Restart=on-failure
RestartSec=1s
[Install]
WantedBy=multi-user.target
Type=oneshot means that the command runs once. Normally since this is a oneshot service the service would exit after the ExecStart command runs, but since I don’t want to do anything when the service starts, there is is no ExecStart command. That’s why I use RemainAfterExit=yes, which keeps the service running even though there’s no ExecStart command.
Finally I use ExecStop to run the command at shutdown time.
After=syslog.service network.target ensures that the ec2-cleanup.service doesn’t start until after syslog service is running and the network has started. More importantly, since systemd stops services in the reverse order that they’re started, this also ensures that syslog and the network service are still running when systemd runs the ec2-cleanup.service‘s ExecStop command.
Although there are many different available syslog services, most use “syslog” as a service alias, so After=syslog.service should work regardless of which syslog service you actually use. (e.g. If you use rsyslog this still works, because rsyslog declares syslog as an alias.)
Finally, I just needed to install the service on my AWS VMs, so I added this to an Ansible playbook that runs on my AWS VMs:
- name: Install the ec2-cleanup.sh script
copy:
src: ec2-cleanup.sh
dest: /usr/local/sbin/ec2-cleanup.sh
owner: root
group: root
mode: 0755
- name: Install a service to run ec2-cleanup.sh at shutdown
copy:
src: ec2-cleanup.service
dest: /lib/systemd/system/ec2-cleanup.service
owner: root
group: root
mode: 0644
register: ec2_cleanup_service
- name: Restart ec2-cleanup service if the service file changed
systemd:
name: ec2-cleanup
daemon_reload: True
state: restarted
when: ec2_cleanup_service.changed
- name: Enable ec2-cleanup service so it starts on boot
systemd:
name: ec2-cleanup
enabled: True
state: started
To verify that all of this works I ran the Ansible playbook on a VM, then logged in and checked the status of the service:
eruby@i-056ac231adeb1f930:~$ systemctl status ec2-cleanup
● ec2-cleanup.service - Run cleanup at shutdown
Loaded: loaded (/lib/systemd/system/ec2-cleanup.service; enabled; vendor preset: enabled)
Active: active (exited) since Tue 2023-03-14 17:04:37 UTC; 44s ago
Mar 14 17:04:37 i-056ac221aceb1f830 systemd[1]: Finished Run cleanup at shutdown.
The service is active (exited), which I expected (exited because ExecStart has completed, active because RemainAfterExit=yes is keeping the service running until shutdown.
If I reboot the VM and log back in I can check syslog with:
journalctl -u ec2-cleanup.service -n 20
… and see the last 20 lines of output from the script. The log output shows that the script ran when I rebooted.
Hope you find this useful.