#!/usr/bin/env bash # Install the Rust collector (rust/collector, `ping-collector`) and switch # data collection over to it, or back. # # sudo bash scripts/install_collector.sh # install binary + unit, dry-run check # sudo bash scripts/install_collector.sh --cutover # install, then Rust collects: # # COLLECTION_ENABLED=false, start # # ping-collector, restart water-monitor # sudo bash scripts/install_collector.sh --rollback # Python collects again # # The binary comes from BIN=/path/to/ping-collector (e.g. the "ping-collector- # linux-x86_64" CI artifact) or from rust/target/release/ping-collector, built # beforehand as a normal user: # cargo build --release --locked --manifest-path rust/Cargo.toml # (needs rustup, pkg-config and libssl-dev). set -euo pipefail APP_DIR="${APP_DIR:-/opt/thailand-water-monitor}" ENV_FILE="${APP_DIR}/.env" STATUS_FILE="${APP_DIR}/collector-status.json" REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" MODE="${1:-install}" log() { printf '\033[1;32m==>\033[0m %s\n' "$*"; } die() { printf '\033[1;31m[error]\033[0m %s\n' "$*" >&2; exit 1; } [ "$(id -u)" -eq 0 ] || die "run as root (sudo)" [ -f "$ENV_FILE" ] || die "$ENV_FILE not found" set_env() { local key="$1" value="$2" if grep -q "^${key}=" "$ENV_FILE"; then sed -i "s|^${key}=.*|${key}=${value}|" "$ENV_FILE" else printf '%s=%s\n' "$key" "$value" >>"$ENV_FILE" fi } if [ "$MODE" = "--rollback" ]; then log "Stopping ping-collector; the Python app collects again" systemctl disable --now ping-collector.service 2>/dev/null || true set_env COLLECTION_ENABLED true systemctl restart water-monitor.service log "Done. Check: journalctl -u water-monitor -n 50" exit 0 fi case "$MODE" in install | --cutover) ;; *) die "unknown option: $MODE" ;; esac BIN="${BIN:-${REPO_DIR}/rust/target/release/ping-collector}" [ -x "$BIN" ] || die "no binary at $BIN: build it (see header) or pass BIN=/path/to/ping-collector" log "Installing $BIN -> ${APP_DIR}/bin/ping-collector ($("$BIN" --version))" install -D -m 0755 -o root -g root "$BIN" "${APP_DIR}/bin/ping-collector" install -m 0644 "${REPO_DIR}/scripts/ping-collector.service" /etc/systemd/system/ping-collector.service systemctl daemon-reload # Both services read and write /scraping/status through this file (inside # the app dir: the units use PrivateTmp). set_env SCRAPING_STATUS_FILE "$STATUS_FILE" touch "$STATUS_FILE" chown "$(stat -c %U:%G "$APP_DIR")" "$STATUS_FILE" log "Dry run against the configured database (writes nothing)" (cd "$APP_DIR" && "${APP_DIR}/bin/ping-collector" --env-file "$ENV_FILE" once --dry-run) if [ "$MODE" = "--cutover" ]; then log "Cutover: ping-collector collects, the Python app forecasts and notifies" set_env COLLECTION_ENABLED false systemctl enable --now ping-collector.service systemctl restart water-monitor.service sleep 20 systemctl --no-pager --lines=0 status ping-collector.service || true journalctl -u ping-collector -n 20 --no-pager || true log "Rollback if needed: sudo bash scripts/install_collector.sh --rollback" else log "Installed, not started. Switch over with: sudo bash scripts/install_collector.sh --cutover" fi