package service import ( "errors" "hy2xs-admin/util" ) // Жизненный цикл Hysteria принадлежит systemd и install-оркестратору. // Панель умеет только наблюдать состояние: функций Start/Stop/Restart и // смены версии здесь нет намеренно, а не «временно отключены». // InitHysteria2 проверяет единственное, что панели действительно нужно от // Hysteria на старте: наличие бинарника, версию которого показывает дашборд и // у которого спрашивает состояние Hysteria2IsRunning. // // Чтения HYSTERIA2_ENABLE здесь больше нет. Ключ был последним следом модели, // в которой панель сама запускала и останавливала Hysteria: clean install // создавал его со значением "0", записать "1" было некому, а вся ветка // сводилась к строке в журнале. Настройка, которая ничем не управляет, но // выглядит выключателем, хуже отсутствующей. func InitHysteria2() error { if !util.Exists(util.GetHysteria2BinPath()) { return errors.New("systemd-managed hysteria binary not found") } return nil } // Hysteria2IsRunning — ответ systemd о состоянии службы, и НЕ БОЛЬШЕ ТОГО. // // Точность этого ответа ограничена сверху устройством util.Exec: он схлопывает // «systemctl вернул 3, служба неактивна» и «запустить systemctl не удалось» в // одну ошибку. Различить их здесь нельзя, поэтому false означает «служба // неактивна ИЛИ спросить не получилось». // // Отсюда правило, которое стоило продукту трёх дыр: на этом значении нельзя // строить решения о доступе и о применении операции. Ему место в отображении // (дашборд, признак online в списке), где ошибочное «выключено» стоит одной // неверной плашки. Решения о доступе принимаются по фактическому ответу // Traffic Stats API — см. hysteria2Online и disconnectAuthIDs. // // Третья дыра была самой дорогой и жила в cron: гейт `if !Hysteria2IsRunning() // { return }` стоял перед всем циклом учёта, поэтому сломанный systemctl при // живой Hysteria молча отключал и сбор трафика, и принудительное отключение — // без единой строки в журнале. func Hysteria2IsRunning() bool { return hysteria2IsRunning() } // hysteria2IsRunning — та же проверка в виде значения. // // Переменная нужна тестам: без неё каждая проверка, зависящая от состояния // службы, доказуема только на живом systemd, то есть не доказуема в сборке // вовсе. Продуктовый путь от этого не меняется — значение по умолчанию и есть // прежняя реализация. var hysteria2IsRunning = func() bool { _, err := util.Exec("systemctl is-active --quiet hysteria-server") return err == nil } func ReleaseHysteria2() error { return nil }