101 lines
4.1 KiB
Bash
101 lines
4.1 KiB
Bash
|
|
#!/bin/bash
|
|||
|
|
# check-stack.sh – Statusprüfung DIESES Stacks (MT5, MCP, Trader, Telegram)
|
|||
|
|
# Läuft im Stack-Ordner auf dem Server; Werte kommen aus deploy.conf.
|
|||
|
|
#
|
|||
|
|
# scripts/check-stack.sh ausführlich
|
|||
|
|
# scripts/check-stack.sh -q nur Fehler/Warnungen (cron/Deploy)
|
|||
|
|
# Exit-Code: 0 = ok, 1 = mindestens ein Fehler (Warnungen zählen nicht)
|
|||
|
|
|
|||
|
|
cd "$(dirname "$0")/.." || exit 1
|
|||
|
|
source ./deploy.conf
|
|||
|
|
|
|||
|
|
QUIET=0; [ "${1:-}" = "-q" ] && QUIET=1
|
|||
|
|
FAIL=0
|
|||
|
|
SYMBOL="${CHECK_SYMBOL:-XAUUSD}"
|
|||
|
|
BASE="http://127.0.0.1:$MCP_PORT"
|
|||
|
|
|
|||
|
|
if [ -t 1 ]; then G=$'\e[32m'; R=$'\e[31m'; Y=$'\e[33m'; B=$'\e[1m'; N=$'\e[0m'; else G=; R=; Y=; B=; N=; fi
|
|||
|
|
pfx() { [ $QUIET -eq 1 ] && echo "[$STACK_KEY] "; }
|
|||
|
|
ok() { [ $QUIET -eq 1 ] || echo " ${G}OK${N} $*"; }
|
|||
|
|
warn() { echo " ${Y}WARN${N} $(pfx)$*"; }
|
|||
|
|
fail() { echo " ${R}FAIL${N} $(pfx)$*"; FAIL=1; }
|
|||
|
|
|
|||
|
|
jget() { python3 -c "import json,sys
|
|||
|
|
try: v=json.load(sys.stdin)
|
|||
|
|
except Exception: print('${2:-}'); sys.exit()
|
|||
|
|
for k in '$1'.split('.'):
|
|||
|
|
v = v.get(k) if isinstance(v, dict) else None
|
|||
|
|
print('${2:-}' if v is None else v)"; }
|
|||
|
|
|
|||
|
|
cid() { docker compose ps -q "$1" 2>/dev/null | head -1; }
|
|||
|
|
|
|||
|
|
[ $QUIET -eq 1 ] || echo "${B}== $STACK_NAME ==${N}"
|
|||
|
|
|
|||
|
|
# 1. Container
|
|||
|
|
for svc in "$MT5_SVC" "$MCP_SVC" "$TRADER_SVC"; do
|
|||
|
|
id=$(cid "$svc")
|
|||
|
|
if [ -z "$id" ]; then fail "Dienst $svc: kein Container"; continue; fi
|
|||
|
|
st=$(docker inspect -f '{{.State.Status}}{{if .State.Health}}/{{.State.Health.Status}}{{end}}' "$id")
|
|||
|
|
case "$st" in running/healthy|running) ok "Dienst $svc: $st" ;; *) fail "Dienst $svc: $st" ;; esac
|
|||
|
|
done
|
|||
|
|
|
|||
|
|
# 2. Bridge + Konto
|
|||
|
|
H=$(curl -s -m 10 "$BASE/health")
|
|||
|
|
[ "$(echo "$H" | jget connected)" = "True" ] && ok "MCP $BASE: Bridge verbunden" \
|
|||
|
|
|| fail "MCP $BASE: keine Verbindung zu MT5 (${H:-keine Antwort})"
|
|||
|
|
|
|||
|
|
A=$(curl -s -m 15 "$BASE/account")
|
|||
|
|
if [ -n "$(echo "$A" | jget login)" ]; then
|
|||
|
|
ok "Konto $(echo "$A" | jget login) @ $(echo "$A" | jget server): Balance $(echo "$A" | jget balance)" \
|
|||
|
|
"Equity $(echo "$A" | jget equity) $(echo "$A" | jget currency)"
|
|||
|
|
else
|
|||
|
|
fail "Konto: $(echo "$A" | jget detail "${A:-keine Antwort}")"
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
# 3. Kurs
|
|||
|
|
T=$(curl -s -m 15 "$BASE/tick/$SYMBOL")
|
|||
|
|
if [ -n "$(echo "$T" | jget bid)" ]; then
|
|||
|
|
ok "$SYMBOL → $(echo "$T" | jget symbol): bid $(echo "$T" | jget bid) ask $(echo "$T" | jget ask)"
|
|||
|
|
else
|
|||
|
|
fail "Kurs $SYMBOL: $(echo "$T" | jget detail "${T:-keine Antwort}")"
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
# 4. Positionen
|
|||
|
|
P=$(curl -s -m 15 "$BASE/positions" | jget count)
|
|||
|
|
if [ -z "$P" ]; then fail "Positionen: keine Antwort"
|
|||
|
|
elif [ "$P" -gt 0 ]; then warn "Offene Positionen: $P"
|
|||
|
|
else ok "Offene Positionen: 0"; fi
|
|||
|
|
|
|||
|
|
# 5. Trader-Lebenszeichen (Docker-Zeitstempel = UTC, unabhängig von Zeitzonen)
|
|||
|
|
TID=$(cid "$TRADER_SVC")
|
|||
|
|
if [ -n "$TID" ]; then
|
|||
|
|
LAST=$(docker logs --timestamps --since 10m "$TID" 2>&1 | grep -E "\[(LIVE|DRY)\] Balance" | tail -1)
|
|||
|
|
if [ -n "$LAST" ]; then
|
|||
|
|
AGE=$(( $(date +%s) - $(date -d "$(echo "$LAST" | awk '{print $1}')" +%s 2>/dev/null || echo 0) ))
|
|||
|
|
MODE=$(echo "$LAST" | grep -oE "LIVE|DRY" | head -1)
|
|||
|
|
[ "$AGE" -le 120 ] && ok "Trader lebt ($MODE), letztes Lebenszeichen vor ${AGE}s" \
|
|||
|
|
|| fail "Trader: letztes Lebenszeichen vor ${AGE}s"
|
|||
|
|
else
|
|||
|
|
fail "Trader: keine Balance-Zeile in den letzten 10 min"
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
# 6. Telegram
|
|||
|
|
START=$(docker inspect -f '{{.State.StartedAt}}' "$TID")
|
|||
|
|
CHAN=$(docker logs --since "$START" "$TID" 2>&1 | grep -oE "Active channels: [^|]*" | tail -1)
|
|||
|
|
[ -n "$CHAN" ] && ok "Telegram: $CHAN" || fail "Telegram: keine 'Active channels'-Meldung seit Start"
|
|||
|
|
ERRS=$(docker logs --since 60m "$TID" 2>&1 \
|
|||
|
|
| grep -ciE "AUTH_KEY|EOFError|SessionPasswordNeeded|PhoneNumber|Traceback|disconnected|server closed")
|
|||
|
|
[ "$ERRS" -gt 0 ] && warn "Telegram/Trader: $ERRS Fehlerzeile(n) in der letzten Stunde"
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
if [ -f "$DIAG_FILE" ]; then
|
|||
|
|
DAGE=$(( $(date +%s) - $(stat -c %Y "$DIAG_FILE") ))
|
|||
|
|
[ "$DAGE" -le 900 ] && ok "Diagnose: vor ${DAGE}s geschrieben, $(jget total_messages < "$DIAG_FILE") Nachricht(en)" \
|
|||
|
|
|| fail "Diagnose: seit ${DAGE}s nicht geschrieben ($DIAG_FILE)"
|
|||
|
|
else
|
|||
|
|
warn "Diagnose: $DIAG_FILE fehlt"
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
[ $QUIET -eq 1 ] || { [ $FAIL -eq 0 ] && echo "${G}${B}Alles in Ordnung.${N}" || echo "${R}${B}Fehler – siehe oben.${N}"; }
|
|||
|
|
exit $FAIL
|