remote.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. package nginx
  2. import (
  3. "errors"
  4. "fmt"
  5. "github.com/astaxie/beego/logs"
  6. "github.com/pkg/sftp"
  7. "golang.org/x/crypto/ssh"
  8. "io"
  9. "net"
  10. "nginx-ui/server/models"
  11. "os"
  12. "time"
  13. )
  14. // RemoteInstance 远程
  15. type RemoteInstance struct {
  16. nginx *models.Nginx
  17. client *ssh.Client
  18. LastResult string
  19. }
  20. func NewRemoteInstance(ngx *models.Nginx) *RemoteInstance {
  21. return &RemoteInstance{
  22. nginx: ngx,
  23. }
  24. }
  25. func (n *RemoteInstance) Connect() error {
  26. if n.client != nil {
  27. return nil
  28. }
  29. config := ssh.ClientConfig{}
  30. config.SetDefaults()
  31. config.User = n.nginx.User
  32. config.Auth = []ssh.AuthMethod{
  33. ssh.Password(n.nginx.Password),
  34. }
  35. config.HostKeyCallback = func(hostname string, remote net.Addr, key ssh.PublicKey) error {
  36. return nil
  37. }
  38. config.Timeout = time.Second * 60
  39. addr := fmt.Sprintf("%s:%d", n.nginx.IpAddr, n.nginx.Port)
  40. client, err := ssh.Dial("tcp", addr, &config)
  41. if err != nil {
  42. logs.Warn("connect error", err)
  43. return err
  44. }
  45. n.client = client
  46. go n.onDisConnect()
  47. return nil
  48. }
  49. // Run RemoteInstance 这里应该要处理session断开的流程吧
  50. func (n *RemoteInstance) Run(cmd string) (string, error) {
  51. logs.Info("Run: ", cmd)
  52. if n.client == nil {
  53. err := n.Connect()
  54. if err != nil {
  55. return "", err
  56. }
  57. }
  58. session, err := n.client.NewSession()
  59. if err != nil {
  60. logs.Warn("NewSession fail", err)
  61. return "", err
  62. }
  63. defer session.Close()
  64. buf, err := session.CombinedOutput(cmd)
  65. n.LastResult = string(buf)
  66. logger.Printf("out: %v", n.LastResult)
  67. if err != nil {
  68. err = errors.New(fmt.Sprintf("%s;\n%s", err.Error(), n.LastResult))
  69. }
  70. return n.LastResult, err
  71. }
  72. func (n *RemoteInstance) Close(onlySession bool) {
  73. if onlySession {
  74. return
  75. }
  76. if n.client != nil {
  77. n.client.Close()
  78. n.client = nil
  79. }
  80. }
  81. func (n *RemoteInstance) onDisConnect() {
  82. if n.client != nil {
  83. err := n.client.Wait()
  84. logger.Printf("disconnect", err)
  85. }
  86. n.client = nil
  87. }
  88. func (n *RemoteInstance) SetNginx(nginx *models.Nginx) {
  89. n.nginx = nginx
  90. }
  91. func (n *RemoteInstance) getSSHConfig() ssh.ClientConfig {
  92. config := ssh.ClientConfig{}
  93. config.SetDefaults()
  94. config.User = n.nginx.User
  95. config.Auth = []ssh.AuthMethod{
  96. ssh.Password(n.nginx.Password),
  97. }
  98. config.HostKeyCallback = func(hostname string, remote net.Addr, key ssh.PublicKey) error {
  99. return nil
  100. }
  101. config.Timeout = time.Second * 60
  102. return config
  103. }
  104. // SendFile RemoteInstance 这里应该要处理session断开的流程吧
  105. func (n *RemoteInstance) SendFile(src string, remote string) error {
  106. session, err := sftp.NewClient(n.client)
  107. if err != nil {
  108. return err
  109. }
  110. defer session.Close()
  111. srcFile, err := os.Open(src)
  112. if err != nil {
  113. return err
  114. }
  115. defer srcFile.Close()
  116. dstFile, err := session.Create(remote)
  117. if err != nil {
  118. return err
  119. }
  120. defer dstFile.Close()
  121. l, err := io.Copy(dstFile, srcFile)
  122. logs.Info("sendFile ok with size: ", l)
  123. return err
  124. }