From 96a9cd525e7caf46704ba2240c1c86f6892e3aaf Mon Sep 17 00:00:00 2001 From: St33v Date: Sun, 15 Mar 2026 15:48:10 +1100 Subject: Add deployment config and strengthen synopticChart.sh - Inline DeriveTime from func/deriveTimeString.sh; delete func/ - Add set -euo pipefail, quoting, and stderr for error messages - Archive PDFs to /var/lib/synoptic/archive/raw/ after conversion - Publish PNG to /srv/www/synopticLatest.png - Add systemd units: synoptic.{service,timer}, synoptic-retry.{service,timer} - Timer fires at 02:10, 08:10, 14:10, 20:10 UTC (2h after BOM publish slots) - Add nginx site config for pestrel.com - Add setup.sh (run once on VPS as root) and deploy.sh (run from cr4y) Co-Authored-By: Claude Sonnet 4.6 --- deploy.sh | 16 ++++++++ func/deriveTimeString.sh | 33 ----------------- index.html | 5 +++ nginx/pestrel.com.conf | 18 +++++++++ setup.sh | 83 ++++++++++++++++++++++++++++++++++++++++++ synopticChart.sh | 68 ++++++++++++++++++++-------------- systemd/synoptic-retry.service | 12 ++++++ systemd/synoptic-retry.timer | 8 ++++ systemd/synoptic.service | 13 +++++++ systemd/synoptic.timer | 9 +++++ 10 files changed, 204 insertions(+), 61 deletions(-) create mode 100755 deploy.sh delete mode 100755 func/deriveTimeString.sh create mode 100644 index.html create mode 100644 nginx/pestrel.com.conf create mode 100755 setup.sh create mode 100644 systemd/synoptic-retry.service create mode 100644 systemd/synoptic-retry.timer create mode 100644 systemd/synoptic.service create mode 100644 systemd/synoptic.timer diff --git a/deploy.sh b/deploy.sh new file mode 100755 index 0000000..bb1badb --- /dev/null +++ b/deploy.sh @@ -0,0 +1,16 @@ +#!/bin/bash +set -euo pipefail + +REMOTE=st33v@pestrel.com +PORT=40022 + +echo "Deploying synopticChart.sh to ${REMOTE}..." +scp -P "$PORT" synopticChart.sh "${REMOTE}:/opt/synoptic/synopticChart.sh" + +echo "Restarting synoptic.service..." +if ssh -p "$PORT" "$REMOTE" "sudo systemctl restart synoptic.service"; then + echo "SUCCESS: synoptic.service ran cleanly." +else + echo "FAILURE: synoptic.service exited non-zero." >&2 + exit 1 +fi diff --git a/func/deriveTimeString.sh b/func/deriveTimeString.sh deleted file mode 100755 index a09a393..0000000 --- a/func/deriveTimeString.sh +++ /dev/null @@ -1,33 +0,0 @@ - -# BOM releases four synoptic charts per day. -# They are named according to the UTC dat/time for which they are valid. -# -# Filenames follow this template: IDY00030.YYYYMMDDHHMM.[png|pdf] -# -# IDY00030 = the asset name (i.e. the Mean Sea Level Pressure synoptic chart) -# . -# -# . -# (I want pdf because it contains a Scalable Vectort Graphic (SVG) image) - - -# This function returns the filename for the most recent chart. - -DeriveTime() { - nowDate=$(\date -u +%Y%m%d) # backslash req. to unalias date to raw format - nowTime=$(\date -u +%H%M) # (I have date aliased to date -R) -# echo $nowDate$nowTime - - if [ $nowTime -ge 1800 ] ; then - fileTime=1800 - elif [ $nowTime -ge 1200 ] ; then - fileTime=1200 - elif [ $nowTime -ge 0600 ] ; then - fileTime=0600 - else - fileTime=0000 - fi - - echo $nowDate$fileTime -} - diff --git a/index.html b/index.html new file mode 100644 index 0000000..f43eedc --- /dev/null +++ b/index.html @@ -0,0 +1,5 @@ + + +Synoptic +Latest synoptic + diff --git a/nginx/pestrel.com.conf b/nginx/pestrel.com.conf new file mode 100644 index 0000000..372c321 --- /dev/null +++ b/nginx/pestrel.com.conf @@ -0,0 +1,18 @@ +# Synoptic chart site — pestrel.com +# Installed to /etc/nginx/conf.d/synoptic.conf by setup.sh +# +# Requires /etc/nginx/nginx.conf to include: +# include /etc/nginx/conf.d/*.conf; + +server { + listen 80; + listen [::]:80; + server_name pestrel.com www.pestrel.com; + + root /srv/www; + index index.html; + + location / { + try_files $uri $uri/ =404; + } +} diff --git a/setup.sh b/setup.sh new file mode 100755 index 0000000..14c2eec --- /dev/null +++ b/setup.sh @@ -0,0 +1,83 @@ +#!/bin/bash +set -euo pipefail + +# Run once on pestrel as root (or with sudo) to install the synoptic service. +# Usage: sudo ./setup.sh + +if [ "$(id -u)" -ne 0 ]; then + echo "Must run as root or with sudo." >&2 + exit 1 +fi + +SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd) +OWNER=st33v + +# --------------------------------------------------------------------------- +# Nginx conflict checks +# --------------------------------------------------------------------------- +echo "==> Checking for nginx conflicts..." + +CONFLICT=0 + +if grep -rl "server_name.*pestrel\.com" /etc/nginx/ 2>/dev/null; then + echo "WARNING: The above nginx config(s) already reference pestrel.com — check for duplicate server blocks." + CONFLICT=1 +fi + +if grep -rl "listen.*80.*default_server" /etc/nginx/ 2>/dev/null; then + echo "WARNING: The above nginx config(s) define a default_server on port 80 — may intercept traffic intended for this site." + CONFLICT=1 +fi + +if ! grep -q "include.*conf\.d" /etc/nginx/nginx.conf 2>/dev/null; then + echo "WARNING: /etc/nginx/nginx.conf does not appear to include conf.d/*.conf — you may need to add the following line manually:" + echo " include /etc/nginx/conf.d/*.conf;" + CONFLICT=1 +fi + +[ "$CONFLICT" -eq 0 ] && echo " No conflicts detected." + +# --------------------------------------------------------------------------- +# Directories +# --------------------------------------------------------------------------- +echo "==> Creating directories..." +install -d -o "$OWNER" -g "$OWNER" /opt/synoptic +install -d -o "$OWNER" -g "$OWNER" /var/lib/synoptic +install -d -o "$OWNER" -g "$OWNER" /var/lib/synoptic/archive +install -d -o "$OWNER" -g "$OWNER" /var/lib/synoptic/archive/raw +install -d -o "$OWNER" -g "$OWNER" /srv/www + +# --------------------------------------------------------------------------- +# Web content +# --------------------------------------------------------------------------- +echo "==> Writing index.html..." +install -o "$OWNER" -g "$OWNER" -m 644 "$SCRIPT_DIR/index.html" /srv/www/index.html + +# --------------------------------------------------------------------------- +# Systemd units +# --------------------------------------------------------------------------- +echo "==> Installing systemd unit files..." +for unit in synoptic.service synoptic.timer synoptic-retry.service synoptic-retry.timer; do + install -m 644 "$SCRIPT_DIR/systemd/${unit}" "/etc/systemd/system/${unit}" + echo " installed ${unit}" +done + +echo "==> Reloading systemd and enabling timer..." +systemctl daemon-reload +systemctl enable --now synoptic.timer + +# --------------------------------------------------------------------------- +# Nginx +# --------------------------------------------------------------------------- +echo "==> Installing nginx config..." +install -m 644 "$SCRIPT_DIR/nginx/pestrel.com.conf" /etc/nginx/conf.d/synoptic.conf + +echo "==> Testing nginx config..." +nginx -t + +echo "==> Reloading nginx..." +systemctl reload nginx + +# --------------------------------------------------------------------------- +echo "==> Done." +echo " Run 'systemctl list-timers synoptic.timer' to confirm next scheduled run." diff --git a/synopticChart.sh b/synopticChart.sh index e7d3726..a515c90 100755 --- a/synopticChart.sh +++ b/synopticChart.sh @@ -1,37 +1,49 @@ #!/bin/bash -# SJP 28 Nov 2021 -# Get synoptic weather charts from BOM and make them into a movie -# See notes about BOM. they don't like scrapers but permit anon FTP -# for *personal use* -# This script will be called froma timer, once every 6 hours, which is -# how often new charts are published. -# -# The timer will take care of scheduing the call to the script -# todo: check what happens with daylight saving... - -source func/deriveTimeString.sh - -dateTime=$(DeriveTime) +set -euo pipefail + +# SJP 28 Nov 2021 — extended for deployment +# Download BOM synoptic chart (IDY00030) and publish as PNG. +# BOM permits anonymous FTP for personal use. +# Charts are valid at 00, 06, 12, 18 UTC; files appear ~2h later. +# Deployed to /opt/synoptic/synopticChart.sh on pestrel.com. + +ARCHIVE_DIR=/var/lib/synoptic/archive +RAW_DIR=/var/lib/synoptic/archive/raw +LATEST=/srv/www/synopticLatest.png + +# Return the datetime string for the most recently published chart slot. +# BOM chart slots: 0000, 0600, 1200, 1800 UTC. +DeriveTime() { + local nowDate nowTime fileTime + nowDate=$(date -u +%Y%m%d) + nowTime=$(date -u +%H%M) + + if [ "$nowTime" -ge 1800 ]; then fileTime=1800 + elif [ "$nowTime" -ge 1200 ]; then fileTime=1200 + elif [ "$nowTime" -ge 0600 ]; then fileTime=0600 + else fileTime=0000 + fi -latestChart=IDY00030.${dateTime}.pdf -#printf "latestChart filename: %s\n" ${latestChart} + echo "${nowDate}${fileTime}" +} -# -q no config file lookup -# -f fail early -# -s silent -curl -q -fs -o ${latestChart} ftp://ftp.bom.gov.au/anon/gen/fwo/${latestChart} -curlExit=$? +dateTime=$(DeriveTime) +latestChart="IDY00030.${dateTime}.pdf" +# -q no config file lookup -f fail on error -s silent +curlExit=0 +curl -q -fs -o "${latestChart}" "ftp://ftp.bom.gov.au/anon/gen/fwo/${latestChart}" \ + || curlExit=$? -if [ $curlExit -gt 0 ] ; then - # Did we find a file? (Maybe it has not been created yet). - if [ $curlExit -eq 78 ] ; then - echo "No file at remote site $curlExit" - # todo create a one-shot timer service +if [ "$curlExit" -gt 0 ]; then + if [ "$curlExit" -eq 78 ]; then + echo "No file at remote site: ${latestChart} (curl exit ${curlExit})" >&2 fi - exit $curlExit + exit "$curlExit" fi +magick -density 300 "${latestChart}" "${dateTime}.png" -magick -density 300 ${latestChart} ${dateTime}.png - +mv "${latestChart}" "${RAW_DIR}/" +cp "${dateTime}.png" "${ARCHIVE_DIR}/" +mv "${dateTime}.png" "${LATEST}" diff --git a/systemd/synoptic-retry.service b/systemd/synoptic-retry.service new file mode 100644 index 0000000..ed46d41 --- /dev/null +++ b/systemd/synoptic-retry.service @@ -0,0 +1,12 @@ +[Unit] +Description=Retry download and render BOM synoptic chart (after failure) + +[Service] +Type=oneshot +User=st33v +WorkingDirectory=/var/lib/synoptic +ExecStart=/opt/synoptic/synopticChart.sh +ExecStopPost=/bin/sh -c 'STATUS=SUCCESS; [ "$$EXIT_STATUS" != "0" ] && STATUS=FAILURE; logger -t synoptic-retry -p user.err "synoptic-retry $$STATUS exit=$$EXIT_STATUS"' +SyslogIdentifier=synoptic-retry +StandardOutput=journal +StandardError=journal diff --git a/systemd/synoptic-retry.timer b/systemd/synoptic-retry.timer new file mode 100644 index 0000000..fc93089 --- /dev/null +++ b/systemd/synoptic-retry.timer @@ -0,0 +1,8 @@ +[Unit] +Description=Retry synoptic chart download 15 minutes after failure + +[Timer] +OnActiveSec=15min + +[Install] +WantedBy=timers.target diff --git a/systemd/synoptic.service b/systemd/synoptic.service new file mode 100644 index 0000000..33e7237 --- /dev/null +++ b/systemd/synoptic.service @@ -0,0 +1,13 @@ +[Unit] +Description=Download and render BOM synoptic chart +OnFailure=synoptic-retry.timer + +[Service] +Type=oneshot +User=st33v +WorkingDirectory=/var/lib/synoptic +ExecStart=/opt/synoptic/synopticChart.sh +ExecStopPost=/bin/sh -c 'STATUS=SUCCESS; [ "$$EXIT_STATUS" != "0" ] && STATUS=FAILURE; logger -t synoptic -p user.err "synoptic $$STATUS exit=$$EXIT_STATUS"' +SyslogIdentifier=synoptic +StandardOutput=journal +StandardError=journal diff --git a/systemd/synoptic.timer b/systemd/synoptic.timer new file mode 100644 index 0000000..4884078 --- /dev/null +++ b/systemd/synoptic.timer @@ -0,0 +1,9 @@ +[Unit] +Description=Run synoptic chart download at 02:10, 08:10, 14:10, 20:10 UTC + +[Timer] +OnCalendar=*-*-* 02,08,14,20:10:00 UTC +Persistent=true + +[Install] +WantedBy=timers.target -- cgit v1.3