@@ -18,6 +18,55 @@ import (
1818 "github.com/pkg/errors"
1919)
2020
21+ func (b * BaseApi ) WsSSH (c * gin.Context ) {
22+ wsConn , err := upGrader .Upgrade (c .Writer , c .Request , nil )
23+ if err != nil {
24+ global .LOG .Errorf ("gin context http handler failed, err: %v" , err )
25+ return
26+ }
27+ defer wsConn .Close ()
28+
29+ if global .CONF .Base .IsDemo {
30+ if wshandleError (wsConn , errors .New (" demo server, prohibit this operation!" )) {
31+ return
32+ }
33+ }
34+
35+ cols , err := strconv .Atoi (c .DefaultQuery ("cols" , "80" ))
36+ if wshandleError (wsConn , errors .WithMessage (err , "invalid param cols in request" )) {
37+ return
38+ }
39+ rows , err := strconv .Atoi (c .DefaultQuery ("rows" , "40" ))
40+ if wshandleError (wsConn , errors .WithMessage (err , "invalid param rows in request" )) {
41+ return
42+ }
43+ name , err := loadExecutor ()
44+ if wshandleError (wsConn , err ) {
45+ return
46+ }
47+ slave , err := terminal .NewCommand (name )
48+ if wshandleError (wsConn , err ) {
49+ return
50+ }
51+ defer slave .Close ()
52+
53+ tty , err := terminal .NewLocalWsSession (cols , rows , wsConn , slave , false )
54+ if wshandleError (wsConn , err ) {
55+ return
56+ }
57+
58+ quitChan := make (chan bool , 3 )
59+ tty .Start (quitChan )
60+ go slave .Wait (quitChan )
61+
62+ <- quitChan
63+
64+ global .LOG .Info ("websocket finished" )
65+ if wshandleError (wsConn , err ) {
66+ return
67+ }
68+ }
69+
2170func (b * BaseApi ) ContainerWsSSH (c * gin.Context ) {
2271 wsConn , err := upGrader .Upgrade (c .Writer , c .Request , nil )
2372 if err != nil {
@@ -42,7 +91,7 @@ func (b *BaseApi) ContainerWsSSH(c *gin.Context) {
4291 }
4392 source := c .Query ("source" )
4493 var containerID string
45- var initCmd string
94+ var initCmd [] string
4695 switch source {
4796 case "redis" :
4897 containerID , initCmd , err = loadRedisInitCmd (c )
@@ -59,11 +108,11 @@ func (b *BaseApi) ContainerWsSSH(c *gin.Context) {
59108 return
60109 }
61110 pidMap := loadMapFromDockerTop (containerID )
62- slave , err := terminal .NewCommand ("clear && " + initCmd )
111+ slave , err := terminal .NewCommand ("docker" , initCmd ... )
63112 if wshandleError (wsConn , err ) {
64113 return
65114 }
66- defer killBash (containerID , strings .ReplaceAll (initCmd , fmt .Sprintf ("docker exec -it %s " , containerID ), "" ), pidMap )
115+ defer killBash (containerID , strings .ReplaceAll (strings . Join ( initCmd , " " ), fmt .Sprintf ("exec -it %s " , containerID ), "" ), pidMap )
67116 defer slave .Close ()
68117
69118 tty , err := terminal .NewLocalWsSession (cols , rows , wsConn , slave , false )
@@ -83,62 +132,63 @@ func (b *BaseApi) ContainerWsSSH(c *gin.Context) {
83132 }
84133}
85134
86- func loadRedisInitCmd (c * gin.Context ) (string , string , error ) {
135+ func loadRedisInitCmd (c * gin.Context ) (string , [] string , error ) {
87136 name := c .Query ("name" )
88137 from := c .Query ("from" )
89- commands := "redis-cli"
138+ commands := [] string { "exec" , "-it" }
90139 database , err := databaseService .Get (name )
91140 if err != nil {
92- return "" , "" , fmt .Errorf ("no such database in db, err: %v" , err )
141+ return "" , nil , fmt .Errorf ("no such database in db, err: %v" , err )
93142 }
94143 if from == "local" {
95144 redisInfo , err := appInstallService .LoadConnInfo (dto.OperationWithNameAndType {Name : name , Type : "redis" })
96145 if err != nil {
97- return "" , "" , fmt .Errorf ("no such app in db, err: %v" , err )
146+ return "" , nil , fmt .Errorf ("no such app in db, err: %v" , err )
98147 }
99148 name = redisInfo .ContainerName
149+ commands = append (commands , []string {name , "redis-cli" }... )
100150 if len (database .Password ) != 0 {
101- commands = "redis-cli -a " + database .Password + " --no-auth-warning"
151+ commands = append ( commands , [] string { "-a" , database .Password , " --no-auth-warning"} ... )
102152 }
103153 } else {
104- commands = fmt .Sprintf ("redis-cli -h %s -p %v" , database .Address , database .Port )
154+ name = "1Panel-redis-cli-tools"
155+ commands = append (commands , []string {name , "redis-cli" , "-h" , database .Address , "-p" , fmt .Sprintf ("%v" , database .Port )}... )
105156 if len (database .Password ) != 0 {
106- commands = fmt . Sprintf ( "redis-cli -h %s -p %v -a %s --no-auth-warning", database . Address , database . Port , database . Password )
157+ commands = append ( commands , [] string { "-a" , database . Password , " --no-auth-warning"} ... )
107158 }
108- name = "1Panel-redis-cli-tools"
109159 }
110- return name , fmt . Sprintf ( "docker exec -it %s %s" , name , commands ) , nil
160+ return name , commands , nil
111161}
112162
113- func loadOllamaInitCmd (c * gin.Context ) (string , string , error ) {
163+ func loadOllamaInitCmd (c * gin.Context ) (string , [] string , error ) {
114164 name := c .Query ("name" )
115165 if cmd .CheckIllegal (name ) {
116- return "" , "" , fmt .Errorf ("ollama model %s contains illegal characters" , name )
166+ return "" , nil , fmt .Errorf ("ollama model %s contains illegal characters" , name )
117167 }
118168 ollamaInfo , err := appInstallService .LoadConnInfo (dto.OperationWithNameAndType {Name : "" , Type : "ollama" })
119169 if err != nil {
120- return "" , "" , fmt .Errorf ("no such app in db, err: %v" , err )
170+ return "" , nil , fmt .Errorf ("no such app in db, err: %v" , err )
121171 }
122172 containerName := ollamaInfo .ContainerName
123- return containerName , fmt . Sprintf ( "docker exec -it %s ollama run %s " , containerName , name ) , nil
173+ return containerName , [] string { " exec" , " -it" , containerName , " ollama" , " run" , name } , nil
124174}
125175
126- func loadContainerInitCmd (c * gin.Context ) (string , string , error ) {
176+ func loadContainerInitCmd (c * gin.Context ) (string , [] string , error ) {
127177 containerID := c .Query ("containerid" )
128178 command := c .Query ("command" )
129179 user := c .Query ("user" )
130180 if cmd .CheckIllegal (user , containerID , command ) {
131- return "" , "" , fmt .Errorf ("the command contains illegal characters. command: %s, user: %s, containerID: %s" , command , user , containerID )
181+ return "" , nil , fmt .Errorf ("the command contains illegal characters. command: %s, user: %s, containerID: %s" , command , user , containerID )
132182 }
133183 if len (command ) == 0 || len (containerID ) == 0 {
134- return "" , "" , fmt .Errorf ("error param of command: %s or containerID: %s" , command , containerID )
184+ return "" , nil , fmt .Errorf ("error param of command: %s or containerID: %s" , command , containerID )
135185 }
136- command = fmt . Sprintf ( "docker exec -it %s %s " , containerID , command )
186+ commands := [] string { " exec" , " -it" , containerID , command }
137187 if len (user ) != 0 {
138- command = fmt . Sprintf ( "docker exec -it -u %s %s %s " , user , containerID , command )
188+ commands = [] string { " exec" , " -it" , "-u " , user , containerID , command }
139189 }
140190
141- return containerID , command , nil
191+ return containerID , commands , nil
142192}
143193
144194func wshandleError (ws * websocket.Conn , err error ) bool {
@@ -204,3 +254,12 @@ var upGrader = websocket.Upgrader{
204254 return true
205255 },
206256}
257+
258+ func loadExecutor () (string , error ) {
259+ std , err := cmd .RunDefaultWithStdoutBashC ("echo $SHELL" )
260+ if err != nil {
261+ return "" , fmt .Errorf ("load default executor failed, err: %s" , std )
262+ }
263+
264+ return strings .ReplaceAll (std , "\n " , "" ), nil
265+ }
0 commit comments