feat(hub): deploy_agent_termux.sh (runit+Termux:Boot+wake-lock, helpers shell battery/logcat), panels de batería + logs unificados en node detail
This commit is contained in:
@@ -161,13 +161,36 @@
|
||||
"fieldConfig": { "defaults": {}, "overrides": [ { "matcher": { "id": "byName", "options": "RAM %" }, "properties": [ { "id": "unit", "value": "percent" }, { "id": "custom.cellOptions", "value": { "type": "gauge" } }, { "id": "max", "value": 100 } ] } ] },
|
||||
"options": { "sortBy": [ { "displayName": "RAM %", "desc": true } ] }
|
||||
},
|
||||
{
|
||||
"id": 14,
|
||||
"type": "gauge",
|
||||
"title": "Batería % (móviles)",
|
||||
"gridPos": { "h": 6, "w": 8, "x": 0, "y": 41 },
|
||||
"datasource": { "type": "prometheus", "uid": "victoriametrics" },
|
||||
"targets": [ { "refId": "A", "expr": "node_battery_percent{instance=\"$node\"}", "datasource": { "type": "prometheus", "uid": "victoriametrics" } } ],
|
||||
"fieldConfig": { "defaults": { "unit": "percent", "min": 0, "max": 100, "thresholds": { "mode": "absolute", "steps": [ { "color": "red", "value": null }, { "color": "yellow", "value": 20 }, { "color": "green", "value": 50 } ] } }, "overrides": [] },
|
||||
"options": { "reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false } }
|
||||
},
|
||||
{
|
||||
"id": 15,
|
||||
"type": "timeseries",
|
||||
"title": "Batería: nivel y temperatura",
|
||||
"gridPos": { "h": 6, "w": 16, "x": 8, "y": 41 },
|
||||
"datasource": { "type": "prometheus", "uid": "victoriametrics" },
|
||||
"targets": [
|
||||
{ "refId": "A", "expr": "node_battery_percent{instance=\"$node\"}", "legendFormat": "nivel %", "datasource": { "type": "prometheus", "uid": "victoriametrics" } },
|
||||
{ "refId": "B", "expr": "node_battery_temp_celsius{instance=\"$node\"}", "legendFormat": "temp °C", "datasource": { "type": "prometheus", "uid": "victoriametrics" } }
|
||||
],
|
||||
"fieldConfig": { "defaults": { "custom": { "drawStyle": "line", "fillOpacity": 8, "showPoints": "never", "lineWidth": 2 } }, "overrides": [ { "matcher": { "id": "byName", "options": "temp °C" }, "properties": [ { "id": "unit", "value": "celsius" } ] }, { "matcher": { "id": "byName", "options": "nivel %" }, "properties": [ { "id": "unit", "value": "percent" }, { "id": "max", "value": 100 } ] } ] },
|
||||
"options": { "legend": { "displayMode": "list", "placement": "bottom" }, "tooltip": { "mode": "multi" } }
|
||||
},
|
||||
{
|
||||
"id": 13,
|
||||
"type": "logs",
|
||||
"title": "Logs (journald)",
|
||||
"gridPos": { "h": 11, "w": 24, "x": 0, "y": 41 },
|
||||
"title": "Logs (journald / logcat)",
|
||||
"gridPos": { "h": 11, "w": 24, "x": 0, "y": 47 },
|
||||
"datasource": { "type": "loki", "uid": "loki" },
|
||||
"targets": [ { "refId": "A", "expr": "{instance=\"$node\", job=\"journald\"}", "datasource": { "type": "loki", "uid": "loki" } } ],
|
||||
"targets": [ { "refId": "A", "expr": "{instance=\"$node\"}", "datasource": { "type": "loki", "uid": "loki" } } ],
|
||||
"options": { "showTime": true, "wrapLogMessage": true, "prettifyLogMessage": false, "enableLogDetails": true, "dedupStrategy": "none", "sortOrder": "Descending" }
|
||||
}
|
||||
]
|
||||
|
||||
Executable
+105
@@ -0,0 +1,105 @@
|
||||
#!/usr/bin/env bash
|
||||
# Despliega metrics_agent en un móvil Android/Termux como servicio supervisado
|
||||
# (termux-services / runit) con arranque en boot (Termux:Boot) y wake-lock.
|
||||
#
|
||||
# Uso: ./deploy_agent_termux.sh <node> <ssh_alias>
|
||||
#
|
||||
# Requisitos:
|
||||
# - Binario en apps/metrics_agent/dist/metrics_agent_arm64
|
||||
# (CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -ldflags="-s -w" -o dist/metrics_agent_arm64 .)
|
||||
# - `pass fleet/ingest-pass`.
|
||||
# - En el móvil: Termux + Termux:Boot + Termux:API instalados, paquetes
|
||||
# `termux-services` y `termux-api`, y un alias SSH al sshd de Termux.
|
||||
set -euo pipefail
|
||||
|
||||
NODE="${1:?uso: deploy_agent_termux.sh <node> <ssh_alias>}"
|
||||
HOST="${2:?uso: deploy_agent_termux.sh <node> <ssh_alias>}"
|
||||
|
||||
HUB="https://metrics-dxaqj3ina6eqd5pjt85wkrrj.organic-machine.com/api/v1/import/prometheus"
|
||||
LOKI="https://logs-wmaxecsjcfnocz81d5luca92.organic-machine.com/loki/api/v1/push"
|
||||
PW="$(pass show fleet/ingest-pass | head -1)"
|
||||
BIN="$(cd "$(dirname "$0")/.." && pwd)/apps/metrics_agent/dist/metrics_agent_arm64"
|
||||
|
||||
[ -f "$BIN" ] || { echo "ERROR: falta el binario $BIN (compílalo primero)"; exit 1; }
|
||||
|
||||
echo ">> copiando binario a $HOST"
|
||||
ssh -o BatchMode=yes "$HOST" 'mkdir -p ~/fleet-agent'
|
||||
scp -q -o BatchMode=yes "$BIN" "$HOST:fleet-agent/metrics_agent"
|
||||
|
||||
echo ">> instalando servicio Termux en $NODE ($HOST)"
|
||||
ssh -o BatchMode=yes "$HOST" "NODE='$NODE' PW='$PW' HUB='$HUB' LOKI='$LOKI' bash -s" <<'OUTER'
|
||||
set -e
|
||||
PREFIX=/data/data/com.termux/files/usr
|
||||
HM=/data/data/com.termux/files/home
|
||||
chmod +x "$HM/fleet-agent/metrics_agent"
|
||||
|
||||
cat > "$HM/fleet-agent/agent.json" <<JSON
|
||||
{
|
||||
"node": "${NODE}",
|
||||
"hub_url": "${HUB}",
|
||||
"loki_url": "${LOKI}",
|
||||
"user": "fleet",
|
||||
"pass": "${PW}",
|
||||
"interval_sec": 15,
|
||||
"battery_file": "$HM/fleet-agent/battery.json",
|
||||
"log_file": "$HM/fleet-agent/logcat.log"
|
||||
}
|
||||
JSON
|
||||
chmod 600 "$HM/fleet-agent/agent.json"
|
||||
|
||||
# Servicio runit del agente Go (solo lee ficheros: métricas + battery.json + tail logcat.log).
|
||||
mkdir -p "$PREFIX/var/service/fleet-agent"
|
||||
cat > "$PREFIX/var/service/fleet-agent/run" <<RUN
|
||||
#!$PREFIX/bin/sh
|
||||
exec 2>&1
|
||||
termux-wake-lock
|
||||
exec $HM/fleet-agent/metrics_agent -config $HM/fleet-agent/agent.json
|
||||
RUN
|
||||
chmod +x "$PREFIX/var/service/fleet-agent/run"
|
||||
|
||||
# Helper shell de batería: el exec de sh SÍ funciona en Termux (el bloqueado es
|
||||
# el pidfd_open de Go). Escribe el JSON de termux-battery-status cada 20s.
|
||||
mkdir -p "$PREFIX/var/service/fleet-battery"
|
||||
cat > "$PREFIX/var/service/fleet-battery/run" <<RUN
|
||||
#!$PREFIX/bin/sh
|
||||
exec 2>&1
|
||||
termux-wake-lock
|
||||
while true; do
|
||||
termux-battery-status > $HM/fleet-agent/battery.json.tmp 2>/dev/null && mv $HM/fleet-agent/battery.json.tmp $HM/fleet-agent/battery.json
|
||||
sleep 20
|
||||
done
|
||||
RUN
|
||||
chmod +x "$PREFIX/var/service/fleet-battery/run"
|
||||
|
||||
# Helper shell de logcat: vuelca el log de Android a fichero rotado (cap ~4MB).
|
||||
# El agente Go lo tail-ea sin exec.
|
||||
mkdir -p "$PREFIX/var/service/fleet-logcat"
|
||||
cat > "$PREFIX/var/service/fleet-logcat/run" <<RUN
|
||||
#!$PREFIX/bin/sh
|
||||
exec 2>&1
|
||||
termux-wake-lock
|
||||
exec logcat -v epoch -f $HM/fleet-agent/logcat.log -r 2048 -n 2
|
||||
RUN
|
||||
chmod +x "$PREFIX/var/service/fleet-logcat/run"
|
||||
|
||||
# Arranque en boot (Termux:Boot): wake-lock + runsvdir vía profile.
|
||||
mkdir -p "$HM/.termux/boot"
|
||||
cat > "$HM/.termux/boot/start-fleet.sh" <<BOOT
|
||||
#!$PREFIX/bin/sh
|
||||
termux-wake-lock
|
||||
. $PREFIX/etc/profile
|
||||
BOOT
|
||||
chmod +x "$HM/.termux/boot/start-fleet.sh"
|
||||
|
||||
# Arrancar ya sin esperar a un reinicio: asegurar runsvdir vivo.
|
||||
if ! pgrep -f "runsvdir.*var/service" >/dev/null 2>&1; then
|
||||
nohup runsvdir "$PREFIX/var/service" >/dev/null 2>&1 &
|
||||
sleep 6
|
||||
fi
|
||||
export SVDIR="$PREFIX/var/service"
|
||||
for s in fleet-logcat fleet-battery fleet-agent; do sv up "$s" 2>/dev/null || true; done
|
||||
sleep 5
|
||||
for s in fleet-logcat fleet-battery fleet-agent; do echo -n "$s: "; sv status "$s" 2>/dev/null || echo "N/A"; done
|
||||
OUTER
|
||||
|
||||
echo ">> $NODE desplegado"
|
||||
Reference in New Issue
Block a user