Files
NeoTachyon/uninstall.sh
T
Dushnilin 1c48422511 fix(luci): ensure Tachyon menu item reliably appears in LuCI
- Remove 'uci: { tachyon: true }' dependency from menu.d/luci-app-tachyon.json so LuCI does not hide the menu node if UCI config is uncommitted/reloading
- Add portable timeout normalization in install.sh ucode to handle Busybox timeout and systems without timeout applet
- Ensure luci_postinst is called directly in IPK postinst (build.sh) and after install in install.sh
- Restart uhttpd alongside rpcd and purge LuCI caches in post-install and uninstaller
- Fix uninstall.sh to remove packages individually with lock retry and omit non-existent luci-i18n-tachyon-en
- In install_ui_packages, verify that menu.d/luci-app-tachyon.json actually exists on disk before proceeding
2026-09-03 19:14:22 +03:00

333 lines
14 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/sh
# shellcheck shell=dash
# ==============================================================================
# Tachyon Uninstaller & Cleanup Script
# Полное чистое удаление Tachyon с сохранением резервной копии конфигурации.
# ==============================================================================
set -u
UNINSTALLER_VERSION="1.2.88"
# ─── TUI helpers & Color detection ───────────────────────────────────────────
ESC="$(printf '\033')"
_tui_colors=0
if [ -t 1 ] 2>/dev/null; then
case "${TERM:-dumb}" in
dumb) _tui_colors=0 ;;
*) _tui_colors=1 ;;
esac
fi
if [ "$_tui_colors" -eq 1 ]; then
_c_reset="${ESC}[0m"
_c_bold="${ESC}[1m"
_c_dim="${ESC}[2m"
_c_red="${ESC}[31;1m"
_c_green="${ESC}[32;1m"
_c_yellow="${ESC}[33;1m"
_c_blue="${ESC}[34;1m"
_c_cyan="${ESC}[36;1m"
_c_magenta="${ESC}[35;1m"
else
_c_reset=''
_c_bold=''
_c_dim=''
_c_red=''
_c_green=''
_c_yellow=''
_c_blue=''
_c_cyan=''
_c_magenta=''
fi
_tui_width() {
if [ -t 1 ] 2>/dev/null && command -v stty >/dev/null 2>&1; then
_w="$(stty size 2>/dev/null | awk '{print $2}')"
[ -n "$_w" ] && [ "$_w" -gt 0 ] 2>/dev/null && printf '%s' "$_w" && return 0
fi
printf '70'
}
_tui_hline() {
_w="$(_tui_width)"
_char="${1:--}"
_i=0
while [ "$_i" -lt "$_w" ]; do
printf '%s' "$_char"
_i=$((_i + 1))
done
}
tui_banner() {
printf '\n'
printf ' %s%s⚡ Tachyon Clean Uninstaller%s v%s\n' "$_c_cyan" "$_c_bold" "$_c_reset" "$UNINSTALLER_VERSION"
printf ' %sПолное удаление пакетов, сетевых правил и восстановление DNS%s\n' "$_c_dim" "$_c_reset"
printf ' %s%s%s\n\n' "$_c_dim" "$(_tui_hline '─')" "$_c_reset"
}
tui_step() {
_step_no="$1"
_step_total="$2"
_step_text="$3"
printf ' %s%s[ %s/%s ]%s %s%s%s\n' \
"$_c_blue" "$_c_bold" \
"$_step_no" "$_step_total" \
"$_c_reset" \
"$_c_bold" "$_step_text" "$_c_reset"
}
tui_ok() {
printf ' %s%s✓%s %s\n' "$_c_green" "$_c_bold" "$_c_reset" "$1"
}
tui_warn() {
printf ' %s%s⚠%s %s\n' "$_c_yellow" "$_c_bold" "$_c_reset" "$1"
}
tui_info() {
printf ' %s%sℹ%s %s\n' "$_c_cyan" "$_c_dim" "$_c_reset" "$1"
}
# ─── Options parsing ─────────────────────────────────────────────────────────
OPT_PURGE=0
OPT_YES=0
OPT_KEEP_BINARIES=0
for _arg in "$@"; do
case "$_arg" in
--purge|-p)
OPT_PURGE=1
;;
--yes|-y)
OPT_YES=1
;;
--keep-binaries)
OPT_KEEP_BINARIES=1
;;
--help|-h)
printf 'Использование: %s [ОПЦИИ]\n' "$0"
printf 'Опции:\n'
printf ' -y, --yes Выполнить удаление без подтверждения\n'
printf ' -p, --purge Полное удаление вместе с резервными копиями конфига\n'
printf ' --keep-binaries Не удалять бинарники sing-box / zapret / byedpi\n'
printf ' -h, --help Показать эту справку\n\n'
exit 0
;;
*)
;;
esac
done
# ─── Root check ──────────────────────────────────────────────────────────────
if [ "$(id -u)" -ne 0 ] 2>/dev/null; then
printf '%sОшибка: скрипт удаления должен запускаться с правами root!%s\n' "$_c_red" "$_c_reset" >&2
exit 1
fi
tui_banner
# ─── Confirmation prompt ─────────────────────────────────────────────────────
if [ "$OPT_YES" -eq 0 ] && [ -t 0 ] 2>/dev/null; then
printf ' Вы действительно хотите удалить %sTachyon%s с этого роутера?\n' "$_c_bold" "$_c_reset"
if [ "$OPT_PURGE" -eq 1 ]; then
printf ' %sВнимание: указан флаг --purge. Все конфигурации и бэкапы будут удалены!%s\n' "$_c_red" "$_c_reset"
else
printf ' Рабочая конфигурация будет сохранена в резервную копию.\n'
fi
printf ' Продолжить? [y/N]: '
read -r _answer
case "$_answer" in
y|Y|yes|Yes|YES|да|Да|ДА)
;;
*)
printf '\n %sУдаление отменено пользователем.%s\n\n' "$_c_yellow" "$_c_reset"
exit 0
;;
esac
printf '\n'
fi
TOTAL_STEPS=6
CURRENT_STEP=1
# ─── STEP 1: Backup Configuration ────────────────────────────────────────────
tui_step "$CURRENT_STEP" "$TOTAL_STEPS" "Создание резервной копии конфигурации..."
BACKUP_PATH=""
if [ "$OPT_PURGE" -eq 0 ]; then
TIMESTAMP="$(date +%Y%m%d_%H%M%S 2>/dev/null || date +%s)"
if [ -f "/etc/config/tachyon" ]; then
BACKUP_PATH="/etc/config/tachyon.backup-${TIMESTAMP}"
cp -af "/etc/config/tachyon" "$BACKUP_PATH" 2>/dev/null
cp -af "/etc/config/tachyon" "/etc/config/tachyon.bak" 2>/dev/null
chmod 600 "$BACKUP_PATH" "/etc/config/tachyon.bak" 2>/dev/null
tui_ok "Конфигурация успешно сохранена в: ${BACKUP_PATH}"
else
tui_info "Конфигурационный файл /etc/config/tachyon не найден, бэкап пропущен."
fi
else
tui_warn "Режим --purge: резервное копирование конфигурации отключено."
fi
CURRENT_STEP=$((CURRENT_STEP + 1))
# ─── STEP 2: Stop Services & Daemons ─────────────────────────────────────────
tui_step "$CURRENT_STEP" "$TOTAL_STEPS" "Остановка служб и фоновых процессов..."
if [ -f "/etc/init.d/tachyon" ]; then
/etc/init.d/tachyon stop >/dev/null 2>&1 || true
/etc/init.d/tachyon disable >/dev/null 2>&1 || true
tui_ok "Служба /etc/init.d/tachyon остановлена и отключена"
fi
# Terminate running DPI and proxy processes if any
killall sing-box >/dev/null 2>&1 || true
killall nfqws >/dev/null 2>&1 || true
killall nfqws2 >/dev/null 2>&1 || true
killall ciadpi >/dev/null 2>&1 || true
tui_ok "Фоновые процессы sing-box, zapret и byedpi завершены"
CURRENT_STEP=$((CURRENT_STEP + 1))
# ─── STEP 3: Clean up Network & nftables ─────────────────────────────────────
tui_step "$CURRENT_STEP" "$TOTAL_STEPS" "Очистка сетевых таблиц nftables и политик маршрутизации..."
# Remove nftables tables
if command -v nft >/dev/null 2>&1; then
nft delete table inet TachyonTable >/dev/null 2>&1 || true
nft delete table inet tachyon >/dev/null 2>&1 || true
nft delete table ip tachyon >/dev/null 2>&1 || true
nft delete table ip6 tachyon >/dev/null 2>&1 || true
rm -f /usr/share/nftables.d/chain-pre/input/10-tachyon.nft 2>/dev/null || true
tui_ok "Таблицы nftables (TachyonTable) успешно удалены"
fi
# Remove IP policy routing rules & flush table 100
if command -v ip >/dev/null 2>&1; then
ip rule del fwmark 0x10000000/0x10000000 lookup 100 >/dev/null 2>&1 || true
ip rule del fwmark 0x1/0x1 lookup 100 >/dev/null 2>&1 || true
ip rule del fwmark 0x2/0x2 lookup 100 >/dev/null 2>&1 || true
ip route flush table 100 >/dev/null 2>&1 || true
tui_ok "Политики маршрутизации (table 100, fwmark) сброшены"
fi
CURRENT_STEP=$((CURRENT_STEP + 1))
# ─── STEP 4: Restore DNS & dnsmasq ───────────────────────────────────────────
tui_step "$CURRENT_STEP" "$TOTAL_STEPS" "Восстановление конфигурации DNS и dnsmasq..."
rm -f /etc/dnsmasq.d/tachyon*.conf 2>/dev/null || true
rm -f /tmp/dnsmasq.d/tachyon*.conf 2>/dev/null || true
rm -rf /tmp/tachyon 2>/dev/null || true
# Restore dnsmasq backup if exists
if [ -f "/etc/config/dnsmasq.tachyon-bak" ]; then
cp -f "/etc/config/dnsmasq.tachyon-bak" "/etc/config/dnsmasq" 2>/dev/null
rm -f "/etc/config/dnsmasq.tachyon-bak" 2>/dev/null
tui_ok "Восстановлен исходный /etc/config/dnsmasq из бэкапа"
fi
# Restart dnsmasq to apply clean DNS configuration
if [ -f "/etc/init.d/dnsmasq" ]; then
/etc/init.d/dnsmasq restart >/dev/null 2>&1 || true
tui_ok "Служба dnsmasq перезапущена в штатном режиме"
fi
CURRENT_STEP=$((CURRENT_STEP + 1))
# ─── STEP 5: Remove Packages ─────────────────────────────────────────────────
tui_step "$CURRENT_STEP" "$TOTAL_STEPS" "Удаление установленных пакетов Tachyon..."
if command -v apk >/dev/null 2>&1 && [ -d "/lib/apk/db" ]; then
for _pkg in luci-i18n-tachyon-ru luci-app-tachyon tachyon; do
if apk info -e "$_pkg" >/dev/null 2>&1; then
apk del "$_pkg" >/dev/null 2>&1 || true
fi
done
tui_ok "Пакеты удалены через apk-tools"
elif command -v opkg >/dev/null 2>&1; then
_wait=0
while [ -f /var/lock/opkg.lock ] || [ -f /var/run/opkg.lock ]; do
_wait=$((_wait + 1))
[ "$_wait" -ge 10 ] && break
sleep 1
done
for _pkg in luci-i18n-tachyon-ru luci-app-tachyon tachyon; do
if opkg list-installed "$_pkg" 2>/dev/null | grep -q "^$_pkg "; then
opkg remove --force-depends --force-remove "$_pkg" >/dev/null 2>&1 || true
fi
done
tui_ok "Пакеты удалены через opkg"
fi
CURRENT_STEP=$((CURRENT_STEP + 1))
# ─── STEP 6: Remove Leftover Files & LuCI Cache ──────────────────────────────
tui_step "$CURRENT_STEP" "$TOTAL_STEPS" "Очистка оставшихся файлов и кэша LuCI..."
rm -rf /usr/lib/tachyon 2>/dev/null || true
rm -rf /usr/share/tachyon 2>/dev/null || true
rm -rf /www/luci-static/resources/view/tachyon 2>/dev/null || true
rm -f /usr/share/luci/menu.d/luci-app-tachyon.json 2>/dev/null || true
rm -f /usr/share/rpcd/acl.d/luci-app-tachyon.json 2>/dev/null || true
rm -f /etc/uci-defaults/50_luci-tachyon 2>/dev/null || true
rm -f /etc/tachyon_commit 2>/dev/null || true
rm -f /usr/bin/tachyon 2>/dev/null || true
rm -f /etc/init.d/tachyon 2>/dev/null || true
# Optional binary removal
if [ "$OPT_KEEP_BINARIES" -eq 0 ]; then
# Only remove binaries if they were placed for tachyon
rm -f /usr/lib/libcronet.so 2>/dev/null || true
fi
# Clean translations
rm -f /usr/lib/lua/luci/i18n/tachyon.* 2>/dev/null || true
find /usr/lib/lua/luci/i18n/ -name "tachyon.*" -delete 2>/dev/null || true
# Clear LuCI index and module caches
rm -f /var/luci-indexcache* /tmp/luci-indexcache* /tmp/luci-modulecache/* 2>/dev/null || true
# Purge configs if requested
if [ "$OPT_PURGE" -eq 1 ]; then
rm -f /etc/config/tachyon* 2>/dev/null || true
rm -rf /etc/tachyon 2>/dev/null || true
tui_ok "Все конфигурации Tachyon удалены (--purge)"
fi
# Restart rpcd and uhttpd to update LuCI menu
if [ -f "/etc/init.d/rpcd" ]; then
/etc/init.d/rpcd restart >/dev/null 2>&1 || true
fi
if [ -f "/etc/init.d/uhttpd" ]; then
/etc/init.d/uhttpd restart >/dev/null 2>&1 || true
fi
# Check if parent Forkop / Podkop services exist and restore them
if [ -f "/etc/init.d/forkop" ]; then
/etc/init.d/forkop enable >/dev/null 2>&1 || true
/etc/init.d/forkop restart >/dev/null 2>&1 || true
tui_ok "Обнаружен родительский сервис Forkop — восстановлен и запущен"
elif [ -f "/etc/init.d/podkop" ]; then
/etc/init.d/podkop enable >/dev/null 2>&1 || true
/etc/init.d/podkop restart >/dev/null 2>&1 || true
tui_ok "Обнаружен родительский сервис Podkop — восстановлен и запущен"
fi
tui_ok "Кэш LuCI очищен, файлы удалены"
# ─── Final Summary ───────────────────────────────────────────────────────────
printf '\n'
printf ' %s%s%s\n' "$_c_dim" "$(_tui_hline '─')" "$_c_reset"
printf ' %s%s✓ Tachyon успешно и чисто удален с вашего роутера!%s\n' "$_c_green" "$_c_bold" "$_c_reset"
if [ "$OPT_PURGE" -eq 0 ] && [ -n "$BACKUP_PATH" ]; then
printf ' %s📁 Резервная копия конфигурации сохранена:%s %s%s%s\n' "$_c_cyan" "$_c_reset" "$_c_bold" "$BACKUP_PATH" "$_c_reset"
printf ' %s (а также продублирована в /etc/config/tachyon.bak)%s\n' "$_c_dim" "$_c_reset"
fi
printf ' %s🌐 Сетевой стек и DNS возвращены в штатный режим OpenWrt.%s\n\n' "$_c_dim" "$_c_reset"
exit 0