diff --git a/main.go b/main.go index 8096616c..f8d3357b 100644 --- a/main.go +++ b/main.go @@ -16,6 +16,7 @@ import ( "github.com/mhsanaei/3x-ui/v2/logger" "github.com/mhsanaei/3x-ui/v2/sub" "github.com/mhsanaei/3x-ui/v2/util/crypto" + "github.com/mhsanaei/3x-ui/v2/util/sys" "github.com/mhsanaei/3x-ui/v2/web" "github.com/mhsanaei/3x-ui/v2/web/global" "github.com/mhsanaei/3x-ui/v2/web/service" @@ -70,7 +71,7 @@ func runWebServer() { sigCh := make(chan os.Signal, 1) // Trap shutdown signals - signal.Notify(sigCh, syscall.SIGHUP, syscall.SIGTERM) + signal.Notify(sigCh, syscall.SIGHUP, syscall.SIGTERM, sys.SIGUSR1) for { sig := <-sigCh @@ -108,6 +109,12 @@ func runWebServer() { return } log.Println("Sub server restarted successfully.") + case sys.SIGUSR1: + logger.Info("Received USR1 signal, restarting xray-core...") + err := server.RestartXray() + if err != nil { + logger.Error("Failed to restart xray-core:", err) + } default: // --- FIX FOR TELEGRAM BOT CONFLICT (409) on full shutdown --- diff --git a/util/sys/sys_darwin.go b/util/sys/sys_darwin.go index b635b549..b44d7689 100644 --- a/util/sys/sys_darwin.go +++ b/util/sys/sys_darwin.go @@ -7,11 +7,14 @@ import ( "encoding/binary" "fmt" "sync" + "syscall" "github.com/shirou/gopsutil/v4/net" "golang.org/x/sys/unix" ) +var SIGUSR1 = syscall.SIGUSR1 + func GetTCPCount() (int, error) { stats, err := net.Connections("tcp") if err != nil { diff --git a/util/sys/sys_linux.go b/util/sys/sys_linux.go index 23483b57..5b1b1127 100644 --- a/util/sys/sys_linux.go +++ b/util/sys/sys_linux.go @@ -12,8 +12,11 @@ import ( "strconv" "strings" "sync" + "syscall" ) +var SIGUSR1 = syscall.SIGUSR1 + func getLinesNum(filename string) (int, error) { file, err := os.Open(filename) if err != nil { diff --git a/util/sys/sys_windows.go b/util/sys/sys_windows.go index 186fa4bb..9b6d659f 100644 --- a/util/sys/sys_windows.go +++ b/util/sys/sys_windows.go @@ -12,6 +12,8 @@ import ( "github.com/shirou/gopsutil/v4/net" ) +var SIGUSR1 = syscall.Signal(0) + // GetConnectionCount returns the number of active connections for the specified protocol ("tcp" or "udp"). func GetConnectionCount(proto string) (int, error) { if proto != "tcp" && proto != "udp" { diff --git a/web/web.go b/web/web.go index 300572a3..71845a14 100644 --- a/web/web.go +++ b/web/web.go @@ -490,3 +490,7 @@ func (s *Server) GetCron() *cron.Cron { func (s *Server) GetWSHub() any { return s.wsHub } + +func (s *Server) RestartXray() error { + return s.xrayService.RestartXray(true) +} diff --git a/x-ui.rc b/x-ui.rc index 1323d76a..cfb54211 100644 --- a/x-ui.rc +++ b/x-ui.rc @@ -10,4 +10,9 @@ depend() { } start_pre(){ cd /usr/local/x-ui +} +reload() { + ebegin "Reloading ${RC_SVCNAME}" + kill -USR1 $pidfile + eend $? } \ No newline at end of file diff --git a/x-ui.service.arch b/x-ui.service.arch index b6e01141..9060fbf6 100644 --- a/x-ui.service.arch +++ b/x-ui.service.arch @@ -9,6 +9,7 @@ Environment="XRAY_VMESS_AEAD_FORCED=false" Type=simple WorkingDirectory=/usr/lib/x-ui/ ExecStart=/usr/lib/x-ui/x-ui +ExecReload=kill -USR1 $MAINPID Restart=on-failure RestartSec=5s diff --git a/x-ui.service.debian b/x-ui.service.debian index 037f88bb..4902c5fe 100644 --- a/x-ui.service.debian +++ b/x-ui.service.debian @@ -9,6 +9,7 @@ Environment="XRAY_VMESS_AEAD_FORCED=false" Type=simple WorkingDirectory=/usr/local/x-ui/ ExecStart=/usr/local/x-ui/x-ui +ExecReload=kill -USR1 $MAINPID Restart=on-failure RestartSec=5s diff --git a/x-ui.service.rhel b/x-ui.service.rhel index 30652d52..696a9c12 100644 --- a/x-ui.service.rhel +++ b/x-ui.service.rhel @@ -9,6 +9,7 @@ Environment="XRAY_VMESS_AEAD_FORCED=false" Type=simple WorkingDirectory=/usr/local/x-ui/ ExecStart=/usr/local/x-ui/x-ui +ExecReload=kill -USR1 $MAINPID Restart=on-failure RestartSec=5s diff --git a/x-ui.sh b/x-ui.sh index 0f625b5f..2f7f63cd 100644 --- a/x-ui.sh +++ b/x-ui.sh @@ -408,6 +408,16 @@ restart() { fi } +restart_xray() { + systemctl reload x-ui + LOGI "xray-core Restart signal sent successfully, Please check the log information to confirm whether xray restarted successfully" + sleep 2 + show_xray_status + if [[ $# == 0 ]]; then + before_show_menu + fi +} + status() { if [[ $release == "alpine" ]]; then rc-service x-ui status @@ -2270,6 +2280,7 @@ show_usage() { │ ${blue}x-ui start${plain} - Start │ │ ${blue}x-ui stop${plain} - Stop │ │ ${blue}x-ui restart${plain} - Restart │ +| ${blue}x-ui restart-xray${plain} - Restart Xray │ │ ${blue}x-ui status${plain} - Current Status │ │ ${blue}x-ui settings${plain} - Current Settings │ │ ${blue}x-ui enable${plain} - Enable Autostart on OS Startup │ @@ -2305,11 +2316,12 @@ show_menu() { │ ${green}11.${plain} Start │ │ ${green}12.${plain} Stop │ │ ${green}13.${plain} Restart │ -│ ${green}14.${plain} Check Status │ -│ ${green}15.${plain} Logs Management │ +| ${green}14.${plain} Restart Xray │ +│ ${green}15.${plain} Check Status │ +│ ${green}16.${plain} Logs Management │ │────────────────────────────────────────────────│ -│ ${green}16.${plain} Enable Autostart │ -│ ${green}17.${plain} Disable Autostart │ +│ ${green}17.${plain} Enable Autostart │ +│ ${green}18.${plain} Disable Autostart │ │────────────────────────────────────────────────│ │ ${green}18.${plain} SSL Certificate Management │ │ ${green}19.${plain} Cloudflare SSL Certificate │ @@ -2372,31 +2384,31 @@ show_menu() { check_install && restart ;; 14) - check_install && status + check_install && restart_xray ;; 15) - check_install && show_log + check_install && status ;; 16) - check_install && enable + check_install && show_log ;; 17) - check_install && disable + check_install && enable ;; 18) - ssl_cert_issue_main + check_install && disable ;; 19) - ssl_cert_issue_CF + ssl_cert_issue_main ;; 20) - iplimit_main + ssl_cert_issue_CF ;; 21) - firewall_menu + iplimit_main ;; 22) - SSH_port_forwarding + firewall_menu ;; 23) create_honeypot @@ -2433,6 +2445,9 @@ if [[ $# > 0 ]]; then "restart") check_install 0 && restart 0 ;; + "restart-xray") + check_install 0 && restart_xray 0 + ;; "status") check_install 0 && status 0 ;;