From e1ddd0b656e426379dd89d51b24843337ade5e76 Mon Sep 17 00:00:00 2001 From: Magnus Root Date: Thu, 26 Feb 2026 12:47:28 +0300 Subject: [PATCH] Docker check --- README.md | 21 +++++++------------ dockercheck.go | 57 ++++++++++++++++++++++++++++++++++---------------- 2 files changed, 47 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index d71804c..3f8b3f5 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ | `-m` | Проверка совпадений портов Angie ↔ Docker (+ проверка запуска контейнеров) | | `-l` | Проверка обновления файлов PT AF access logs | | `-sv` | Проверка работоспособности служб | +| `-dv` или `-d` | Проверка работоспособности контейнеров | ## Структура проекта @@ -33,7 +34,9 @@ auspex/ │ └── matchcheck/ │ | └── matchcheck.go # -m: совпадения Angie ↔ Docker │ └── servicecheck/ -│ └── servicecheck.go # -sv: проверка работоспособности служб +│ | └── servicecheck.go # -sv: проверка работоспособности служб +│ └── dockercheck/ +│ └── dockercheck.go # -dv или -d: проверка работоспособности служб ├── go.mod ├── Makefile └── README.md @@ -59,7 +62,8 @@ go build -o auspex ./auspex -m # Проверка Angie ↔ Docker (все клиенты) ./auspex -m client_name # Проверка конкретного клиента ./auspex -l # Проверка свежести логов -./auspex -sw # Проверка работоспособности служб +./auspex -sv # Проверка работоспособности служб +./auspex -dv или -d # Проверка работоспособности контейнеров ./auspex -h # Справка ./auspex -v # Версия ``` @@ -68,17 +72,7 @@ go build -o auspex Все настройки находятся в `config.go`. -### Текущий режим: хардкод -Значения прописаны прямо в коде. Для изменения — отредактируйте переменные и пересоберите. - -### Переключение на переменные окружения -В файле `config.go` рядом с каждым хардкод-значением есть закомментированные строки -для чтения из переменных окружения. Для переключения: - -1. Раскомментируйте нужные строки в `config.go` -2. Или вызовите `config.InitFromEnvOverrides()` в `main.go` (строка уже есть, закомментирована) - -### Переменные окружения (при включении) +### Переменные окружения | Переменная | Описание | Значение по умолчанию | |------------|----------|----------------------| @@ -101,6 +95,7 @@ go build -o auspex | `cfgDBPort` | Порт БД | `5432` | | `cfgPrimaryDBHost` | Основная БД | `10.100.10.8` | | `cfgSecondaryDBHost` | Резервная БД | `10.100.13.5` | +| `SERVICES_TO_CHECK ` | Службы для проверки | `ansible,docker` | ## Зависимости diff --git a/dockercheck.go b/dockercheck.go index 72fc039..b89d180 100644 --- a/dockercheck.go +++ b/dockercheck.go @@ -173,22 +173,24 @@ func runDockerCheck() error { // ── Получение контейнеров ──────────────────────────────────────────────────── func dcCheckDockerAvailable() error { - err := exec.Command("docker", "info").Run() + cmd := exec.Command("docker", "info") + out, err := cmd.CombinedOutput() if err != nil { - return fmt.Errorf("docker info завершился с ошибкой: %v", err) + return fmt.Errorf("docker info завершился с ошибкой: %v\n%s", err, string(out)) } return nil } func dcGetContainers() ([]dcContainerInfo, error) { - // Получаем все контейнеры (включая не-running) через Go-шаблон - // Поля: ID, Name, Status, Health, Image — разделитель | - out, err := exec.Command( + // Шаг 1: получаем ID, Name, Status, Image без .Health — оно доступно + // только через docker inspect и отсутствует у контейнеров без healthcheck. + cmd := exec.Command( "docker", "ps", "-a", - "--format", "{{.ID}}|{{.Names}}|{{.Status}}|{{.Health}}|{{.Image}}", - ).Output() + "--format", "{{.ID}}|{{.Names}}|{{.Status}}|{{.Image}}", + ) + out, err := cmd.CombinedOutput() if err != nil { - return nil, fmt.Errorf("docker ps завершился с ошибкой: %v", err) + return nil, fmt.Errorf("docker ps завершился с ошибкой: %v\n%s", err, string(out)) } var containers []dcContainerInfo @@ -196,28 +198,47 @@ func dcGetContainers() ([]dcContainerInfo, error) { if line == "" { continue } - parts := strings.SplitN(line, "|", 5) - if len(parts) != 5 { + parts := strings.SplitN(line, "|", 4) + if len(parts) != 4 { continue } c := dcContainerInfo{ - ID: strings.TrimSpace(parts[0]), - Name: strings.TrimSpace(parts[1]), - Image: strings.TrimSpace(parts[4]), - Health: strings.ToLower(strings.TrimSpace(parts[3])), + ID: strings.TrimSpace(parts[0]), + Name: strings.TrimSpace(parts[1]), + Image: strings.TrimSpace(parts[3]), } - - // Status из docker ps выглядит как "Up 2 hours" или "Exited (1) 3 minutes ago" - // Нормализуем до короткого статуса c.Status = dcNormalizeStatus(parts[2]) - containers = append(containers, c) } + // Шаг 2: получаем health отдельно через docker inspect для каждого контейнера. + // Контейнеры без healthcheck вернут пустую строку — это нормально. + for i := range containers { + containers[i].Health = dcGetHealth(containers[i].ID) + } + return containers, nil } +// dcGetHealth возвращает health статус контейнера через docker inspect. +// Если healthcheck не настроен или inspect завершился с ошибкой — возвращает "none". +func dcGetHealth(containerID string) string { + out, err := exec.Command( + "docker", "inspect", + "--format", "{{if .State.Health}}{{.State.Health.Status}}{{else}}none{{end}}", + containerID, + ).Output() + if err != nil { + return "none" + } + health := strings.ToLower(strings.TrimSpace(string(out))) + if health == "" { + return "none" + } + return health +} + // dcNormalizeStatus приводит вывод docker ps к короткому статусу func dcNormalizeStatus(raw string) string { raw = strings.TrimSpace(raw)