1
0
mirror of https://github.com/1Panel-dev/1Panel.git synced 2025-01-31 22:18:07 +08:00

fix: 解决僵尸进程的问题 (#4464)

This commit is contained in:
ssongliu 2024-04-10 22:18:08 +08:00 committed by GitHub
parent 0cd06803e2
commit 0bf6db1cf8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 55 additions and 48 deletions

View File

@ -102,7 +102,7 @@ func (b *BaseApi) RedisWsSsh(c *gin.Context) {
if wshandleError(wsConn, err) { if wshandleError(wsConn, err) {
return return
} }
defer killBash(redisConf.ContainerName, commands, pidMap) defer killBash(redisConf.ContainerName, pidMap)
defer slave.Close() defer slave.Close()
tty, err := terminal.NewLocalWsSession(cols, rows, wsConn, slave, false) tty, err := terminal.NewLocalWsSession(cols, rows, wsConn, slave, false)
@ -170,7 +170,7 @@ func (b *BaseApi) ContainerWsSsh(c *gin.Context) {
if wshandleError(wsConn, err) { if wshandleError(wsConn, err) {
return return
} }
defer killBash(containerID, command, pidMap) defer killBash(containerID, pidMap)
defer slave.Close() defer slave.Close()
tty, err := terminal.NewLocalWsSession(cols, rows, wsConn, slave, true) 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") lines := strings.Split(stdout, "\n")
for _, line := range lines { for _, line := range lines {
parts := strings.Fields(line) parts := strings.Fields(line)
if len(parts) != 2 { if len(parts) == 0 {
continue continue
} }
pidMap[parts[0]] = parts[1] pidMap[parts[0]] = strings.Join(parts, " ")
} }
return pidMap return pidMap
} }
func killBash(containerID, comm string, pidMap map[string]string) { func killBash(containerID string, pidMap map[string]string) {
sudo := cmd.SudoHandleCmd() sudo := cmd.SudoHandleCmd()
newPidMap := loadMapFromDockerTop(containerID) newPidMap := loadMapFromDockerTop(containerID)
for pid, command := range newPidMap { for pid, newCmd := range newPidMap {
isOld := false isOld := false
for pid2 := range pidMap { for pid2, oldCmd := range pidMap {
if pid == pid2 { if pid == pid2 && oldCmd == newCmd {
isOld = true isOld = true
break break
} }
} }
if !isOld && command == comm { if !isOld {
_, _ = cmd.Execf("%s kill -9 %s", sudo, pid) _, _ = cmd.Execf("%s kill -9 %s", sudo, pid)
} }
} }

View File

@ -626,22 +626,26 @@ func (u *ContainerService) ContainerLogs(wsConn *websocket.Conn, containerType,
if cmd.CheckIllegal(container, since, tail) { if cmd.CheckIllegal(container, since, tail) {
return buserr.New(constant.ErrCmdIllegal) return buserr.New(constant.ErrCmdIllegal)
} }
command := fmt.Sprintf("docker logs %s", container) commandName := "docker"
commandArg := []string{"logs", container}
if containerType == "compose" { if containerType == "compose" {
command = fmt.Sprintf("docker-compose -f %s logs", container) commandName = "docker-compose"
commandArg = []string{"-f", container, "logs"}
} }
if tail != "0" { if tail != "0" {
command += " --tail " + tail commandArg = append(commandArg, "--tail")
commandArg = append(commandArg, tail)
} }
if since != "all" { if since != "all" {
command += " --since " + since commandArg = append(commandArg, "--since")
commandArg = append(commandArg, since)
} }
if follow { if follow {
command += " -f" commandArg = append(commandArg, "-f")
} }
command += " 2>&1"
cmd := exec.Command("bash", "-c", command)
if !follow { if !follow {
commandArg = append(commandArg, "2>&1")
cmd := exec.Command(commandName, commandArg...)
stdout, _ := cmd.CombinedOutput() stdout, _ := cmd.CombinedOutput()
if !utf8.Valid(stdout) { if !utf8.Valid(stdout) {
return errors.New("invalid utf8") return errors.New("invalid utf8")
@ -652,50 +656,52 @@ func (u *ContainerService) ContainerLogs(wsConn *websocket.Conn, containerType,
return nil return nil
} }
cmd := exec.Command(commandName, commandArg...)
stdout, err := cmd.StdoutPipe() stdout, err := cmd.StdoutPipe()
if err != nil { if err != nil {
_ = cmd.Process.Signal(syscall.SIGTERM)
return err return err
} }
if err := cmd.Start(); err != nil { if err := cmd.Start(); err != nil {
_ = cmd.Process.Signal(syscall.SIGTERM)
return err return err
} }
defer func() { exitCh := make(chan struct{})
_ = cmd.Process.Signal(syscall.SIGTERM) go func() {
_ = cmd.Wait() _, 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) go func() {
for { buffer := make([]byte, 1024)
select { for {
case <-exitCh: select {
return nil case <-exitCh:
default: return
n, err := stdout.Read(buffer) default:
if err != nil { n, err := stdout.Read(buffer)
if err == io.EOF { if err != nil {
return err 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) { func (u *ContainerService) ContainerStats(id string) (*dto.ContainerStats, error) {

View File

@ -143,6 +143,7 @@ const searchLogs = async () => {
MsgError(i18n.global.t('container.linesHelper')); MsgError(i18n.global.t('container.linesHelper'));
return; return;
} }
terminalSocket.value?.send('close conn');
terminalSocket.value?.close(); terminalSocket.value?.close();
logInfo.value = ''; logInfo.value = '';
const href = window.location.href; const href = window.location.href;