package nginx import ( "errors" "fmt" "github.com/astaxie/beego/logs" "github.com/pkg/sftp" "golang.org/x/crypto/ssh" "io" "net" "nginx-ui/server/models" "os" "time" ) // RemoteInstance 远程 type RemoteInstance struct { nginx *models.Nginx client *ssh.Client LastResult string } func (n *RemoteInstance) Connect() error { if n.client != nil { return nil } config := ssh.ClientConfig{} config.SetDefaults() config.User = n.nginx.User config.Auth = []ssh.AuthMethod{ ssh.Password(n.nginx.Password), } config.HostKeyCallback = func(hostname string, remote net.Addr, key ssh.PublicKey) error { return nil } config.Timeout = time.Second * 60 addr := fmt.Sprintf("%s:%d", n.nginx.IpAddr, n.nginx.Port) client, err := ssh.Dial("tcp", addr, &config) if err != nil { logs.Warn("connect error", err) return err } n.client = client go n.onDisConnect() return nil } // Run RemoteInstance 这里应该要处理session断开的流程吧 func (n *RemoteInstance) Run(cmd string) (string, error) { logs.Info("Run: ", cmd) if n.client == nil { err := n.Connect() if err != nil { return "", err } } session, err := n.client.NewSession() if err != nil { logs.Warn("NewSession fail", err) return "", err } defer session.Close() buf, err := session.CombinedOutput(cmd) n.LastResult = string(buf) logger.Printf("out: %v", n.LastResult) if err != nil { err = errors.New(fmt.Sprintf("%s;\n%s", err.Error(), n.LastResult)) } return n.LastResult, err } func (n *RemoteInstance) Close(onlySession bool) { if onlySession { return } if n.client != nil { n.client.Close() n.client = nil } } func (n *RemoteInstance) onDisConnect() { if n.client != nil { err := n.client.Wait() logger.Printf("disconnect", err) } n.client = nil } func (n *RemoteInstance) SetNginx(nginx *models.Nginx) { n.nginx = nginx } func (n *RemoteInstance) getSSHConfig() ssh.ClientConfig { config := ssh.ClientConfig{} config.SetDefaults() config.User = n.nginx.User config.Auth = []ssh.AuthMethod{ ssh.Password(n.nginx.Password), } config.HostKeyCallback = func(hostname string, remote net.Addr, key ssh.PublicKey) error { return nil } config.Timeout = time.Second * 60 return config } // SendFile RemoteInstance 这里应该要处理session断开的流程吧 func (n *RemoteInstance) SendFile(src string, remote string) error { session, err := sftp.NewClient(n.client) if err != nil { return err } defer session.Close() srcFile, err := os.Open(src) if err != nil { return err } defer srcFile.Close() dstFile, err := session.Create(remote) if err != nil { return err } defer dstFile.Close() l, err := io.Copy(dstFile, srcFile) logs.Info("sendFile ok with size: ", l) return err }