| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110 |
- #!/usr/bin/env bash
- # LuxStats background launcher for Arch Linux
- #
- # * Auto-detects every installed CPython 3 and uses the newest one
- # * Runs WITHOUT a venv when the system python already has the deps
- # (pacman: python-pyqt5 python-pyserial python-psutil)
- # * Otherwise creates/uses a managed venv at
- # ${XDG_DATA_HOME:-~/.local/share}/luxstats/venv and installs deps there
- # * Launches the configurator detached from the terminal, logging to
- # ${XDG_STATE_HOME:-~/.local/state}/luxstats/luxstats.log
- #
- # Usage: ./luxstats.sh start in the background
- # ./luxstats.sh stop stop a running instance
- # ./luxstats.sh status show whether it's running
- set -euo pipefail
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
- # works both from the repo root (host/ beside this script) and from packaging/
- if [[ -f "$SCRIPT_DIR/host/luxstats_configurator.py" ]]; then
- APP="$SCRIPT_DIR/host/luxstats_configurator.py"
- elif [[ -f "$SCRIPT_DIR/../host/luxstats_configurator.py" ]]; then
- APP="$(cd "$SCRIPT_DIR/../host" && pwd)/luxstats_configurator.py"
- else
- echo "luxstats: cannot locate host/luxstats_configurator.py" >&2
- exit 1
- fi
- DATA_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/luxstats"
- STATE_DIR="${XDG_STATE_HOME:-$HOME/.local/state}/luxstats"
- VENV="$DATA_DIR/venv"
- LOG="$STATE_DIR/luxstats.log"
- PIDFILE="$STATE_DIR/luxstats.pid"
- DEPS_IMPORT='import PyQt5, serial, psutil'
- mkdir -p "$DATA_DIR" "$STATE_DIR"
- find_newest_python() {
- local best="" bestver=0 py ver base
- # scan PATH + common locations for pythonN.M binaries
- for py in $(compgen -c python3 | sort -u) /usr/bin/python3 \
- /usr/local/bin/python3.*; do
- base="$(basename "$py" 2>/dev/null || true)"
- [[ "$base" =~ ^python3(\.[0-9]+)?$ ]] || continue
- command -v "$py" >/dev/null 2>&1 || [[ -x "$py" ]] || continue
- ver="$("$py" -c 'import sys;print(sys.version_info[0]*1000+sys.version_info[1])' \
- 2>/dev/null)" || continue
- if (( ver > bestver )); then bestver=$ver; best="$py"; fi
- done
- [[ -n "$best" ]] || { echo "luxstats: no python3 found" >&2; return 1; }
- echo "$best"
- }
- pick_interpreter() {
- local sys_py; sys_py="$(find_newest_python)"
- echo "using system interpreter candidate: $sys_py" \
- "($("$sys_py" -V 2>&1))" >&2
- if "$sys_py" -c "$DEPS_IMPORT" 2>/dev/null; then
- echo "$sys_py" # no venv needed
- return
- fi
- echo "system python lacks PyQt5/pyserial/psutil - using managed venv" >&2
- echo "(tip: 'sudo pacman -S python-pyqt5 python-pyserial python-psutil'" \
- "avoids the venv entirely)" >&2
- if [[ ! -x "$VENV/bin/python" ]] \
- || ! "$VENV/bin/python" -c "$DEPS_IMPORT" 2>/dev/null; then
- "$sys_py" -m venv --clear "$VENV"
- "$VENV/bin/pip" install --quiet --upgrade pip
- "$VENV/bin/pip" install --quiet PyQt5 pyserial psutil
- fi
- echo "$VENV/bin/python"
- }
- is_running() {
- [[ -f "$PIDFILE" ]] && kill -0 "$(cat "$PIDFILE")" 2>/dev/null
- }
- case "${1:-start}" in
- start)
- if is_running; then
- echo "luxstats already running (pid $(cat "$PIDFILE"))"
- exit 0
- fi
- PY="$(pick_interpreter)"
- echo "launching with $PY"
- setsid "$PY" "$APP" >>"$LOG" 2>&1 < /dev/null &
- echo $! > "$PIDFILE"
- disown
- echo "luxstats started in the background (pid $(cat "$PIDFILE"))"
- echo "log: $LOG"
- ;;
- stop)
- if is_running; then
- kill "$(cat "$PIDFILE")" && rm -f "$PIDFILE"
- echo "luxstats stopped"
- else
- echo "luxstats is not running"
- fi
- ;;
- status)
- if is_running; then
- echo "running (pid $(cat "$PIDFILE"))"
- else
- echo "not running"
- fi
- ;;
- *)
- echo "usage: $0 [start|stop|status]" >&2
- exit 1
- ;;
- esac
|