From dc880835d0bc94f8da699ec7f64868e2fc1286b7 Mon Sep 17 00:00:00 2001 From: ssongliu <73214554+ssongliu@users.noreply.github.com> Date: Wed, 2 Apr 2025 18:19:54 +0800 Subject: [PATCH] fix: Modify the container terminal connection mode (#8301) --- backend/app/api/v1/terminal.go | 47 +++++++++++++++-------------- backend/utils/terminal/local_cmd.go | 9 ++---- 2 files changed, 26 insertions(+), 30 deletions(-) diff --git a/backend/app/api/v1/terminal.go b/backend/app/api/v1/terminal.go index 5d32248b9..cdb73a1ca 100644 --- a/backend/app/api/v1/terminal.go +++ b/backend/app/api/v1/terminal.go @@ -96,7 +96,7 @@ func (b *BaseApi) ContainerWsSSH(c *gin.Context) { } source := c.Query("source") var containerID string - var initCmd string + var initCmd []string switch source { case "redis": containerID, initCmd, err = loadRedisInitCmd(c) @@ -113,11 +113,11 @@ func (b *BaseApi) ContainerWsSSH(c *gin.Context) { return } pidMap := loadMapFromDockerTop(containerID) - slave, err := terminal.NewCommand("clear && " + initCmd) + slave, err := terminal.NewCommand(initCmd) if wshandleError(wsConn, err) { return } - defer killBash(containerID, strings.ReplaceAll(initCmd, fmt.Sprintf("docker exec -it %s ", containerID), ""), pidMap) + defer killBash(containerID, strings.ReplaceAll(strings.Join(initCmd, " "), fmt.Sprintf("exec -it %s ", containerID), ""), pidMap) defer slave.Close() tty, err := terminal.NewLocalWsSession(cols, rows, wsConn, slave, false) @@ -137,62 +137,63 @@ func (b *BaseApi) ContainerWsSSH(c *gin.Context) { } -func loadRedisInitCmd(c *gin.Context) (string, string, error) { +func loadRedisInitCmd(c *gin.Context) (string, []string, error) { name := c.Query("name") from := c.Query("from") - commands := "redis-cli" + commands := []string{"exec", "-it"} database, err := databaseService.Get(name) if err != nil { - return "", "", fmt.Errorf("no such database in db, err: %v", err) + return "", nil, fmt.Errorf("no such database in db, err: %v", err) } if from == "local" { redisInfo, err := appInstallService.LoadConnInfo(dto.OperationWithNameAndType{Name: name, Type: "redis"}) if err != nil { - return "", "", fmt.Errorf("no such app in db, err: %v", err) + return "", nil, fmt.Errorf("no such app in db, err: %v", err) } name = redisInfo.ContainerName + commands = append(commands, []string{name, "redis-cli"}...) if len(database.Password) != 0 { - commands = "redis-cli -a " + database.Password + " --no-auth-warning" + commands = append(commands, []string{"-a", database.Password, "--no-auth-warning"}...) } } else { - commands = fmt.Sprintf("redis-cli -h %s -p %v", database.Address, database.Port) - if len(database.Password) != 0 { - commands = fmt.Sprintf("redis-cli -h %s -p %v -a %s --no-auth-warning", database.Address, database.Port, database.Password) - } name = "1Panel-redis-cli-tools" + commands = append(commands, []string{name, "redis-cli", "-h", database.Address, "-p", fmt.Sprintf("%v", database.Port)}...) + if len(database.Password) != 0 { + commands = append(commands, []string{"-a", database.Password, "--no-auth-warning"}...) + } } - return name, fmt.Sprintf("docker exec -it %s %s", name, commands), nil + return name, commands, nil } -func loadOllamaInitCmd(c *gin.Context) (string, string, error) { +func loadOllamaInitCmd(c *gin.Context) (string, []string, error) { name := c.Query("name") if cmd.CheckIllegal(name) { - return "", "", fmt.Errorf("ollama model %s contains illegal characters", name) + return "", nil, fmt.Errorf("ollama model %s contains illegal characters", name) } ollamaInfo, err := appInstallService.LoadConnInfo(dto.OperationWithNameAndType{Name: "", Type: "ollama"}) if err != nil { - return "", "", fmt.Errorf("no such app in db, err: %v", err) + return "", nil, fmt.Errorf("no such app in db, err: %v", err) } containerName := ollamaInfo.ContainerName - return containerName, fmt.Sprintf("docker exec -it %s ollama run %s", containerName, name), nil + return containerName, []string{"exec", "-it", containerName, "ollama", "run", name}, nil } -func loadContainerInitCmd(c *gin.Context) (string, string, error) { +func loadContainerInitCmd(c *gin.Context) (string, []string, error) { containerID := c.Query("containerid") command := c.Query("command") user := c.Query("user") if cmd.CheckIllegal(user, containerID, command) { - return "", "", fmt.Errorf("the command contains illegal characters. command: %s, user: %s, containerID: %s", command, user, containerID) + return "", nil, fmt.Errorf("the command contains illegal characters. command: %s, user: %s, containerID: %s", command, user, containerID) } if len(command) == 0 || len(containerID) == 0 { - return "", "", fmt.Errorf("error param of command: %s or containerID: %s", command, containerID) + return "", nil, fmt.Errorf("error param of command: %s or containerID: %s", command, containerID) } - command = fmt.Sprintf("docker exec -it %s %s", containerID, command) + commands := []string{"exec", "-it", containerID, command} if len(user) != 0 { - command = fmt.Sprintf("docker exec -it -u %s %s %s", user, containerID, command) + commands = []string{"exec", "-it", "-u", user, containerID, command} } - return containerID, command, nil + return containerID, commands, nil } func wshandleError(ws *websocket.Conn, err error) bool { diff --git a/backend/utils/terminal/local_cmd.go b/backend/utils/terminal/local_cmd.go index eaf96c6fc..d77bb3596 100644 --- a/backend/utils/terminal/local_cmd.go +++ b/backend/utils/terminal/local_cmd.go @@ -25,8 +25,8 @@ type LocalCommand struct { pty *os.File } -func NewCommand(initCmd string) (*LocalCommand, error) { - cmd := exec.Command("bash") +func NewCommand(initCmd []string) (*LocalCommand, error) { + cmd := exec.Command("docker", initCmd...) if term := os.Getenv("TERM"); term != "" { cmd.Env = append(os.Environ(), "TERM="+term) } else { @@ -38,11 +38,6 @@ func NewCommand(initCmd string) (*LocalCommand, error) { return nil, errors.Wrapf(err, "failed to start command") } - if len(initCmd) != 0 { - time.Sleep(100 * time.Millisecond) - _, _ = pty.Write([]byte(initCmd + "\n")) - } - lcmd := &LocalCommand{ closeSignal: DefaultCloseSignal, closeTimeout: DefaultCloseTimeout,