@@ -2,7 +2,10 @@ package nginx
2
2
3
3
import (
4
4
"os"
5
+ "strconv"
6
+ "strings"
5
7
"sync"
8
+ "syscall"
6
9
"time"
7
10
8
11
"github.com/0xJacky/Nginx-UI/internal/docker"
@@ -33,20 +36,18 @@ func Reload() (stdOut string, stdErr error) {
33
36
// Clear the modules cache when reloading Nginx
34
37
clearModulesCache ()
35
38
39
+ if ! IsRunning () {
40
+ restart ()
41
+ return
42
+ }
43
+
36
44
if settings .NginxSettings .ReloadCmd != "" {
37
45
return execShell (settings .NginxSettings .ReloadCmd )
38
46
}
39
47
return execCommand ("nginx" , "-s" , "reload" )
40
48
}
41
49
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 () {
50
51
// fix(docker): nginx restart always output network error
51
52
time .Sleep (500 * time .Millisecond )
52
53
@@ -58,9 +59,12 @@ func Restart() {
58
59
pidPath := GetPIDPath ()
59
60
daemon := GetSbinPath ()
60
61
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
+ }
64
68
}
65
69
66
70
if daemon == "" {
@@ -71,6 +75,17 @@ func Restart() {
71
75
lastStdOut , lastStdErr = execCommand ("start-stop-daemon" , "--start" , "--quiet" , "--pidfile" , pidPath , "--exec" , daemon )
72
76
}
73
77
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
+
74
89
// GetLastOutput returns the last output of the nginx command
75
90
func GetLastResult () * ControlResult {
76
91
mutex .Lock ()
@@ -87,9 +102,42 @@ func IsRunning() bool {
87
102
case true :
88
103
return docker .StatPath (pidPath )
89
104
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
93
141
return true
94
142
}
95
143
return false
0 commit comments