Skip to content

Commit 4f0a51a

Browse files
committed
fix: improve nginx control logic and enhance error handling
1 parent 55d5476 commit 4f0a51a

File tree

3 files changed

+73
-19
lines changed

3 files changed

+73
-19
lines changed

api/nginx/control.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,11 @@ func Reload(c *gin.Context) {
1414

1515
// TestConfig tests the nginx config
1616
func TestConfig(c *gin.Context) {
17-
nginx.Control(nginx.TestConfig).Resp(c)
17+
lastResult := nginx.Control(nginx.TestConfig)
18+
c.JSON(http.StatusOK, gin.H{
19+
"message": lastResult.GetOutput(),
20+
"level": lastResult.GetLevel(),
21+
})
1822
}
1923

2024
// Restart restarts the nginx
@@ -28,10 +32,6 @@ func Restart(c *gin.Context) {
2832
// Status returns the status of the nginx
2933
func Status(c *gin.Context) {
3034
lastResult := nginx.GetLastResult()
31-
if lastResult.IsError() {
32-
lastResult.RespError(c)
33-
return
34-
}
3535

3636
running := nginx.IsRunning()
3737

app/src/views/config/InspectConfig.vue

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ defineExpose({
3636
<AAlert
3737
v-else-if="data?.level === logLevel.Warn"
3838
:message="$gettext('Warning')"
39+
:banner
3940
type="warning"
4041
show-icon
4142
>
@@ -47,6 +48,7 @@ defineExpose({
4748
<AAlert
4849
v-else-if="data?.level > logLevel.Warn"
4950
:message="$gettext('Error')"
51+
:banner
5052
type="error"
5153
show-icon
5254
>
@@ -65,4 +67,8 @@ defineExpose({
6567
:deep(.ant-alert-description) {
6668
white-space: pre-line;
6769
}
70+
71+
:deep(.ant-alert-banner) {
72+
padding: 8px 24px;
73+
}
6874
</style>

internal/nginx/nginx.go

Lines changed: 62 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ package nginx
22

33
import (
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
7590
func 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

Comments
 (0)