#!/bin/bash # ExF Fetcher Startup Script # ========================== # Starts the External Factors fetcher daemon for unattended operation. # # Usage: # ./start_exf.sh # Start daemon # ./start_exf.sh stop # Stop daemon # ./start_exf.sh status # Check status # ./start_exf.sh restart # Restart daemon SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" LOG_FILE="/var/log/exf_fetcher.log" PID_FILE="/var/run/exf_fetcher.pid" WARMUP_SECONDS="${EXF_WARMUP:-15}" case "${1:-start}" in start) if [ -f "$PID_FILE" ] && kill -0 "$(cat "$PID_FILE")" 2>/dev/null; then echo "ExF fetcher already running (PID: $(cat "$PID_FILE"))" exit 0 fi echo "Starting ExF fetcher daemon..." cd "$SCRIPT_DIR" || exit 1 nohup python exf_fetcher_flow.py --warmup "$WARMUP_SECONDS" >> "$LOG_FILE" 2>&1 & echo $! > "$PID_FILE" echo "ExF fetcher started with PID: $(cat "$PID_FILE")" echo "Logs: tail -f $LOG_FILE" # Wait and verify sleep 5 if kill -0 "$(cat "$PID_FILE")" 2>/dev/null; then echo "✓ Process is running" else echo "✗ Process failed to start (check logs)" exit 1 fi ;; stop) if [ -f "$PID_FILE" ]; then PID=$(cat "$PID_FILE") if kill -0 "$PID" 2>/dev/null; then echo "Stopping ExF fetcher (PID: $PID)..." kill "$PID" sleep 2 if kill -0 "$PID" 2>/dev/null; then echo "Force killing..." kill -9 "$PID" fi echo "✓ Stopped" else echo "ExF fetcher not running" fi rm -f "$PID_FILE" else echo "No PID file found" fi ;; restart) $0 stop sleep 2 $0 start ;; status) if [ -f "$PID_FILE" ]; then PID=$(cat "$PID_FILE") if kill -0 "$PID" 2>/dev/null; then echo "ExF fetcher is running (PID: $PID)" ps -p "$PID" -o pid,etime,cmd # Check Hazelcast echo "" echo "Checking Hazelcast data..." python3 << 'PYEOF' import sys sys.path.insert(0, '/mnt/dolphinng5_predict') try: import hazelcast, json client = hazelcast.HazelcastClient(cluster_name="dolphin", cluster_members=["localhost:5701"], connection_timeout=3.0) data = client.get_map("DOLPHIN_FEATURES").blocking().get("exf_latest") if data: parsed = json.loads(data) print(f" ✓ Data flowing: {parsed.get('_ok_count', 0)} indicators") print(f" ✓ Last push: {parsed.get('_pushed_at', 'N/A')}") client.shutdown() except Exception as e: print(f" ✗ Error: {e}") PYEOF else echo "ExF fetcher not running (stale PID file)" rm -f "$PID_FILE" fi else echo "ExF fetcher not running" fi ;; logs) tail -f "$LOG_FILE" ;; *) echo "Usage: $0 {start|stop|restart|status|logs}" exit 1 ;; esac