diff --git a/deploy/systemd/README.md b/deploy/systemd/README.md new file mode 100644 index 0000000..a9d7e7a --- /dev/null +++ b/deploy/systemd/README.md @@ -0,0 +1,31 @@ +# Scheduled export (systemd timer) + +Runs `scripts/export-runner.sh` once a day at **03:30** via a systemd timer (this host +has no cron daemon; the timer is native and, unlike cron, catches up a missed run with +`Persistent=true` if the machine was asleep/off at 03:30). + +`ctrader-export.service` runs `scripts/cron-export.sh` as user `brummel` (a wrapper that +sets a sane PATH, serialises with `flock`, and logs into `runtime/logs/`). + +## Install (one-time, needs sudo) + +```bash +sudo cp deploy/systemd/ctrader-export.service deploy/systemd/ctrader-export.timer \ + /etc/systemd/system/ +sudo systemctl daemon-reload +sudo systemctl enable --now ctrader-export.timer +``` + +## Verify / operate + +```bash +systemctl list-timers ctrader-export.timer # next/last fire time +systemctl status ctrader-export.service # last run result +journalctl -u ctrader-export.service # service-level logs +ls -t runtime/logs/ # per-run export logs +sudo systemctl start ctrader-export.service # run once now, on demand +sudo systemctl disable --now ctrader-export.timer # stop scheduling +``` + +Paths in the unit files are absolute (`/home/brummel/dev/cTrader`). If the repo moves, +update `ExecStart` in `ctrader-export.service` and re-run the install steps. diff --git a/deploy/systemd/ctrader-export.service b/deploy/systemd/ctrader-export.service new file mode 100644 index 0000000..cd7728c --- /dev/null +++ b/deploy/systemd/ctrader-export.service @@ -0,0 +1,13 @@ +[Unit] +Description=cTrader MS_SimpleExport daily market-data export +# The export writes to the NFS-mounted data dir and logs into cTrader over the network. +After=network-online.target +Wants=network-online.target + +[Service] +Type=oneshot +User=brummel +SupplementaryGroups=docker +ExecStart=/home/brummel/dev/cTrader/scripts/cron-export.sh +# A full run is ~15-20 min; allow generous head-room for gap backfills. +TimeoutStartSec=2h diff --git a/deploy/systemd/ctrader-export.timer b/deploy/systemd/ctrader-export.timer new file mode 100644 index 0000000..1272abc --- /dev/null +++ b/deploy/systemd/ctrader-export.timer @@ -0,0 +1,11 @@ +[Unit] +Description=Run the cTrader market-data export daily at 03:30 + +[Timer] +OnCalendar=*-*-* 03:30:00 +# Catch up a missed run (e.g. the machine was asleep/off at 03:30) on next boot. +Persistent=true +Unit=ctrader-export.service + +[Install] +WantedBy=timers.target diff --git a/scripts/cron-export.sh b/scripts/cron-export.sh new file mode 100755 index 0000000..748a3e9 --- /dev/null +++ b/scripts/cron-export.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +# +# Wrapper for scheduled (systemd timer) runs of export-runner.sh. +# Sets a sane PATH (schedulers run with a minimal environment), serialises runs with +# flock so a slow run never overlaps the next tick, and logs each run under +# runtime/logs/ (gitignored). +set -uo pipefail + +export PATH="/usr/local/bin:/usr/bin:/bin" +REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +LOG_DIR="$REPO_ROOT/runtime/logs" +mkdir -p "$LOG_DIR" +LOG="$LOG_DIR/export-$(date +%Y%m%d-%H%M%S).log" + +# Serialise: if a previous run is still going, skip this tick instead of piling up. +exec 9>"$LOG_DIR/.lock" +if ! flock -n 9; then + echo "$(date): another export run is still in progress — skipping this tick" >> "$LOG" + exit 0 +fi + +{ + echo "=== scheduled export run: $(date) ===" + "$REPO_ROOT/scripts/export-runner.sh" + echo "=== exit $? at $(date) ===" +} >> "$LOG" 2>&1 + +# Keep the log dir tidy: drop runs older than 30 days. +find "$LOG_DIR" -name 'export-*.log' -mtime +30 -delete 2>/dev/null || true