blob: 9fb0b449232e85d4400b0a21555fa2dbbb3361d4 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
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
|