@@ -2,7 +2,10 @@ package nginx
22
33import (
44 "os"
5+ "strconv"
6+ "strings"
57 "sync"
8+ "syscall"
69 "time"
710
811 "github.com/0xJacky/Nginx-UI/internal/docker"
@@ -33,20 +36,18 @@ func Reload() (stdOut string, stdErr error) {
3336 // Clear the modules cache when reloading Nginx
3437 clearModulesCache ()
3538
39+ if ! IsRunning () {
40+ restart ()
41+ return
42+ }
43+
3644 if settings .NginxSettings .ReloadCmd != "" {
3745 return execShell (settings .NginxSettings .ReloadCmd )
3846 }
3947 return execCommand ("nginx" , "-s" , "reload" )
4048}
4149
42- // Restart restarts the nginx
43- func Restart () {
44- mutex .Lock ()
45- defer mutex .Unlock ()
46-
47- // Clear the modules cache when restarting Nginx
48- clearModulesCache ()
49-
50+ func restart () {
5051 // fix(docker): nginx restart always output network error
5152 time .Sleep (500 * time .Millisecond )
5253
@@ -58,9 +59,12 @@ func Restart() {
5859 pidPath := GetPIDPath ()
5960 daemon := GetSbinPath ()
6061
61- lastStdOut , lastStdErr = execCommand ("start-stop-daemon" , "--stop" , "--quiet" , "--oknodo" , "--retry=TERM/30/KILL/5" , "--pidfile" , pidPath )
62- if lastStdErr != nil {
63- return
62+ // Check if nginx is running before attempting to stop it
63+ if IsRunning () {
64+ lastStdOut , lastStdErr = execCommand ("start-stop-daemon" , "--stop" , "--quiet" , "--oknodo" , "--retry=TERM/30/KILL/5" , "--pidfile" , pidPath )
65+ if lastStdErr != nil {
66+ return
67+ }
6468 }
6569
6670 if daemon == "" {
@@ -71,6 +75,17 @@ func Restart() {
7175 lastStdOut , lastStdErr = execCommand ("start-stop-daemon" , "--start" , "--quiet" , "--pidfile" , pidPath , "--exec" , daemon )
7276}
7377
78+ // Restart restarts the nginx
79+ func Restart () {
80+ mutex .Lock ()
81+ defer mutex .Unlock ()
82+
83+ // Clear the modules cache when restarting Nginx
84+ clearModulesCache ()
85+
86+ restart ()
87+ }
88+
7489// GetLastOutput returns the last output of the nginx command
7590func GetLastResult () * ControlResult {
7691 mutex .Lock ()
@@ -87,9 +102,42 @@ func IsRunning() bool {
87102 case true :
88103 return docker .StatPath (pidPath )
89104 case false :
90- if fileInfo , err := os .Stat (pidPath ); err != nil || fileInfo .Size () == 0 {
91- return false
92- }
105+ return isProcessRunning (pidPath )
106+ }
107+ return false
108+ }
109+
110+ // isProcessRunning checks if the process with the PID from pidPath is actually running
111+ func isProcessRunning (pidPath string ) bool {
112+ // Check if PID file exists
113+ if fileInfo , err := os .Stat (pidPath ); err != nil || fileInfo .Size () == 0 {
114+ return false
115+ }
116+
117+ // Read PID from file
118+ pidBytes , err := os .ReadFile (pidPath )
119+ if err != nil {
120+ return false
121+ }
122+
123+ pidStr := strings .TrimSpace (string (pidBytes ))
124+ pid , err := strconv .Atoi (pidStr )
125+ if err != nil {
126+ return false
127+ }
128+
129+ // Cross-platform process existence check
130+ process , err := os .FindProcess (pid )
131+ if err != nil {
132+ return false
133+ }
134+
135+ // On Unix systems, FindProcess always succeeds and returns a Process for the given pid,
136+ // regardless of whether the process exists. To test whether the process actually exists,
137+ // see whether p.Signal(syscall.Signal(0)) reports an error.
138+ err = process .Signal (syscall .Signal (0 ))
139+ if err == nil {
140+ // Process exists and we can signal it
93141 return true
94142 }
95143 return false
0 commit comments