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.sh
when a VM shuts down (poweroff or reboot). - Send the output from the script to the
syslog
service.
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.