#!/bin/sh # ClinicPro production diagnostics โ€” run ON THE HOST as root (or a user with docker access). # Collects every piece of evidence needed to pin down why the service goes down # after hours of uptime (OOM vs full disk vs Redis growth). See docs/ops-restarts.md ยง7. # # Usage: sh collect-diagnostics.sh [container-name-or-id] set -u C="${1:-$(docker ps --format '{{.Names}}' | grep -i -m1 clinic || true)}" echo "=== 1. OOM evidence (kernel, last 48h) ===" journalctl -k --since "48 hours ago" 2>/dev/null | grep -i -E "oom|killed process" | tail -20 \ || dmesg 2>/dev/null | grep -i -E "oom|killed process" | tail -20 echo "" echo "=== 2. Memory / swap now ===" free -h echo "" echo "=== 3. Disk ===" df -h | head -10 du -sh /var/lib/docker/containers/*/*-json.log 2>/dev/null | sort -h | tail -5 echo "" echo "=== 4. Container state ===" docker ps -a --format 'table {{.Names}}\t{{.Status}}' if [ -n "$C" ]; then docker inspect --format \ 'OOMKilled={{.State.OOMKilled}} ExitCode={{.State.ExitCode}} RestartCount={{.RestartCount}} StartedAt={{.State.StartedAt}} FinishedAt={{.State.FinishedAt}}' "$C" fi echo "" echo "=== 5. Live memory per container ===" docker stats --no-stream echo "" echo "=== 6. php-fpm inside app container ===" if [ -n "$C" ]; then docker exec "$C" sh -c 'php -i 2>/dev/null | grep -E "^memory_limit"; ps -o rss,args 2>/dev/null | grep -E "php-fpm|messenger" | grep -v grep' fi echo "" echo "=== 7. Redis memory ===" R="$(docker ps --format '{{.Names}}' | grep -i -m1 redis || true)" if [ -n "$R" ]; then docker exec "$R" redis-cli info memory 2>/dev/null | grep -E "used_memory_human|maxmemory_human|maxmemory_policy" docker exec "$R" redis-cli info server 2>/dev/null | grep -E "uptime_in_seconds|uptime_in_days" docker exec "$R" redis-cli xlen messages 2>/dev/null && echo "(messages stream length above)" echo "--- last redis logs:" docker logs --tail 15 "$R" 2>&1 fi echo "" echo "=== 8. Docker log driver config ===" docker info --format '{{.LoggingDriver}}' 2>/dev/null cat /etc/docker/daemon.json 2>/dev/null || echo "(no daemon.json โ€” log rotation NOT configured)" echo "" echo "=== done โ€” paste this whole output back for diagnosis ==="