#!/bin/bash # Sanad_lite uvicorn launcher. Idempotent — exits cleanly if uvicorn is # already SERVING on :8000. Designed to be called every 2 min by cron. # # This is the copy that actually runs in production, kept here so the repo # is not missing the piece that keeps the site up. It lives on the host at # /home2/sanadliteysloota/sanadlite/start.sh # and is invoked by: # */2 * * * * /home2/sanadliteysloota/sanadlite/start.sh # The absolute paths below are that account's; change them for another host. # --- 1. Health check: is the app actually SERVING HTTP on :8000? ---------- # A plain TCP-connect probe is not enough on its own: a wedged uvicorn (frozen # asyncio loop) still holds the port and completes the TCP handshake, so a # connect-only check reports "up" and never restarts a hung app (this bit us — # the site was down ~2 days on a bound-but-frozen process). So: first cheaply # check whether anything is bound (bash /dev/tcp), and if so require a real # HTTP response too. curl prints "000" on timeout (hung); any real status code # (200/303/401/...) means the event loop is alive and serving. if (exec 3<>/dev/tcp/127.0.0.1/8000) 2>/dev/null; then exec 3<&-; exec 3>&- CODE="$(curl -s -o /dev/null -m 8 -w '%{http_code}' http://127.0.0.1:8000/api/health 2>/dev/null)" if [ -n "$CODE" ] && [ "$CODE" != "000" ]; then exit 0 # bound AND serving → healthy, nothing to do fi # Bound but not responding → wedged. Kill the frozen instance so we can # relaunch cleanly. Pattern is anchored to the venv path so it only ever # matches our own uvicorn, never this script or the selector helper. echo "[start.sh] $(date) — :8000 bound but not serving (code=${CODE:-none}); killing frozen instance" >> /home2/sanadliteysloota/sanadlite/logs/uvicorn.log pkill -9 -f '/home2/sanadliteysloota/virtualenv/sanadlite/.*main.py' 2>/dev/null sleep 2 fi cd /home2/sanadliteysloota/sanadlite # --- 2. Activate the venv (puts python3 on PATH, sets VIRTUAL_ENV) -------- source /home2/sanadliteysloota/virtualenv/sanadlite/3.8/bin/activate # --- 3. Source env vars set in cPanel "Setup Python App" form ------------- # CloudLinux's Python Selector stores them in ~/.cl.selector/python-selector.json # but the activate script does NOT re-export them. Parse + export here. SELECTOR_JSON="$HOME/.cl.selector/python-selector.json" APP_NAME="sanadlite" if [ -f "$SELECTOR_JSON" ]; then eval "$(python - <> /home2/sanadliteysloota/sanadlite/logs/uvicorn.log nohup python main.py >> /home2/sanadliteysloota/sanadlite/logs/uvicorn.log 2>&1 & disown