mirror of
https://github.com/anten-ka/gotelegram_pro.git
synced 2026-05-19 15:36:03 +00:00
v2.4.8: preflight port-conflict check
Добавлена предустановочная проверка свободы портов перед установкой
telemt. На вход приходит режим (lite/pro) и выбранный порт, проверяются
443 (lite: выбранный), 80 и 8443 (pro). Известный proxy/VPN/веб-софт
(xray, sing-box, v2ray, trojan, hysteria, mtg, shadowsocks, x-ui,
marzban, amneziawg, caddy, apache, haproxy, wireguard, openvpn)
распознаётся по имени процесса и показывается отдельным блоком.
При конфликте пользователь видит список занятых портов, получает
рекомендацию удалить конфликтующий софт или взять чистый VPS, и
может либо форсировать установку, либо отказаться — тогда показывается
15-секундный промо-блок с QR для донатов и возврат в меню.
Override для автоматизированных сценариев: GOTELEGRAM_SKIP_PREFLIGHT=1.
Files:
lib/common.sh — get_port_process, match_known_conflict, preflight_check
lib/lang/ru.sh — preflight_* i18n keys (ru)
lib/lang/en.sh — preflight_* i18n keys (en)
install.sh — preflight_check вызов в install_lite_mode / install_pro_mode;
show_promo_with_qr теперь принимает countdown arg
gotelegram-bot/bot.py — version bump 2.4.7 → 2.4.8
This commit is contained in:
163
lib/common.sh
163
lib/common.sh
@@ -3,7 +3,7 @@
|
||||
# Colors, logging, spinner, system helpers, v1 compat, i18n-aware
|
||||
|
||||
# ── Version ───────────────────────────────────────────────────────────────────
|
||||
GOTELEGRAM_VERSION="2.4.7"
|
||||
GOTELEGRAM_VERSION="2.4.8"
|
||||
GOTELEGRAM_NAME="GoTelegram"
|
||||
|
||||
# ── Пути ──────────────────────────────────────────────────────────────────────
|
||||
@@ -463,6 +463,167 @@ check_port() {
|
||||
return 1 # свободен
|
||||
}
|
||||
|
||||
# ── Preflight: port conflict detection ───────────────────────────────────────
|
||||
# Проверяет, что нужные для установки порты свободны. Если порт занят —
|
||||
# определяет процесс и сопоставляет с известным списком proxy/VPN софта
|
||||
# (xray, sing-box, v2ray, trojan, hysteria, mtg, shadowsocks, x-ui/3x-ui,
|
||||
# marzban, amneziawg, caddy, apache, haproxy). Пользователь видит явное
|
||||
# предупреждение и может либо прервать установку, либо продолжить на свой
|
||||
# страх и риск (GOTELEGRAM_SKIP_PREFLIGHT=1 — полностью отключить проверку).
|
||||
#
|
||||
# Используемые порты GoTelegram:
|
||||
# 443 — telemt (внешний, MTProxy + fake-TLS) — lite и pro
|
||||
# 80 — nginx redirect + certbot ACME HTTP-01 — только pro
|
||||
# 8443 — nginx internal mask (127.0.0.1:8443) — только pro
|
||||
|
||||
# get_port_process <port> → "<pid>|<comm>" если занят, иначе пусто
|
||||
get_port_process() {
|
||||
local port="$1"
|
||||
local line="" pid="" proc=""
|
||||
line=$(ss -tlnp 2>/dev/null | grep -E ":${port}[[:space:]]" | head -1)
|
||||
if [ -z "$line" ]; then
|
||||
line=$(netstat -tlnp 2>/dev/null | grep -E ":${port}[[:space:]]" | head -1)
|
||||
fi
|
||||
if [ -n "$line" ]; then
|
||||
pid=$(echo "$line" | grep -oE 'pid=[0-9]+' | head -1 | cut -d= -f2)
|
||||
if [ -z "$pid" ]; then
|
||||
# netstat format: "12345/procname"
|
||||
pid=$(echo "$line" | grep -oE '[0-9]+/[^ ]+' | head -1 | cut -d/ -f1)
|
||||
fi
|
||||
fi
|
||||
if [ -z "$pid" ]; then
|
||||
pid=$(fuser -n tcp "$port" 2>/dev/null | tr -s ' ' | awk '{print $1}' | head -1)
|
||||
pid="${pid:-}"
|
||||
fi
|
||||
if [ -n "$pid" ] && [ "$pid" -gt 0 ] 2>/dev/null; then
|
||||
proc=$(ps -p "$pid" -o comm= 2>/dev/null | tr -d ' \n')
|
||||
[ -z "$proc" ] && proc="unknown"
|
||||
echo "${pid}|${proc}"
|
||||
return 0
|
||||
fi
|
||||
if [ -n "$line" ]; then
|
||||
# Port is occupied but process cannot be identified (kernel socket / no root)
|
||||
echo "0|unknown"
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
# match_known_conflict <comm> → печатает человекочитаемое имя если это
|
||||
# известный proxy/VPN/web софт. Возвращает 0 если нашли, 1 иначе.
|
||||
match_known_conflict() {
|
||||
local proc="$1"
|
||||
case "$proc" in
|
||||
*xray*|*Xray*) echo "Xray"; return 0 ;;
|
||||
*sing-box*|*sing_box*|*singbox*) echo "sing-box"; return 0 ;;
|
||||
*v2ray*|*V2Ray*) echo "V2Ray"; return 0 ;;
|
||||
*trojan*) echo "Trojan"; return 0 ;;
|
||||
*hysteria*) echo "Hysteria"; return 0 ;;
|
||||
*mtg*) echo "mtg (old MTProxy)"; return 0 ;;
|
||||
*ss-server*|*ss-local*|*shadowsocks*|*ssserver*) echo "Shadowsocks"; return 0 ;;
|
||||
*x-ui*|*3x-ui*|*xui*) echo "x-ui / 3x-ui panel"; return 0 ;;
|
||||
*marzban*) echo "Marzban panel"; return 0 ;;
|
||||
*amneziawg*|*awg-go*|*awg*) echo "AmneziaWG"; return 0 ;;
|
||||
*caddy*) echo "Caddy web server"; return 0 ;;
|
||||
*apache2*|*httpd*) echo "Apache httpd"; return 0 ;;
|
||||
*haproxy*) echo "HAProxy"; return 0 ;;
|
||||
*nginx*) echo "nginx (already running)"; return 0 ;;
|
||||
*tgproxy*|*mtproxy*|*mtproto*) echo "MTProto Proxy (other impl)"; return 0 ;;
|
||||
*wireguard*|*wg-quick*) echo "WireGuard"; return 0 ;;
|
||||
*openvpn*) echo "OpenVPN"; return 0 ;;
|
||||
esac
|
||||
return 1
|
||||
}
|
||||
|
||||
# preflight_check <mode> [port]
|
||||
# mode = "lite" | "pro"
|
||||
# port = selected port for lite mode (default 443)
|
||||
# Returns:
|
||||
# 0 — OK to proceed (no conflicts, or user confirmed to force)
|
||||
# 1 — user aborted (caller should show promo and return)
|
||||
preflight_check() {
|
||||
local mode="${1:-lite}"
|
||||
local lite_port="${2:-443}"
|
||||
|
||||
# Escape hatch
|
||||
if [ "${GOTELEGRAM_SKIP_PREFLIGHT:-0}" = "1" ]; then
|
||||
log_dim "preflight: skipped (GOTELEGRAM_SKIP_PREFLIGHT=1)"
|
||||
return 0
|
||||
fi
|
||||
|
||||
local required_ports=()
|
||||
if [ "$mode" = "pro" ]; then
|
||||
required_ports=(443 80 8443)
|
||||
else
|
||||
# lite: проверяем только выбранный внешний порт
|
||||
required_ports=("$lite_port")
|
||||
fi
|
||||
|
||||
local known_conflicts=() unknown_conflicts=() info port pid proc label
|
||||
for port in "${required_ports[@]}"; do
|
||||
info=$(get_port_process "$port")
|
||||
if [ -n "$info" ]; then
|
||||
pid="${info%%|*}"
|
||||
proc="${info##*|}"
|
||||
if label=$(match_known_conflict "$proc"); then
|
||||
known_conflicts+=("${port}|${label}|${pid}|${proc}")
|
||||
else
|
||||
unknown_conflicts+=("${port}|${pid}|${proc}")
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
if [ ${#known_conflicts[@]} -eq 0 ] && [ ${#unknown_conflicts[@]} -eq 0 ]; then
|
||||
log_dim "preflight: ports ${required_ports[*]} свободны"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Показываем баннер конфликта
|
||||
echo "" >&2
|
||||
echo -e " ${BOLD}${YELLOW}⚠ $(_t_or preflight_title 'Предустановочная проверка: обнаружены конфликты портов')${NC}" >&2
|
||||
echo -e " ${DIM}$(printf '─%.0s' {1..60})${NC}" >&2
|
||||
|
||||
local item p label2 pid2 proc2 rest
|
||||
if [ ${#known_conflicts[@]} -gt 0 ]; then
|
||||
echo -e " ${RED}$(_t_or preflight_known 'Известный proxy/VPN/веб-софт занимает нужные порты:')${NC}" >&2
|
||||
for item in "${known_conflicts[@]}"; do
|
||||
p="${item%%|*}"
|
||||
rest="${item#*|}"
|
||||
label2="${rest%%|*}"
|
||||
rest="${rest#*|}"
|
||||
pid2="${rest%%|*}"
|
||||
proc2="${rest##*|}"
|
||||
echo -e " ${RED}✗${NC} ${BOLD}:${p}${NC} → ${BOLD}${label2}${NC} ${DIM}(pid=${pid2}, cmd=${proc2})${NC}" >&2
|
||||
done
|
||||
fi
|
||||
if [ ${#unknown_conflicts[@]} -gt 0 ]; then
|
||||
echo -e " ${YELLOW}$(_t_or preflight_unknown 'Порты заняты неизвестными процессами:')${NC}" >&2
|
||||
for item in "${unknown_conflicts[@]}"; do
|
||||
p="${item%%|*}"
|
||||
rest="${item#*|}"
|
||||
pid2="${rest%%|*}"
|
||||
proc2="${rest##*|}"
|
||||
echo -e " ${YELLOW}⚠${NC} ${BOLD}:${p}${NC} ${DIM}(pid=${pid2}, cmd=${proc2})${NC}" >&2
|
||||
done
|
||||
fi
|
||||
|
||||
echo -e " ${DIM}$(printf '─%.0s' {1..60})${NC}" >&2
|
||||
echo -e " ${WHITE}$(_t_or preflight_needed 'GoTelegram нужны порты:')${NC} ${CYAN}${required_ports[*]}${NC}" >&2
|
||||
echo -e " ${WHITE}$(_t_or preflight_hint_header 'Рекомендации:')${NC}" >&2
|
||||
echo -e " ${DIM}• $(_t_or preflight_hint1 'Остановите и удалите конфликтующие сервисы (systemctl stop ...)')${NC}" >&2
|
||||
echo -e " ${DIM}• $(_t_or preflight_hint2 'Либо возьмите чистый VPS без других прокси')${NC}" >&2
|
||||
echo -e " ${DIM}• $(_t_or preflight_hint3 'Установка поверх, скорее всего, завершится некорректно')${NC}" >&2
|
||||
echo -e " ${DIM}$(_t_or preflight_skip_hint 'Override: GOTELEGRAM_SKIP_PREFLIGHT=1 gotelegram')${NC}" >&2
|
||||
echo "" >&2
|
||||
|
||||
if confirm "$(_t_or preflight_proceed 'Продолжить установку всё равно (скорее всего не заработает)?')"; then
|
||||
log_warning "$(_t_or preflight_forced 'Установка продолжена вопреки конфликтам — возможны ошибки')"
|
||||
return 0
|
||||
fi
|
||||
log_info "$(_t_or preflight_aborted 'Установка отменена из-за конфликтов портов')"
|
||||
return 1
|
||||
}
|
||||
|
||||
check_disk_space() {
|
||||
local min_mb="${1:-500}"
|
||||
local avail_mb
|
||||
|
||||
14
lib/lang/en.sh
Executable file → Normal file
14
lib/lang/en.sh
Executable file → Normal file
@@ -347,6 +347,20 @@ I18N[backup_pass_short]="Password too short (minimum 6 characters)"
|
||||
I18N[backup_pick_prompt]="Backup number (or path to file)"
|
||||
I18N[backup_not_found]="Backup not found"
|
||||
|
||||
# ── Preflight (v2.4.8) ──────────────────────────────────────────────────
|
||||
I18N[preflight_title]="Preflight: port conflicts detected"
|
||||
I18N[preflight_known]="Known proxy/VPN/web software is using required ports:"
|
||||
I18N[preflight_unknown]="Required ports are held by unknown processes:"
|
||||
I18N[preflight_needed]="GoTelegram requires ports:"
|
||||
I18N[preflight_hint_header]="Recommended actions:"
|
||||
I18N[preflight_hint1]="Stop and remove the conflicting services (systemctl stop ...)"
|
||||
I18N[preflight_hint2]="Or use a clean VPS without other proxies"
|
||||
I18N[preflight_hint3]="Installing on top will most likely fail"
|
||||
I18N[preflight_skip_hint]="Bypass: GOTELEGRAM_SKIP_PREFLIGHT=1 gotelegram"
|
||||
I18N[preflight_proceed]="Continue installation anyway (likely to fail)?"
|
||||
I18N[preflight_forced]="Installation continued despite conflicts — errors likely"
|
||||
I18N[preflight_aborted]="Installation aborted due to port conflicts"
|
||||
|
||||
# ── Errors / misc ───────────────────────────────────────────────────────
|
||||
I18N[err_need_root]="Run the script with sudo / as root"
|
||||
I18N[err_os_unknown]="Failed to detect OS. Linux is required."
|
||||
|
||||
14
lib/lang/ru.sh
Executable file → Normal file
14
lib/lang/ru.sh
Executable file → Normal file
@@ -347,6 +347,20 @@ I18N[backup_pass_short]="Пароль слишком короткий (мини
|
||||
I18N[backup_pick_prompt]="Номер бекапа (или путь к файлу)"
|
||||
I18N[backup_not_found]="Бекап не найден"
|
||||
|
||||
# ── Preflight (v2.4.8) ──────────────────────────────────────────────────
|
||||
I18N[preflight_title]="Предустановочная проверка: обнаружены конфликты портов"
|
||||
I18N[preflight_known]="Известный proxy/VPN/веб-софт занимает нужные порты:"
|
||||
I18N[preflight_unknown]="Порты заняты неизвестными процессами:"
|
||||
I18N[preflight_needed]="GoTelegram нужны порты:"
|
||||
I18N[preflight_hint_header]="Рекомендации:"
|
||||
I18N[preflight_hint1]="Остановите и удалите конфликтующие сервисы (systemctl stop ...)"
|
||||
I18N[preflight_hint2]="Либо возьмите чистый VPS без других прокси"
|
||||
I18N[preflight_hint3]="Установка поверх, скорее всего, завершится некорректно"
|
||||
I18N[preflight_skip_hint]="Обойти проверку: GOTELEGRAM_SKIP_PREFLIGHT=1 gotelegram"
|
||||
I18N[preflight_proceed]="Продолжить установку всё равно (скорее всего не заработает)?"
|
||||
I18N[preflight_forced]="Установка продолжена вопреки конфликтам — возможны ошибки"
|
||||
I18N[preflight_aborted]="Установка отменена из-за конфликтов портов"
|
||||
|
||||
# ── Errors / misc ───────────────────────────────────────────────────────
|
||||
I18N[err_need_root]="Запустите скрипт с sudo / от root"
|
||||
I18N[err_os_unknown]="Не удалось определить ОС. Требуется Linux."
|
||||
|
||||
Reference in New Issue
Block a user