instance.go 7.2 KB

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