feat: suppress systemctl inotify noise, cache service state in menu loop

This commit is contained in:
2026-06-15 16:25:03 +03:00
parent 0553ef7493
commit 6c12082a54

48
main.sh
View File

@@ -82,6 +82,19 @@ run_elevated() {
"$ELEVATE_CMD" "$@" "$ELEVATE_CMD" "$@"
} }
# systemctl on some systems logs "Failed to add a watch ... inotify watch limit reached"
# to stderr when it talks to PID 1. The operation itself succeeds; suppress the
# noisy line so it does not pollute the TUI.
run_systemctl() {
local line rc
while IFS= read -r line; do
[[ "$line" == *"Failed to add a watch"*"inotify watch limit reached"* ]] && continue
printf '%s\n' "$line"
done < <(systemctl "$@" 2>&1) || true
rc=${PIPESTATUS[0]}
return "$rc"
}
check_deps() { check_deps() {
local missing=() cmd local missing=() cmd
for cmd in bash curl jq systemctl date stat mktemp sha256sum cmp install dirname basename cut mkdir chmod cp cat printf; do for cmd in bash curl jq systemctl date stat mktemp sha256sum cmp install dirname basename cut mkdir chmod cp cat printf; do
@@ -203,7 +216,7 @@ normalize_service_name() {
validate_service() { validate_service() {
local svc="$1" local svc="$1"
systemctl --no-ask-password cat "$svc" >/dev/null 2>&1 run_systemctl --no-ask-password cat "$svc" >/dev/null 2>&1
} }
ensure_target_parent() { ensure_target_parent() {
@@ -422,13 +435,13 @@ install_xray_config() {
restart_xray_service() { restart_xray_service() {
local service="$1" local service="$1"
info "Перезапускаю ${service}" info "Перезапускаю ${service}"
if systemctl --no-ask-password restart "$service" 2>/dev/null; then if run_systemctl --no-ask-password restart "$service" 2>/dev/null; then
ok "Служба ${service} перезапущена." ok "Служба ${service} перезапущена."
return 0 return 0
fi fi
elevate_available || die "Не удалось перезапустить ${service}: нет прав и не найден doas/run0/pkexec/sudo." elevate_available || die "Не удалось перезапустить ${service}: нет прав и не найден doas/run0/pkexec/sudo."
run_elevated systemctl --no-ask-password restart "$service" run_elevated run_systemctl --no-ask-password restart "$service"
ok "Служба ${service} перезапущена." ok "Служба ${service} перезапущена."
} }
@@ -540,12 +553,12 @@ xray_socks_endpoint() {
service_state_raw() { service_state_raw() {
local service="$1" local service="$1"
systemctl --no-ask-password is-active "$service" 2>/dev/null || true run_systemctl --no-ask-password is-active "$service" 2>/dev/null || true
} }
service_enabled_raw() { service_enabled_raw() {
local service="$1" local service="$1"
systemctl --no-ask-password is-enabled "$service" 2>/dev/null || true run_systemctl --no-ask-password is-enabled "$service" 2>/dev/null || true
} }
service_state_colored() { service_state_colored() {
@@ -582,7 +595,7 @@ run_service_action() {
say "" say ""
info "systemctl ${action} ${service}" info "systemctl ${action} ${service}"
if systemctl --no-ask-password "$action" "$service" 2>/dev/null; then if run_systemctl --no-ask-password "$action" "$service" 2>/dev/null; then
ok "Готово: ${service}${action}." ok "Готово: ${service}${action}."
pause_screen pause_screen
hide_cursor hide_cursor
@@ -596,7 +609,7 @@ run_service_action() {
return 1 return 1
} }
if run_elevated systemctl --no-ask-password "$action" "$service"; then if run_elevated run_systemctl --no-ask-password "$action" "$service"; then
ok "Готово: ${service}${action}." ok "Готово: ${service}${action}."
else else
warn "systemctl ${action} завершился с ошибкой. Проверьте статус службы." warn "systemctl ${action} завершился с ошибкой. Проверьте статус службы."
@@ -612,7 +625,7 @@ show_service_status_screen() {
clear_screen clear_screen
say "${C_BOLD}${C_MAGENTA}✦ Статус службы ${service}${C_RESET}" say "${C_BOLD}${C_MAGENTA}✦ Статус службы ${service}${C_RESET}"
say "" say ""
if ! systemctl --no-ask-password --no-pager --full status "$service" -n 18; then if ! run_systemctl --no-ask-password --no-pager --full status "$service" -n 18; then
warn "Не удалось прочитать статус через systemctl." warn "Не удалось прочитать статус через systemctl."
fi fi
pause_screen pause_screen
@@ -663,6 +676,7 @@ render_profile_row() {
render_menu() { render_menu() {
local cursor="$1" count saved_index i cache_info selected_name local cursor="$1" count saved_index i cache_info selected_name
local service service_state service_enabled xray_config socks_endpoint local service service_state service_enabled xray_config socks_endpoint
local now
count="$(profile_count)" count="$(profile_count)"
saved_index="$(cfg_get selected_index)" saved_index="$(cfg_get selected_index)"
@@ -671,8 +685,17 @@ render_menu() {
xray_config="$(cfg_get xray_config)" xray_config="$(cfg_get xray_config)"
socks_endpoint="$(xray_socks_endpoint "$xray_config")" socks_endpoint="$(xray_socks_endpoint "$xray_config")"
cache_info="$(subscription_update_info)" cache_info="$(subscription_update_info)"
service_state="$(service_state_raw "$service")"
service_enabled="$(service_enabled_raw "$service")" # Polling systemd on every keypress can exhaust inotify watches quickly.
# Cache the state for a short interval inside the menu loop.
now="$(date +%s)"
if [[ -z "${_MENU_STATE_CACHE_TS:-}" || $(( now - _MENU_STATE_CACHE_TS )) -gt 2 ]]; then
_MENU_STATE_CACHE_TS="$now"
_MENU_STATE_CACHE_VALUE="$(service_state_raw "$service")"
_MENU_ENABLED_CACHE_VALUE="$(service_enabled_raw "$service")"
fi
service_state="${_MENU_STATE_CACHE_VALUE}"
service_enabled="${_MENU_ENABLED_CACHE_VALUE}"
clear_screen clear_screen
say "${C_BOLD}${C_MAGENTA}✦ Xray JSON TUI${C_RESET}" say "${C_BOLD}${C_MAGENTA}✦ Xray JSON TUI${C_RESET}"
@@ -751,15 +774,19 @@ menu() {
;; ;;
s|S) s|S)
run_service_action start "$service" run_service_action start "$service"
unset _MENU_STATE_CACHE_TS _MENU_STATE_CACHE_VALUE _MENU_ENABLED_CACHE_VALUE
;; ;;
o|O) o|O)
run_service_action stop "$service" run_service_action stop "$service"
unset _MENU_STATE_CACHE_TS _MENU_STATE_CACHE_VALUE _MENU_ENABLED_CACHE_VALUE
;; ;;
e|E) e|E)
run_service_action restart "$service" run_service_action restart "$service"
unset _MENU_STATE_CACHE_TS _MENU_STATE_CACHE_VALUE _MENU_ENABLED_CACHE_VALUE
;; ;;
v|V) v|V)
show_service_status_screen "$service" show_service_status_screen "$service"
unset _MENU_STATE_CACHE_TS _MENU_STATE_CACHE_VALUE _MENU_ENABLED_CACHE_VALUE
;; ;;
q|Q) q|Q)
clear_screen clear_screen
@@ -770,6 +797,7 @@ menu() {
show_cursor show_cursor
say "" say ""
apply_selection "$cursor" apply_selection "$cursor"
unset _MENU_STATE_CACHE_TS _MENU_STATE_CACHE_VALUE _MENU_ENABLED_CACHE_VALUE
pause_screen pause_screen
hide_cursor hide_cursor
;; ;;