From 0bf6db1cf80c2dd0f67a0e0b131f668e8caf229d Mon Sep 17 00:00:00 2001 From: ssongliu <73214554+ssongliu@users.noreply.github.com> Date: Wed, 10 Apr 2024 22:18:08 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E8=A7=A3=E5=86=B3=E5=83=B5=E5=B0=B8?= =?UTF-8?q?=E8=BF=9B=E7=A8=8B=E7=9A=84=E9=97=AE=E9=A2=98=20(#4464)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/app/api/v1/terminal.go | 18 ++-- backend/app/service/container.go | 84 ++++++++++--------- .../views/container/container/log/index.vue | 1 + 3 files changed, 55 insertions(+), 48 deletions(-) diff --git a/backend/app/api/v1/terminal.go b/backend/app/api/v1/terminal.go index 568c4871f..eefad26a2 100644 --- a/backend/app/api/v1/terminal.go +++ b/backend/app/api/v1/terminal.go @@ -102,7 +102,7 @@ func (b *BaseApi) RedisWsSsh(c *gin.Context) { if wshandleError(wsConn, err) { return } - defer killBash(redisConf.ContainerName, commands, pidMap) + defer killBash(redisConf.ContainerName, pidMap) defer slave.Close() tty, err := terminal.NewLocalWsSession(cols, rows, wsConn, slave, false) @@ -170,7 +170,7 @@ func (b *BaseApi) ContainerWsSsh(c *gin.Context) { if wshandleError(wsConn, err) { return } - defer killBash(containerID, command, pidMap) + defer killBash(containerID, pidMap) defer slave.Close() tty, err := terminal.NewLocalWsSession(cols, rows, wsConn, slave, true) @@ -221,26 +221,26 @@ func loadMapFromDockerTop(containerID string) map[string]string { lines := strings.Split(stdout, "\n") for _, line := range lines { parts := strings.Fields(line) - if len(parts) != 2 { + if len(parts) == 0 { continue } - pidMap[parts[0]] = parts[1] + pidMap[parts[0]] = strings.Join(parts, " ") } return pidMap } -func killBash(containerID, comm string, pidMap map[string]string) { +func killBash(containerID string, pidMap map[string]string) { sudo := cmd.SudoHandleCmd() newPidMap := loadMapFromDockerTop(containerID) - for pid, command := range newPidMap { + for pid, newCmd := range newPidMap { isOld := false - for pid2 := range pidMap { - if pid == pid2 { + for pid2, oldCmd := range pidMap { + if pid == pid2 && oldCmd == newCmd { isOld = true break } } - if !isOld && command == comm { + if !isOld { _, _ = cmd.Execf("%s kill -9 %s", sudo, pid) } } diff --git a/backend/app/service/container.go b/backend/app/service/container.go index 330968e22..3dfbc6718 100644 --- a/backend/app/service/container.go +++ b/backend/app/service/container.go @@ -626,22 +626,26 @@ func (u *ContainerService) ContainerLogs(wsConn *websocket.Conn, containerType, if cmd.CheckIllegal(container, since, tail) { return buserr.New(constant.ErrCmdIllegal) } - command := fmt.Sprintf("docker logs %s", container) + commandName := "docker" + commandArg := []string{"logs", container} if containerType == "compose" { - command = fmt.Sprintf("docker-compose -f %s logs", container) + commandName = "docker-compose" + commandArg = []string{"-f", container, "logs"} } if tail != "0" { - command += " --tail " + tail + commandArg = append(commandArg, "--tail") + commandArg = append(commandArg, tail) } if since != "all" { - command += " --since " + since + commandArg = append(commandArg, "--since") + commandArg = append(commandArg, since) } if follow { - command += " -f" + commandArg = append(commandArg, "-f") } - command += " 2>&1" - cmd := exec.Command("bash", "-c", command) if !follow { + commandArg = append(commandArg, "2>&1") + cmd := exec.Command(commandName, commandArg...) stdout, _ := cmd.CombinedOutput() if !utf8.Valid(stdout) { return errors.New("invalid utf8") @@ -652,50 +656,52 @@ func (u *ContainerService) ContainerLogs(wsConn *websocket.Conn, containerType, return nil } + cmd := exec.Command(commandName, commandArg...) stdout, err := cmd.StdoutPipe() if err != nil { + _ = cmd.Process.Signal(syscall.SIGTERM) return err } if err := cmd.Start(); err != nil { + _ = cmd.Process.Signal(syscall.SIGTERM) return err } - defer func() { - _ = cmd.Process.Signal(syscall.SIGTERM) - _ = cmd.Wait() + exitCh := make(chan struct{}) + go func() { + _, wsData, _ := wsConn.ReadMessage() + if string(wsData) == "close conn" { + _ = cmd.Process.Signal(syscall.SIGTERM) + exitCh <- struct{}{} + } }() - var exitCh chan struct{} - if follow { - go func() { - _, wsData, _ := wsConn.ReadMessage() - if string(wsData) == "close conn" { - exitCh <- struct{}{} - } - }() - } - buffer := make([]byte, 1024) - for { - select { - case <-exitCh: - return nil - default: - n, err := stdout.Read(buffer) - if err != nil { - if err == io.EOF { - return err + go func() { + buffer := make([]byte, 1024) + for { + select { + case <-exitCh: + return + default: + n, err := stdout.Read(buffer) + if err != nil { + if err == io.EOF { + return + } + global.LOG.Errorf("read bytes from log failed, err: %v", err) + continue + } + if !utf8.Valid(buffer[:n]) { + continue + } + if err = wsConn.WriteMessage(websocket.TextMessage, buffer[:n]); err != nil { + global.LOG.Errorf("send message with log to ws failed, err: %v", err) + return } - global.LOG.Errorf("read bytes from log failed, err: %v", err) - continue - } - if !utf8.Valid(buffer[:n]) { - continue - } - if err = wsConn.WriteMessage(websocket.TextMessage, buffer[:n]); err != nil { - global.LOG.Errorf("send message with log to ws failed, err: %v", err) - return err } } - } + }() + _ = cmd.Wait() + return nil } func (u *ContainerService) ContainerStats(id string) (*dto.ContainerStats, error) { diff --git a/frontend/src/views/container/container/log/index.vue b/frontend/src/views/container/container/log/index.vue index c2e3ba56a..b5ef262f4 100644 --- a/frontend/src/views/container/container/log/index.vue +++ b/frontend/src/views/container/container/log/index.vue @@ -143,6 +143,7 @@ const searchLogs = async () => { MsgError(i18n.global.t('container.linesHelper')); return; } + terminalSocket.value?.send('close conn'); terminalSocket.value?.close(); logInfo.value = ''; const href = window.location.href;