Table of Contents

Automation: cron, systemd timers, watchers

cron: quick and familiar

crontab -e        # user crontab (no sudo needed)
# min hour dom mon dow  command
0 9 * * *        ~/bin/backup.sh >> ~/logs/backup.log 2>&1
@daily           ~/bin/daily.sh
@reboot          ~/bin/startup.sh
*/15 * * * *     ~/bin/frequent.sh

Gotchas: cron env is minimal: use absolute paths, set PATH in the crontab (PATH=/usr/local/bin:/usr/bin:/bin), and SHELL=/bin/bash if needed. GUI stuff won't work (no DISPLAY).

systemd timers: better logging, dependencies

Two files per timer, e.g. ~/.config/systemd/user/backup.timer + .service:

# backup.service
[Service]
Type=oneshot
ExecStart=%h/bin/backup.sh
 
# backup.timer
[Unit]
Description=Daily backup
 
[Timer]
OnCalendar=daily
Persistent=true          # catch up if the machine was off
 
[Install]
WantedBy=timers.target
systemctl --user daemon-reload
systemctl --user enable --now backup.timer
systemctl --user list-timers        # next run times
journalctl --user -u backup.service # logs

System-wide equivalents are stored in /etc/systemd/system/ and run as root (systemctl without –user). The PROCHOT mitigation service is an example of a oneshot system unit.

OnCalendar cheat sheet: daily, hourly, weekly, Mon..Fri 09:00, *:0/15 (every 15 min), boot (OnBootSec=5min).

LXQt autostart (GUI apps)

lxqt-config-session → Autostart → Add. Or drop a file in ~/.config/autostart/thing.desktop:

[Desktop Entry]
Type=Application
Name=Conky
Exec=conky -d

Watch a directory: inotifywait

sudo apt install inotify-tools
inotifywait -m -e modify,create ~/watchdir | while read -r _ _ f; do
  echo "changed: $f"; ./rebuild.sh
done

Systemd path units also exist (*.path with PathModified=), good for “run this when a file appears”.

One-off delayed jobs: `at`

sudo apt install at
echo 'notify-send "tea"' | at now + 5 minutes
echo './job.sh' | at 03:00 tomorrow
atq && atrm <job#>

Long-running personal daemons

User service without root (~/.config/systemd/user/thing.service):

[Service]
ExecStart=%h/bin/thing --serve
Restart=on-failure
 
[Install]
WantedBy=default.target

systemctl –user enable –now thing. For it to run without login: loginctl enable-linger $USER.

See Also