Scheduled Task With Systemd and Ansible
Why use Systemd instead of Cron
Partly because it seems to be the more modern way of doing things
One of the pain points of cron is having to edit the schedule to run a task - wait for a minute and see if it worked then reset the schedule
With systemd I can
- run the job on demand
sudo systemctl start my.service
- check the status
sudo systemctl status my.service
- look at logs
sudo journalctl -u my.service
Also cron will spawn a new process every time it is scheduled - even if the last run is still going. I’ve seen systems crash under load from this.
Systemd by default will not trigger a new run while the last one is still going.
Setup Job
This is for a scheduled database backup - but it is just calling a shell script so could be for anything
It runs as a non-root user
Type=oneshot just means that it runs and completes and is done.
backup.service
[Unit]
Description=Run Database Backup
[Service]
User=backup-manager
Group=backup-manager
Type=oneshot
ExecStart=/home/backup-manager/backups.sh
This defines the schedule
backup.timer
[Unit]
Description=Database Backup Service
[Timer]
OnCalendar=daily
AccuracySec=1h
Persistent=true
[Install]
WantedBy=timers.target
Ansible
This playbook
- installs any packages needed
- creates user and group for the job to run as
- sets the user shell to /bin/nologin
- copies the systemd files
- enables the timer
The playbook also acts as system documentation.
I’m not likely to install this in multiple places but now instead of a setup made from multiple files and package installs it is all in one place.
And the documentation has to be right - because it is how the system is managed.
---
- hosts: all
gather_facts: no
become: true
tasks:
- name: Install tools needed for backup management
ansible.builtin.apt:
name: mysql-client
state: present
update_cache: yes
- name: Ensure backup-manager group exists
ansible.builtin.group:
name: backup-manager
state: present
- name: Add backup manager user
user:
name=backup-manager
shell=/bin/nologin
group=backup-manager
- name: Copy backup script
ansible.builtin.copy:
src: backups.sh
dest: /home/backup-manager/backups.sh
owner: backup-manager
group: backup-manager
mode: '0700'
- name: Copy systemd service file to server
ansible.builtin.copy:
src: backup.service
dest: /etc/systemd/system/
owner: root
group: root
- name: Copy systemd timer file to server
ansible.builtin.copy:
src: backup.timer
dest: /etc/systemd/system/
owner: root
group: root
- name: Enable backup timer
ansible.builtin.systemd_service:
name: backup.timer
state: started
enabled: true