instance.go 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. package nginx
  2. import (
  3. "errors"
  4. "fmt"
  5. "github.com/astaxie/beego/logs"
  6. "nginx-ui/server/models"
  7. "strings"
  8. "time"
  9. )
  10. var logger = logs.GetLogger()
  11. type Dirs struct {
  12. DataDir string
  13. ConfDir string
  14. StreamDir string
  15. CertsDir string
  16. BackupDir string
  17. }
  18. type InstanceInter interface {
  19. Connect() error
  20. Close(onlySession bool)
  21. Run(cmd string) (string, error)
  22. SetNginx(nginx *models.Nginx)
  23. SendFile(src string, remote string) error
  24. }
  25. type Instance struct {
  26. InstanceInter
  27. nginx *models.Nginx
  28. }
  29. func (n *Instance) CheckDirs() Dirs {
  30. nginx := n.nginx
  31. dataDir := nginx.DataDir
  32. if strings.HasSuffix(dataDir, "/") {
  33. dataDir = dataDir[0 : len(dataDir)-1]
  34. }
  35. streamDir := fmt.Sprintf("%s/stream.d", dataDir)
  36. certsDir := fmt.Sprintf("%s/certs", dataDir)
  37. backupDir := fmt.Sprintf("%s/backup", dataDir)
  38. confDir := fmt.Sprintf("%s/conf.d", dataDir)
  39. _, _ = n.Run(fmt.Sprintf("mkdir -p %s %s %s %s", confDir, streamDir, certsDir, backupDir))
  40. return Dirs{
  41. DataDir: dataDir,
  42. ConfDir: confDir,
  43. StreamDir: streamDir,
  44. CertsDir: certsDir,
  45. BackupDir: backupDir,
  46. }
  47. }
  48. func (n *Instance) RefreshServer(server models.ServerHost) error {
  49. dirs := n.CheckDirs()
  50. var confDir string
  51. if server.IsStream {
  52. confDir = dirs.StreamDir
  53. } else {
  54. confDir = dirs.ConfDir
  55. }
  56. // id_server_name.conf
  57. realName := fmt.Sprintf("%s/%d_%s.conf", confDir, server.Id, server.Name)
  58. var lastName string
  59. if server.LastName != "" {
  60. lastName = fmt.Sprintf("%s/%d_%s.conf", confDir, server.Id, server.LastName)
  61. } else {
  62. lastName = fmt.Sprintf("%s/%d_%s.conf", confDir, server.Id, server.Name)
  63. }
  64. backName := fmt.Sprintf("%s/%s.conf_%s", dirs.BackupDir, server.Name, time.Now().Format("20060102150405"))
  65. res, err := n.Run(fmt.Sprintf("if [ -f %s ];then mv -f %s %s;fi;rm -rf %s/%d_*.conf", lastName, lastName, backName, confDir, server.Id))
  66. if err != nil {
  67. return err
  68. }
  69. defer n.Close(true)
  70. if !server.Enable {
  71. return nil
  72. }
  73. serverConf := strings.ReplaceAll(server.ServerConf, "\"", "\\\"")
  74. serverConf = strings.ReplaceAll(serverConf, "$", "\\$")
  75. cmd := fmt.Sprintf("echo \"%s\" > %s", serverConf, realName)
  76. res, err = n.Run(cmd)
  77. if err != nil {
  78. logger.Printf("echo conf fail", err, res)
  79. return err
  80. }
  81. if err := n.Check(); err != nil {
  82. _, recoveryErr := n.Run(fmt.Sprintf("if [ -f %s ];then mv -f %s %s;fi", backName, backName, realName))
  83. if recoveryErr != nil {
  84. return errors.New(fmt.Sprintf("配置文件异常: %s;且文件恢复异常,请手动处理或者修正后重新刷新!", err.Error()))
  85. }
  86. return err
  87. }
  88. if err := n.Reload(); err != nil {
  89. return err
  90. }
  91. return nil
  92. }
  93. func (n *Instance) RefreshHttp(nginx models.Nginx) error {
  94. dirs := n.CheckDirs()
  95. var confDir = nginx.NginxDir
  96. realName := fmt.Sprintf("%s/nginx.conf", dirs.DataDir)
  97. linkName := fmt.Sprintf("%s/nginx.conf", confDir)
  98. backName := fmt.Sprintf("%s/%d.http_%s", dirs.BackupDir, nginx.Id, time.Now().Format("060102150405"))
  99. res, err := n.Run(fmt.Sprintf("find %s -name nginx.conf -type l -delete", confDir))
  100. if err != nil {
  101. logger.Printf("echo rm conf file fail", err, res)
  102. return err
  103. }
  104. // 如果非软连接,就先mv 备份
  105. res, err = n.Run(fmt.Sprintf("cd %s && if [ -f nginx.conf ];then mv -f nginx.conf nginx.conf.bak ;fi", confDir))
  106. defer n.Close(true)
  107. httpConf := strings.ReplaceAll(nginx.HttpConf, "\"", "\\\"")
  108. httpConf = strings.ReplaceAll(httpConf, "$", "\\$")
  109. cmd := fmt.Sprintf("echo \"%s\" > %s && cp %s %s", httpConf, realName, realName, backName)
  110. res, err = n.Run(cmd)
  111. if err != nil {
  112. logger.Printf("echo conf fail", err, res)
  113. return err
  114. }
  115. res, err = n.Run(fmt.Sprintf("ln -s %s %s", realName, linkName))
  116. if err != nil {
  117. return err
  118. }
  119. if err := n.Check(); err != nil {
  120. return err
  121. }
  122. if err := n.Reload(); err != nil {
  123. return err
  124. }
  125. return nil
  126. }
  127. func (n *Instance) GetVersion() (string, error) {
  128. out, err := n.Run(fmt.Sprintf("%s -V", n.nginx.NginxPath))
  129. if err != nil {
  130. logs.Warn("CheckConf", err)
  131. return "", err
  132. }
  133. logs.Info("CheckConf", out)
  134. return out, err
  135. }
  136. func (n *Instance) Check() error {
  137. nginx := n.nginx
  138. _ = n.CheckDirs()
  139. out, err := n.Run(fmt.Sprintf("%s -t", nginx.NginxPath))
  140. if err != nil {
  141. logs.Warn("CheckConf fail", err, out)
  142. return err
  143. }
  144. logs.Info("CheckConf", out)
  145. return nil
  146. }
  147. // Reload 如果nginx未启动,这个返回码为 1
  148. func (n *Instance) Reload() error {
  149. isRun, _ := n.Status()
  150. if !isRun {
  151. logs.Info("nginx not running")
  152. return nil
  153. }
  154. var cmd string
  155. if n.nginx.IsServer {
  156. cmd = "service nginx reload"
  157. } else {
  158. cmd = fmt.Sprintf("%s -s reload", n.nginx.NginxPath)
  159. }
  160. out, err := n.Run(cmd)
  161. if err != nil {
  162. logs.Warn("Reload", err)
  163. return err
  164. }
  165. logs.Info("Reload", out)
  166. return nil
  167. }
  168. func (n *Instance) Status() (bool, string) {
  169. var cmd string
  170. if n.nginx.IsServer {
  171. cmd = "service nginx status"
  172. } else { // 得想其它办法,这个没有直接的命令,ps也不见得有
  173. cmd = fmt.Sprintf("%s -s reload", n.nginx.NginxPath)
  174. }
  175. out, err := n.Run(cmd)
  176. if err != nil {
  177. logs.Warn("Status", err)
  178. return false, out
  179. }
  180. logs.Info("Status", out)
  181. return true, out
  182. }
  183. // Start 如果已经启动,这里会返回-1
  184. func (n *Instance) Start() error {
  185. var cmd string
  186. if n.nginx.IsServer {
  187. cmd = "service nginx start"
  188. } else {
  189. cmd = fmt.Sprintf("%s", n.nginx.NginxPath)
  190. }
  191. go func() {
  192. out, err := n.Run(cmd)
  193. if err != nil {
  194. logs.Warn("Start", err)
  195. }
  196. logs.Info("Start", out)
  197. }()
  198. time.Sleep(time.Second * 5)
  199. return nil
  200. }
  201. func (n *Instance) Stop() error {
  202. var cmd string
  203. if n.nginx.IsServer {
  204. cmd = "service nginx stop"
  205. } else {
  206. cmd = fmt.Sprintf("%s -s stop", n.nginx.NginxPath)
  207. }
  208. out, err := n.Run(cmd)
  209. if err != nil {
  210. logs.Warn("Stop", err)
  211. return err
  212. }
  213. logs.Info("Stop", out)
  214. return nil
  215. }
  216. func (n *Instance) GetCerts() string {
  217. dirs := n.CheckDirs()
  218. cmd := fmt.Sprintf("cd %s && /usr/bin/ls -l *.key | /usr/bin/awk '{print $9}'", dirs.CertsDir)
  219. out, err := n.Run(cmd)
  220. if err != nil {
  221. logs.Warn("GetCerts", err)
  222. return ""
  223. }
  224. logs.Info("GetCerts", out)
  225. return out
  226. }
  227. func (n *Instance) GetCertData(name string) (*models.NginxCerts, error) {
  228. cert := models.NginxCerts{
  229. ServiceName: name,
  230. }
  231. dirs := n.CheckDirs()
  232. pemPath := fmt.Sprintf("%s/%s.pem", dirs.CertsDir, name)
  233. keyPath := fmt.Sprintf("%s/%s.key", dirs.CertsDir, name)
  234. cmd := "/usr/bin/cat " + keyPath
  235. out, err := n.Run(cmd)
  236. if err != nil {
  237. logs.Warn("Stop", err)
  238. return &cert, err
  239. }
  240. cert.Key = out
  241. cmd = "/usr/bin/cat " + pemPath
  242. out, err = n.Run(cmd)
  243. if err != nil {
  244. logs.Warn("Stop", err)
  245. return &cert, err
  246. }
  247. cert.Pem = out
  248. return &cert, nil
  249. }
  250. func (n *Instance) SaveCerts(cert *models.NginxCerts) error {
  251. dirs := n.CheckDirs()
  252. pemPath := fmt.Sprintf("%s/%s.pem", dirs.CertsDir, cert.ServiceName)
  253. keyPath := fmt.Sprintf("%s/%s.key", dirs.CertsDir, cert.ServiceName)
  254. cmd := fmt.Sprintf("echo '%s' > %s;echo '%s' > %s", cert.Pem, pemPath, cert.Key, keyPath)
  255. out, err := n.Run(cmd)
  256. if err != nil {
  257. logs.Warn("SaveCerts", err)
  258. return err
  259. }
  260. logs.Info("SaveCerts ", out)
  261. return nil
  262. }