fix: fix issue with open container log failed (#9163)

This commit is contained in:
CityFun 2025-06-18 15:14:56 +08:00 committed by GitHub
parent 754ac64bf6
commit 8b22acce27
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 97 additions and 109 deletions

View file

@ -880,116 +880,102 @@ func (u *ContainerService) ContainerLogClean(req dto.OperationWithName) error {
} }
func (u *ContainerService) StreamLogs(ctx *gin.Context, params dto.StreamLog) { func (u *ContainerService) StreamLogs(ctx *gin.Context, params dto.StreamLog) {
messageChan := make(chan string, 1024) messageChan := make(chan string, 1024)
errorChan := make(chan error, 1) errorChan := make(chan error, 1)
doneChan := make(chan struct{}) doneChan := make(chan struct{})
// 监听客户端连接状态 go func() {
go func() { <-ctx.Request.Context().Done()
<-ctx.Request.Context().Done() close(doneChan)
close(doneChan) // 通知 collectLogs 停止 }()
}() go collectLogs(doneChan, params, messageChan, errorChan)
// 启动日志收集协程 ctx.Stream(func(w io.Writer) bool {
go collectLogs(doneChan, params, messageChan, errorChan) select {
// 流式发送日志到客户端 case msg, ok := <-messageChan:
ctx.Stream(func(w io.Writer) bool { if !ok {
select { return false
case msg, ok := <-messageChan: }
if !ok { _, err := fmt.Fprintf(w, "data: %s\n\n", msg)
return false if err != nil {
} return false
_, err := fmt.Fprintf(w, "data: %s\n\n", msg) }
if err != nil { return true
return false case err := <-errorChan:
} if err != nil {
return true _, _ = fmt.Fprintf(w, "event: error\ndata: %v\n\n", err.Error())
case err := <-errorChan: }
if err != nil { return false
_, _ = fmt.Fprintf(w, "event: error\ndata: %v\n\n", err.Error()) }
} })
return false
}
})
} }
func collectLogs( func collectLogs(done <-chan struct{}, params dto.StreamLog, messageChan chan<- string, errorChan chan<- error) {
done <-chan struct{}, defer close(messageChan)
params dto.StreamLog, defer close(errorChan)
messageChan chan<- string, var cmdArgs []string
errorChan chan<- error, if params.Type == "compose" {
) { cmdArgs = []string{"compose", "-f", params.Compose}
defer close(messageChan) }
defer close(errorChan) cmdArgs = append(cmdArgs, "logs")
var cmdArgs []string if params.Follow {
if params.Type == "compose" { cmdArgs = append(cmdArgs, "-f")
cmdArgs = []string{"compose", "-f", params.Compose} }
} if params.Tail != "0" {
cmdArgs = append(cmdArgs, "logs") cmdArgs = append(cmdArgs, "--tail", params.Tail)
if params.Follow { }
cmdArgs = append(cmdArgs, "-f") if params.Since != "all" {
} cmdArgs = append(cmdArgs, "--since", params.Since)
if params.Tail != "0" { }
cmdArgs = append(cmdArgs, "--tail", params.Tail) if params.Container != "" {
} cmdArgs = append(cmdArgs, params.Container)
if params.Since != "all" { }
cmdArgs = append(cmdArgs, "--since", params.Since)
}
if params.Container != "" {
cmdArgs = append(cmdArgs, params.Container)
}
dockerCmd := exec.Command("docker", cmdArgs...) dockerCmd := exec.Command("docker", cmdArgs...)
stdout, err := dockerCmd.StdoutPipe() stdout, err := dockerCmd.StdoutPipe()
if err != nil { if err != nil {
errorChan <- fmt.Errorf("failed to get stdout pipe: %v", err) errorChan <- fmt.Errorf("failed to get stdout pipe: %v", err)
return return
} }
dockerCmd.Stderr = dockerCmd.Stdout dockerCmd.Stderr = dockerCmd.Stdout
if err = dockerCmd.Start(); err != nil { if err = dockerCmd.Start(); err != nil {
errorChan <- fmt.Errorf("failed to start docker logs command: %v", err) errorChan <- fmt.Errorf("failed to start docker logs command: %v", err)
return return
} }
// 确保在函数退出时清理进程 defer func() {
defer func() { if dockerCmd.Process != nil {
if dockerCmd.Process != nil { _ = dockerCmd.Process.Kill()
_ = dockerCmd.Process.Kill() }
} }()
}()
// 创建一个scanner来读取stdout scanner := bufio.NewScanner(stdout)
scanner := bufio.NewScanner(stdout)
// 启动一个goroutine监听done信号 processKilled := false
processKilled := false go func() {
go func() { <-done
<-done if !processKilled && dockerCmd.Process != nil {
if !processKilled && dockerCmd.Process != nil { processKilled = true
processKilled = true _ = dockerCmd.Process.Kill()
_ = dockerCmd.Process.Kill() }
} }()
}()
// 读取日志输出 for scanner.Scan() {
for scanner.Scan() { message := scanner.Text()
message := scanner.Text() select {
select { case messageChan <- message:
case messageChan <- message: case <-done:
// 消息发送成功 return
case <-done: }
return }
}
}
if err = scanner.Err(); err != nil && err != io.EOF { if err = scanner.Err(); err != nil && err != io.EOF {
errorChan <- fmt.Errorf("scanner error: %v", err) errorChan <- fmt.Errorf("scanner error: %v", err)
} }
// 等待命令完成 _ = dockerCmd.Wait()
_ = dockerCmd.Wait()
} }
func (u *ContainerService) DownloadContainerLogs(containerType, container, since, tail string, c *gin.Context) error { func (u *ContainerService) DownloadContainerLogs(containerType, container, since, tail string, c *gin.Context) error {

View file

@ -153,7 +153,9 @@ const searchLogs = async () => {
}; };
eventSource.onerror = (event: MessageEvent) => { eventSource.onerror = (event: MessageEvent) => {
stopListening(); stopListening();
MsgError(event.data); if (event.data && event.data != '') {
MsgError(event.data);
}
}; };
}; };