agent/session/plugin/ssh/ssh.go (93 lines of code) (raw):

// Copyright (c) 2009-present, Alibaba Cloud All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package ssh import ( "fmt" "os" "os/signal" "strconv" "strings" "syscall" "github.com/aliyun/aliyun_assist_client/agent/session/plugin/cli" "github.com/aliyun/aliyun_assist_client/agent/session/plugin/client" "github.com/aliyun/aliyun_assist_client/agent/session/plugin/config" "github.com/aliyun/aliyun_assist_client/agent/session/plugin/log" "github.com/aliyun/aliyun_assist_client/agent/session/plugin/session" "github.com/aliyun/aliyun_assist_client/agent/session/plugin/i18n" "github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests" "github.com/aliyun/alibaba-cloud-sdk-go/services/ecs" ) func NewSshCommand() *cli.Command { c := &cli.Command{ Name: "ssh", Short: i18n.T( "use ssh proxy devops aliyun ecs instance", "使用ssh proxy运维阿里云实例"), Usage: "ssh --instance {instance_id} --port {port}", Run: func(ctx *cli.Context, args []string) error { if len(args) > 0 { return cli.NewInvalidCommandError(args[0], ctx) } instance_id, _ := config.InstanceFlag(ctx.Flags()).GetValue() wss_url, _ := config.WssUrlFlag(ctx.Flags()).GetValue() return doSession(ctx, instance_id, wss_url) }, } return c } func doSession(ctx *cli.Context, instance_id string, wss_url string) error { session.CheckSessionEnabled(ctx) var websocket_url string if instance_id != "" { client, err := session.GetEcsClient(ctx) if err != nil { fmt.Print(err.Error()) log.GetLogger().Errorln(err) return fmt.Errorf("get ecs client err:%v", err) } request := ecs.CreateStartTerminalSessionRequest() request.Scheme = "https" request.InstanceId = &[]string{instance_id} port_val, _ := config.PortNumberFlag(ctx.Flags()).GetValue() if port_val == "" { port_val = "22" } port_i, _ := strconv.Atoi(port_val) request.PortNumber = requests.NewInteger(port_i) response, err := client.StartTerminalSession(request) if err != nil { log.GetLogger().Errorln(err, response) fmt.Print(err.Error()) } log.GetLogger().Infof("response is %#v\n", response) websocket_url = response.WebSocketUrl } else { websocket_url = wss_url } log.GetLogger().Infoln("wss url:", websocket_url) url := websocket_url url = strings.Replace(url, "sessionid", "sessionId", 1) log.GetLogger().Infoln("websocket url:", url) client, err := client.NewClient(url, os.Stdin, os.Stdout, false, "", true, config.VerboseFlag(ctx.Flags()).IsAssigned(), 0) // recvive signal from ssh, avoid killing by ssh done := make(chan bool, 1) go waitSignals(done) if err = client.Loop(); err != nil { log.GetLogger().Fatalf("Communication error: %v", err) } done <- true return nil } func waitSignals(done chan bool) error { sigChan := make(chan os.Signal, 1) signal.Notify( sigChan, syscall.SIGHUP, ) select { case s := <-sigChan: log.GetLogger().Infoln("recv signal: ", s) break case <-done: break } log.GetLogger().Infoln("waitSignals return") return nil }