main.go 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  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. "redisdog/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/forbidden", index_forbidden)
  182. handle.HandleFunc("/index/stats", index_stats)
  183. handle.HandleFunc("/index/info", index_info)
  184. //用户操作
  185. handle.HandleFunc("/profile/logout", profile_logout)
  186. handle.HandleFunc("/profile/passwd", profile_passwd)
  187. //配置-redis
  188. handle.HandleFunc("/syscfg/redis", syscfg_redis)
  189. handle.HandleFunc("/syscfg/redis_list", syscfg_redis_list)
  190. handle.HandleFunc("/syscfg/redis_get", syscfg_redis_get)
  191. handle.HandleFunc("/syscfg/redis_set", syscfg_redis_set)
  192. handle.HandleFunc("/syscfg/redis_del", syscfg_redis_del)
  193. //配置-报警
  194. handle.HandleFunc("/syscfg/warn", syscfg_warn)
  195. handle.HandleFunc("/syscfg/warn_get", syscfg_warn_get)
  196. handle.HandleFunc("/syscfg/warn_set", syscfg_warn_set)
  197. //配置-账号
  198. handle.HandleFunc("/syscfg/account", syscfg_account)
  199. handle.HandleFunc("/syscfg/account_list", syscfg_account_list)
  200. handle.HandleFunc("/syscfg/account_get", syscfg_account_get)
  201. handle.HandleFunc("/syscfg/account_set", syscfg_account_set)
  202. handle.HandleFunc("/syscfg/account_del", syscfg_account_del)
  203. handle.HandleFunc("/syscfg/account_reset_pwd", syscfg_account_reset_pwd)
  204. //配置-杂项
  205. handle.HandleFunc("/syscfg/misc", syscfg_misc)
  206. handle.HandleFunc("/syscfg/misc_get", syscfg_misc_get)
  207. handle.HandleFunc("/syscfg/misc_set", syscfg_misc_set)
  208. //日志-Redis监控
  209. handle.HandleFunc("/log/monitor", log_monitor)
  210. handle.HandleFunc("/log/monitor_list", log_monitor_list)
  211. //日志-Redis报警
  212. handle.HandleFunc("/log/warn", log_warn)
  213. handle.HandleFunc("/log/warn_list", log_warn_list)
  214. //日志-Redis扩容
  215. handle.HandleFunc("/log/autoprocess", log_autoprocess)
  216. handle.HandleFunc("/log/autoprocess_list", log_autoprocess_list)
  217. //日志-系统错误
  218. handle.HandleFunc("/log/syslog", log_syslog)
  219. handle.HandleFunc("/log/syslog_list", log_syslog_list)
  220. //资源文件
  221. handle.Handle("/resources/", http.StripPrefix("/resources/", http.FileServer(http.Dir(Cfg.ResourcesDir))))
  222. //ico文件
  223. handle.HandleFunc("/favicon.ico", func(resp http.ResponseWriter, req *http.Request) {
  224. http.ServeFile(resp, req, filepath.Join(Cfg.ResourcesDir, "favicon.ico"))
  225. })
  226. //测试
  227. handle.HandleFunc("/debug/sendmail", debug_sendmail)
  228. //启动HTTP服务
  229. srv := &http.Server{
  230. Addr: fmt.Sprintf("%s:%s", Cfg.Host, Cfg.Port),
  231. Handler: handle,
  232. }
  233. go func(s *http.Server) {
  234. if err := s.ListenAndServe(); err != nil {
  235. log.Fatal(err)
  236. }
  237. }(srv)
  238. return srv
  239. }
  240. func main() {
  241. //加载基础配置
  242. changeWordDir()
  243. Cfg = loadConfig()
  244. //连接DB
  245. Db = openDatabase(Cfg.Database)
  246. defer Db.Close()
  247. //系统日志表对象
  248. SysLogger = model.NewSysLog(Db)
  249. //创建HTTP会话池
  250. SessPoll = NewSessionPoll(Cfg.SessionTTL)
  251. //添加HTML模板函数
  252. TmplFuncMap = make(template.FuncMap)
  253. TmplFuncMap["has_prefix"] = strings.HasPrefix
  254. //从DB加载业务配置
  255. SysCfg = NewSysCfgCache()
  256. SysCfg.Load()
  257. //开始HTTP服务
  258. Srv = startHttpServer()
  259. //开始监控Redis状态
  260. Monitor := NewRedisMonitor()
  261. go Monitor.Loop()
  262. //开始处理邮件发送队列
  263. Sender = NewMailSender()
  264. go Sender.Loop()
  265. //开始定时清理日志表记录
  266. go func() {
  267. //取配置
  268. days := int(30)
  269. for {
  270. if str, ok := SysCfg.Get("log_kept_days"); ok {
  271. if num, err := strconv.Atoi(str); err == nil {
  272. days = num
  273. } else {
  274. SYSLOG("DEBUG", fmt.Sprintf("表syscfg记录cfg_key=log_kept_days的值不是数字:%s", err.Error()))
  275. }
  276. }
  277. ts := time.Now().Unix() - 86400*int64(days)
  278. SysLogger.CleanUntil(ts)
  279. mdlMonitorLog := model.NewMonitorLog(Db)
  280. mdlMonitorLog.CleanUntil(ts)
  281. mdlWarnLog := model.NewWarnLog(Db)
  282. mdlWarnLog.CleanUntil(ts)
  283. mdlProcessLog := model.NewProcessLog(Db)
  284. mdlProcessLog.CleanUntil(ts)
  285. time.Sleep(time.Hour * 1)
  286. }
  287. }()
  288. //记录启动日志
  289. SYSLOG("DEBUG", "服务启动")
  290. //监听信号
  291. waitSignal()
  292. }