summaryrefslogtreecommitdiff
path: root/scripts/cron_daily.sh
diff options
context:
space:
mode:
authorJSDurand <mmemmew@gmail.com>2026-10-21 15:28:20 +0800
committerJSDurand <mmemmew@gmail.com>2026-10-21 15:28:20 +0800
commit75dd524fadc022d9e6845f41f19203c3d5a951cd (patch)
treeb08ec82fe4358c5f9ea047794bb1ff888b35d64d /scripts/cron_daily.sh
parent5c00355c2ccd94195bdb90e1c1e6f51acbcdd7a5 (diff)
add VPS snapshot pipeline, run.sh, and data-repair fixesHEADmaster
- fetch_tw_daily.sh: --snapshot mode (one file per trading day, merged by symbol), retries, validation of numeric fields - cron_daily.sh (VPS): lock, pruning, e-mail alerts on failure - sync_from_vps.sh (Mac): rsync snapshots and merge into per-stock CSVs - run.sh: pick data files for a symbol, build, analyse, open the page - lib.sh: LC_ALL=C; fetch.sh: small fixes - data.rs: repair rows whose open/close fall outside high/low - template: horizontal hover lines in the RSI and KD panels Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Diffstat (limited to 'scripts/cron_daily.sh')
-rwxr-xr-xscripts/cron_daily.sh62
1 files changed, 62 insertions, 0 deletions
diff --git a/scripts/cron_daily.sh b/scripts/cron_daily.sh
new file mode 100755
index 0000000..9fb0b44
--- /dev/null
+++ b/scripts/cron_daily.sh
@@ -0,0 +1,62 @@
+#!/usr/bin/env bash
+# VPS wrapper for cron: download the latest trading day into a daily snapshot file, keep only
+# recent snapshots, and send an e-mail when something goes wrong.
+#
+# crontab (UTC; Taipei = UTC+8):
+# ALERT_TO=you@example.com
+# 30 6 * * 1-5 $HOME/stock/scripts/cron_daily.sh
+# 0 11 * * 1-5 $HOME/stock/scripts/cron_daily.sh
+#
+# Environment: STOCK_DIR (default ~/stock), KEEP_DAYS (default 30), ALERT_TO (e-mail address;
+# needs msmtp or mail). Snapshots go to $STOCK_DIR/updates/YYYY-MM-DD.csv, the log to
+# $STOCK_DIR/logs/daily.log. Failures: download failed after all retries, or no new data for 10 days.
+set -u
+root=${STOCK_DIR:-$HOME/stock}
+keep_days=${KEEP_DAYS:-30}
+updates="$root/updates"; logs="$root/logs"; log="$logs/daily.log"
+mkdir -p "$updates" "$logs"
+
+notify() { # SUBJECT BODY
+ if [ -z "${ALERT_TO:-}" ]; then echo "ALERT_TO is not set; cannot send e-mail: $1" >> "$log"; return; fi
+ if command -v msmtp >/dev/null; then
+ printf 'To: %s\nSubject: %s\n\n%s\n' "$ALERT_TO" "$1" "$2" | msmtp "$ALERT_TO" || echo "msmtp failed" >> "$log"
+ elif command -v mail >/dev/null; then
+ printf '%s\n' "$2" | mail -s "$1" "$ALERT_TO" || echo "mail failed" >> "$log"
+ else
+ echo "no msmtp/mail command; cannot send e-mail: $1" >> "$log"
+ fi
+}
+
+# One run at a time (mkdir is atomic); a lock older than 3 hours is treated as stale.
+lock="$root/.daily.lock"
+if ! mkdir "$lock" 2>/dev/null; then
+ if [ -n "$(find "$lock" -maxdepth 0 -mmin +180 2>/dev/null)" ]; then
+ rmdir "$lock" 2>/dev/null; mkdir "$lock" 2>/dev/null || exit 0
+ else
+ echo "$(date -u +%FT%TZ) another run is in progress, skipping" >> "$log"; exit 0
+ fi
+fi
+out=$(mktemp)
+trap 'rmdir "$lock" 2>/dev/null; rm -f "$out"' EXIT
+
+"$(dirname "$0")/fetch_tw_daily.sh" --snapshot "$updates" > "$out" 2>&1
+rc=$?
+{ echo "== $(date -u +%FT%TZ) exit $rc"; cat "$out"; } >> "$log"
+find "$updates" -name '????-??-??.csv' -mtime +"$keep_days" -delete
+tail -n 3000 "$log" > "$log.tmp" && mv "$log.tmp" "$log" # keep the log small
+
+if [ $rc -ne 0 ]; then
+ notify "stock daily update FAILED on $(hostname) ($(date -u +%F))" "$(tail -n 40 "$out")"
+ exit $rc
+fi
+if grep -qE '^(new|updated):' "$out"; then
+ echo " -> new data written" >> "$log"
+else
+ echo " -> no new trading day" >> "$log"
+ # A long silence (beyond the longest market holiday) means the exchange feed has probably changed.
+ if ! find "$updates" -name '????-??-??.csv' -mtime -10 2>/dev/null | grep -q .; then
+ notify "stock daily update: no new data for 10 days on $(hostname)" "No snapshot file has changed in $updates for 10 days.
+Last log lines:
+$(tail -n 20 "$log")"
+ fi
+fi