main.go 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. package main
  2. import (
  3. "database/sql"
  4. "encoding/json"
  5. "flag"
  6. "fmt"
  7. "html/template"
  8. "log"
  9. "net/http"
  10. "os"
  11. "os/signal"
  12. "path/filepath"
  13. "strconv"
  14. "strings"
  15. "syscall"
  16. "time"
  17. "cnphper.com/model"
  18. _ "github.com/mattn/go-sqlite3"
  19. )
  20. type Config struct {
  21. Host string
  22. Port string
  23. Database string
  24. RootPwd string
  25. LogDir string
  26. TmplDir string
  27. ResourcesDir string
  28. SessionTTL int64
  29. }
  30. var (
  31. Cfg *Config
  32. Db *sql.DB
  33. SessPoll *SessionPoll
  34. TmplFuncMap template.FuncMap
  35. SysCfg *SysCfgCache
  36. Srv *http.Server
  37. Sender *MailSender
  38. Monitor *RedisMonitor
  39. SysLogger *model.SysLog
  40. )
  41. func changeWordDir() {
  42. if binDir, err := filepath.Abs(filepath.Dir(os.Args[0])); err != nil {
  43. log.Fatalf("%s\n", err.Error())
  44. } else {
  45. rootDir := filepath.Dir(binDir)
  46. os.Chdir(rootDir)
  47. }
  48. }
  49. func loadConfig() *Config {
  50. var (
  51. cfgfile string
  52. cfg *Config = &Config{}
  53. )
  54. flag.StringVar(&cfgfile, "c", "", "config file")
  55. flag.Parse()
  56. if cfgfile == "" {
  57. log.Fatalf("Usage: %s -c <config file>\n", os.Args[0])
  58. }
  59. wd, err := os.Getwd()
  60. if err != nil {
  61. log.Fatalf("Get work directory failed: %s\n", err.Error())
  62. }
  63. file, err := os.OpenFile(cfgfile, os.O_RDONLY, 0644)
  64. if err != nil {
  65. log.Fatal(err)
  66. }
  67. decoder := json.NewDecoder(file)
  68. if err = decoder.Decode(cfg); err != nil {
  69. log.Fatal(err)
  70. }
  71. if cfg.Port == "" {
  72. cfg.Port = "8080"
  73. }
  74. if cfg.Database == "" {
  75. cfg.Database = filepath.Join(wd, "db", "db.sqlite")
  76. }
  77. if cfg.RootPwd == "" {
  78. cfg.RootPwd = "88888888"
  79. }
  80. if cfg.LogDir == "" {
  81. cfg.LogDir = filepath.Join(wd, "log")
  82. }
  83. if cfg.TmplDir == "" {
  84. cfg.TmplDir = filepath.Join(wd, "tmpl")
  85. }
  86. if cfg.ResourcesDir == "" {
  87. cfg.ResourcesDir = filepath.Join(wd, "resources")
  88. }
  89. if cfg.SessionTTL == 0 {
  90. cfg.SessionTTL = 900
  91. }
  92. return cfg
  93. }
  94. func waitSignal() {
  95. ch := make(chan os.Signal, 1)
  96. signal.Notify(ch, syscall.SIGUSR1)
  97. signal.Notify(ch, syscall.SIGTERM)
  98. for {
  99. sig := <-ch
  100. switch sig {
  101. //重启
  102. case syscall.SIGUSR1:
  103. close(ch)
  104. if Srv != nil {
  105. Srv.Close()
  106. }
  107. SYSLOG("WARN", "服务因重启而停止")
  108. syscall.Exec(os.Args[0], os.Args[1:], nil)
  109. //退出
  110. case syscall.SIGTERM:
  111. close(ch)
  112. if Srv != nil {
  113. Srv.Close()
  114. }
  115. SYSLOG("WARN", "服务停止")
  116. os.Exit(0)
  117. }
  118. }
  119. }
  120. func openDatabase(dbfile string) *sql.DB {
  121. db, err := sql.Open("sqlite3", dbfile)
  122. if err != nil {
  123. log.Fatalf("sql.Open() Error: %s\n", err.Error())
  124. }
  125. _, err = db.Exec(Sql_Table_Syscfg)
  126. if err != nil {
  127. log.Fatalf("sql.Exec() Error: %s\n", err.Error())
  128. }
  129. _, err = db.Exec(Sql_Table_Accounts)
  130. if err != nil {
  131. log.Fatalf("sql.Exec() Error: %s\n", err.Error())
  132. }
  133. _, err = db.Exec(Sql_Table_Rediscfg)
  134. if err != nil {
  135. log.Fatalf("sql.Exec() Error: %s\n", err.Error())
  136. }
  137. _, err = db.Exec(Sql_Table_Syslog)
  138. if err != nil {
  139. log.Fatalf("sql.Exec() Error: %s\n", err.Error())
  140. }
  141. _, err = db.Exec(Sql_Index_Syslog)
  142. if err != nil {
  143. log.Fatalf("sql.Exec() Error: %s\n", err.Error())
  144. }
  145. _, err = db.Exec(Sql_Table_Monitorlog)
  146. if err != nil {
  147. log.Fatalf("sql.Exec() Error: %s\n", err.Error())
  148. }
  149. _, err = db.Exec(Sql_Table_Warnlog)
  150. if err != nil {
  151. log.Fatalf("sql.Exec() Error: %s\n", err.Error())
  152. }
  153. _, err = db.Exec(Sql_Index_Warnlog1)
  154. if err != nil {
  155. log.Fatalf("sql.Exec() Error: %s\n", err.Error())
  156. }
  157. _, err = db.Exec(Sql_Index_Warnlog2)
  158. if err != nil {
  159. log.Fatalf("sql.Exec() Error: %s\n", err.Error())
  160. }
  161. _, err = db.Exec(Sql_Table_Processlog)
  162. if err != nil {
  163. log.Fatalf("sql.Exec() Error: %s\n", err.Error())
  164. }
  165. _, err = db.Exec("INSERT OR IGNORE INTO accounts(account,name,password,is_super) VALUES(?,?,?,?)", "root", "超管", model.PasswordConvert(Cfg.RootPwd), 1)
  166. if err != nil {
  167. log.Fatalf("sql.Exec() Error: %s\n", err.Error())
  168. }
  169. _, err = db.Exec(Sql_Values_Syscfg)
  170. if err != nil {
  171. log.Fatalf("sql.Exec() Error: %s\n", err.Error())
  172. }
  173. return db
  174. }
  175. func startHttpServer() *http.Server {
  176. handle := http.NewServeMux()
  177. //登录
  178. handle.HandleFunc("/login", login_index)
  179. //首页
  180. handle.HandleFunc("/", index_default)
  181. handle.HandleFunc("/index/stats", index_stats)
  182. handle.HandleFunc("/index/info", index_info)
  183. //用户操作
  184. handle.HandleFunc("/profile/logout", profile_logout)
  185. handle.HandleFunc("/profile/passwd", profile_passwd)
  186. //配置-redis
  187. handle.HandleFunc("/syscfg/redis", syscfg_redis)
  188. handle.HandleFunc("/syscfg/redis_list", syscfg_redis_list)
  189. handle.HandleFunc("/syscfg/redis_get", syscfg_redis_get)
  190. handle.HandleFunc("/syscfg/redis_set", syscfg_redis_set)
  191. handle.HandleFunc("/syscfg/redis_del", syscfg_redis_del)
  192. //配置-报警
  193. handle.HandleFunc("/syscfg/warn", syscfg_warn)
  194. handle.HandleFunc("/syscfg/warn_get", syscfg_warn_get)
  195. handle.HandleFunc("/syscfg/warn_set", syscfg_warn_set)
  196. //配置-账号
  197. handle.HandleFunc("/syscfg/account", syscfg_account)
  198. handle.HandleFunc("/syscfg/account_list", syscfg_account_list)
  199. handle.HandleFunc("/syscfg/account_get", syscfg_account_get)
  200. handle.HandleFunc("/syscfg/account_set", syscfg_account_set)
  201. handle.HandleFunc("/syscfg/account_del", syscfg_account_del)
  202. handle.HandleFunc("/syscfg/account_reset_pwd", syscfg_account_reset_pwd)
  203. //配置-杂项
  204. handle.HandleFunc("/syscfg/misc", syscfg_misc)
  205. handle.HandleFunc("/syscfg/misc_get", syscfg_misc_get)
  206. handle.HandleFunc("/syscfg/misc_set", syscfg_misc_set)
  207. //日志-Redis监控
  208. handle.HandleFunc("/log/monitor", log_monitor)
  209. handle.HandleFunc("/log/monitor_list", log_monitor_list)
  210. //日志-Redis报警
  211. handle.HandleFunc("/log/warn", log_warn)
  212. handle.HandleFunc("/log/warn_list", log_warn_list)
  213. //日志-Redis扩容
  214. handle.HandleFunc("/log/autoprocess", log_autoprocess)
  215. handle.HandleFunc("/log/autoprocess_list", log_autoprocess_list)
  216. //日志-系统错误
  217. handle.HandleFunc("/log/syslog", log_syslog)
  218. handle.HandleFunc("/log/syslog_list", log_syslog_list)
  219. //资源文件
  220. handle.Handle("/resources/", http.StripPrefix("/resources/", http.FileServer(http.Dir(Cfg.ResourcesDir))))
  221. //ico文件
  222. handle.HandleFunc("/favicon.ico", func(resp http.ResponseWriter, req *http.Request) {
  223. http.ServeFile(resp, req, filepath.Join(Cfg.ResourcesDir, "favicon.ico"))
  224. })
  225. //测试
  226. handle.HandleFunc("/debug/sendmail", debug_sendmail)
  227. //启动HTTP服务
  228. srv := &http.Server{
  229. Addr: fmt.Sprintf("%s:%s", Cfg.Host, Cfg.Port),
  230. Handler: handle,
  231. }
  232. go func(s *http.Server) {
  233. if err := s.ListenAndServe(); err != nil {
  234. log.Fatal(err)
  235. }
  236. }(srv)
  237. return srv
  238. }
  239. func main() {
  240. //加载基础配置
  241. changeWordDir()
  242. Cfg = loadConfig()
  243. //连接DB
  244. Db = openDatabase(Cfg.Database)
  245. defer Db.Close()
  246. //系统日志表对象
  247. SysLogger = model.NewSysLog(Db)
  248. //创建HTTP会话池
  249. SessPoll = NewSessionPoll(Cfg.SessionTTL)
  250. //添加HTML模板函数
  251. TmplFuncMap = make(template.FuncMap)
  252. TmplFuncMap["has_prefix"] = strings.HasPrefix
  253. //从DB加载业务配置
  254. SysCfg = NewSysCfgCache()
  255. SysCfg.Load()
  256. //开始HTTP服务
  257. Srv = startHttpServer()
  258. //开始监控Redis状态
  259. Monitor := NewRedisMonitor()
  260. go Monitor.Loop()
  261. //开始处理邮件发送队列
  262. Sender = NewMailSender()
  263. go Sender.Loop()
  264. //开始定时清理日志表记录
  265. go func() {
  266. //取配置
  267. days := int(30)
  268. for {
  269. if str, ok := SysCfg.Get("log_kept_days"); ok {
  270. if num, err := strconv.Atoi(str); err == nil {
  271. days = num
  272. } else {
  273. SYSLOG("DEBUG", fmt.Sprintf("表syscfg记录cfg_key=log_kept_days的值不是数字:%s", err.Error()))
  274. }
  275. }
  276. ts := time.Now().Unix() - 86400*int64(days)
  277. SysLogger.CleanUntil(ts)
  278. mdlMonitorLog := model.NewMonitorLog(Db)
  279. mdlMonitorLog.CleanUntil(ts)
  280. mdlWarnLog := model.NewWarnLog(Db)
  281. mdlWarnLog.CleanUntil(ts)
  282. mdlProcessLog := model.NewProcessLog(Db)
  283. mdlProcessLog.CleanUntil(ts)
  284. time.Sleep(time.Hour * 1)
  285. }
  286. }()
  287. //记录启动日志
  288. SYSLOG("DEBUG", "服务启动")
  289. //监听信号
  290. waitSignal()
  291. }