Files
schedls/docs/systemd.md
T
mdaleo404 aded37d491
CI / test (3.11) (push) Canceled after 0s
CI / test (3.12) (push) Canceled after 0s
CI / test (3.13) (push) Canceled after 0s
CI / test (3.14) (push) Canceled after 0s
CI / package (push) Canceled after 0s
CI / precommit-and-security (push) Canceled after 11s
CI / typecheck (push) Canceled after 11s
Initial code commit
2026-09-25 11:16:19 +01:00

107 lines
3.6 KiB
Markdown

# systemd backend
`schedls` manages systemd **timers**. A timer is always paired with a
oneshot service that holds the command.
## Layout
| Scope | Unit directory | Manager |
|--------|------------------------------|----------------------|
| user | `~/.config/systemd/user` | `systemctl --user` |
| system | `/etc/systemd/system` | `systemctl` |
`new --timer` defaults to user scope. System scope must be requested
explicitly with `--system` and appropriate privileges; `schedls` never invokes
`sudo` for you.
## Created files
For a job named `backup`:
```ini
# ~/.config/systemd/user/schedls-backup.service
# Managed by schedls
# Name: backup
[Unit]
Description=schedls job backup
[Service]
Type=oneshot
ExecStart="/usr/local/bin/backup" "/srv/data"
```
```ini
# ~/.config/systemd/user/schedls-backup.timer
# Managed by schedls
# Name: backup
[Unit]
Description=schedls job backup (timer)
[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true
Unit=schedls-backup.service
[Install]
WantedBy=timers.target
```
The `schedls-` prefix and the header comments provide provenance without a
database.
## Argument handling
`ExecStart=` is not shell syntax. `schedls` serializes each argument with
systemd's own quoting rules and always quotes arguments, so a value such as
`$(...)`, `%i`, `$HOME` or an argument beginning with `-` is passed literally.
Use `--shell` to explicitly request `/bin/sh -c`.
Every rendered unit is validated with `systemd-analyze verify` before
installation.
## Calendar expressions
Convenience flags compile to native `OnCalendar=` values:
| Flag | Example | Compiles to |
|------------------|----------------------------|------------------------------------|
| `--daily TIME` | `--daily 02:00` | `*-*-* 02:00:00` |
| `--weekdays TIME`| `--weekdays 08:30` | `Mon..Fri *-*-* 08:30:00` |
| `--weekly D TIME`| `--weekly sun 04:00` | `Sun *-*-* 04:00:00` |
| `--monthly D TIME`| `--monthly 1 06:00` | `*-*-01 06:00:00` |
| `--calendar EXPR`| `--calendar 'Mon..Fri 02:30'` | used verbatim |
`--calendar` may be repeated; systemd supports multiple `OnCalendar=` entries.
## Discovery
Timers are listed with `systemctl list-unit-files` and `list-units`, then
properties are read with `systemctl show`. OnCalendar, Persistent and the
command are read from the unit fragments. The next elapse is taken from
`NextElapseUSecRealtime`; monotonic timers have no wall-clock next run and are
reported as unknown.
## Logs
`schedls logs NAME` queries the service unit's journal via `journalctl
--no-pager`. The job command is never re-executed.
Two options control how much is shown, both passed to `journalctl`:
| Option | Default | Meaning |
|----------------|---------|---------------------------------------------------------------|
| `--lines N` | `50` | number of recent entries (`journalctl --lines=N`) |
| `--since TIME` | none | lower bound on entry time (`journalctl --since=TIME`) |
`TIME` accepts any value `journalctl --since` accepts, for example
`'2026-09-01'`, `'2 hours ago'` or `'2026-09-01 10:00:00'`. `--since` bounds the
range and `--lines` caps how many entries within it are shown. See
[cli.md](cli.md#logs-name) for the full command reference.
## Lingering
User timers only run while the user's systemd manager is alive. `schedls`
warns when lingering is disabled but never enables it.