Files
server-manager/REDIS_AUDIT.md
2026-02-28 07:15:46 -05:00

8.3 KiB
Raw Permalink Blame History

Аудит Redis — полный отчёт

Дата: 2026-02-28 Версия: v1.8.65 Тестовый сервер: Reddis main ovh (Redis 8.2.1, 27M+ ключей, 2.82GB RAM)


1. Живое тестирование через CLI

Работает корректно

Команда Результат
--redis-info ALIAS Версия, память, клиенты, keyspace
--redis-keys ALIAS "*" SCAN до 1000 ключей, сортировка
--redis ALIAS "PING" True
--redis ALIAS "DBSIZE" 27199166
--redis ALIAS "GET key" Возвращает значение
--redis ALIAS "SET key value" True
--redis ALIAS "DEL key1 key2" Число удалённых
--redis ALIAS "KEYS pattern" Список с нумерацией
--redis ALIAS "INFO memory" Полный вывод секции
--redis ALIAS "TYPE key" Тип данных
--redis ALIAS "TTL key" Секунды / -1
--redis ALIAS "SELECT 1" True
--redis ALIAS "MSET k1 v1 k2 v2" True
--status (redis) ONLINE

Сломано

Команда Ошибка Баг
SET key "hello world" syntax error #1
SET key '{"a":1, "b":2}' syntax error #1
Любое значение с пробелами syntax error #1

2. Найденные баги

БАГ #1 — КРИТИЧНЫЙ: Парсер команд ломает значения с пробелами

Файлы: tools/ssh.py:958, core/redis_client.py:78

Проблема: Используется command.split() вместо shlex.split().

# Текущий код:
parts = command.split()
# "SET key 'hello world'" → ['SET', 'key', "'hello", "world'"]
# Redis получает 4 аргумента вместо 3 → syntax error

Воздействие:

  • Невозможно SET/GET значения с пробелами
  • Невозможно работать с JSON-данными содержащими пробелы
  • Невозможно выполнить EVAL с Lua-скриптами
  • Сломаны команды с multi-word аргументами (SORT, CONFIG SET и др.)

Затронуты: CLI (tools/ssh.py) И GUI (core/redis_client.pyredis_tab.py)


БАГ #2 — СРЕДНИЙ: GUI stats показывает отформатированную строку

Файл: gui/tabs/redis_tab.py:192-208

Проблема: _refresh_stats() вызывает client.execute("DBSIZE"), который возвращает строку "(integer) 27199166" (уже отформатированную через _format()). Эта строка отображается как есть.

# redis_tab.py:198
keys_count = client.execute("DBSIZE")    # Returns "(integer) 27199166"
keys_text = str(keys_count)              # → "(integer) 27199166" in label

Для INFO memory проблема другая:

# redis_tab.py:201
info = client.execute("INFO memory")
# _format() превращает dict в строку, но без \r\n
# Поиск по \r\n ничего не найдёт → memory = "—" всегда
for line in info.split("\r\n"):           # \r\n не найдётся!
    if line.startswith("used_memory_human:"):
        memory = line.split(":")[1].strip()

Воздействие: Статистика в GUI:

  • Keys показывает (integer) 27199166 вместо 27199166
  • Memory всегда показывает (парсинг не находит \r\n)

БАГ #3 — СРЕДНИЙ: GUI RedisClient не поддерживает SSL

Файл: core/redis_client.py:35-43

Проблема: В конструкторе redis.Redis() отсутствует параметр ssl.

# redis_client.py:35-43
self._conn = r.Redis(
    host=self._host,
    port=self._port,
    password=self._password,
    db=self._db,
    decode_responses=True,
    socket_timeout=5,
    socket_connect_timeout=5,
    # ❌ ОТСУТСТВУЕТ: ssl=...
)

При этом CLI (tools/ssh.py:955-956) SSL поддерживает:

ssl_enabled = server.get("ssl", False)
r = redis_lib.Redis(..., ssl=ssl_enabled)

Воздействие: GUI не может подключиться к Redis с TLS/SSL.

Связанная проблема: В server_dialog.py поле use_ssl/ssl НЕ включено в FIELD_MAP["redis"]:

"redis": ["password", "db_index"]   # нет ssl!

Даже если добавить SSL в RedisClient, пользователь не сможет включить его в UI.


БАГ #4 — НИЗКИЙ: CLI Redis ошибки выдают сырой traceback

Файл: tools/ssh.py:957-962

Проблема: r.execute_command() не обёрнут в try-except.

# Текущий код:
result = r.execute_command(*parts)   # При ошибке → необработанное исключение

Пример: HGETALL на string-ключе:

ERROR: ResponseError: WRONGTYPE Operation against a key holding the wrong kind of value

Выводится как traceback с двойным повтором вместо читаемого сообщения.


БАГ #5 — НИЗКИЙ: Двойной PING при status check

Файл: core/status_checker.py:98-110

def _check_redis(self, server: dict) -> bool:
    client = RedisClient(server)
    result = client.connect()      # ← PING #1 внутри connect()
    if result:
        ok = client.check_connection()  # ← PING #2
        client.disconnect()
        return ok
    return False

connect() уже делает self._conn.ping()True. Потом check_connection() вызывает self._conn.ping() ещё раз.


БАГ #6 — НИЗКИЙ: CLI status для Redis без try-except

Файл: tools/ssh.py:698-703

if stype == "redis":
    r = redis_lib.Redis(...)
    r.ping()        # ← Нет try-except! Если offline → traceback
    r.close()
    return "ONLINE"

Сравни с SQL, где conn.close() в finally. Здесь если ping() упадёт, r.close() не вызовется.


ПРОБЛЕМА #7 — Дублирование кода подключения

Файлы: tools/ssh.py:946-956, tools/ssh.py:978-986, tools/ssh.py:1009-1017

Три функции (run_redis_cmd, redis_info, redis_keys) создают одинаковое подключение к Redis копипастом:

import redis as redis_lib
host = server["ip"]
port = server.get("port", 6379)
password = server.get("password", "") or None
db_index = server.get("db_index", 0)
ssl_enabled = server.get("ssl", False)
r = redis_lib.Redis(host=host, port=port, ...)

Этот блок повторяется 3 раза. Вынести в хелпер.


3. Карта проблем по файлам

Файл Строки Баги
tools/ssh.py 958 #1 (split), #4 (error handling), #6 (status), #7 (copypaste)
core/redis_client.py 78, 35-43 #1 (split), #3 (no SSL)
gui/tabs/redis_tab.py 192-208 #2 (stats parsing)
core/status_checker.py 98-110 #5 (double ping)
gui/server_dialog.py 22 #3 (no ssl field for redis)

4. Влияние на пользователей

Сценарий Статус Причина
Простые команды (GET/SET/DEL) Работает Нет пробелов
Команды со значениями с пробелами Сломано Баг #1
JSON-данные с пробелами Сломано Баг #1
GUI статистика Keys ⚠️ Некорректно Баг #2
GUI статистика Memory Всегда "—" Баг #2
SSL-подключение через GUI Невозможно Баг #3
SSL-подключение через CLI Работает
Ошибки в CLI ⚠️ Нечитаемые Баг #4
Status check Работает (с оверхедом) Баг #5