2017-03-10 09:24:06 +00:00
|
|
|
|
package cmd
|
|
|
|
|
|
|
|
|
|
import (
|
2017-04-02 02:38:49 +00:00
|
|
|
|
"github.com/go-macaron/csrf"
|
|
|
|
|
"github.com/go-macaron/gzip"
|
|
|
|
|
"github.com/go-macaron/session"
|
|
|
|
|
"github.com/ouqiang/cron-scheduler/modules/app"
|
|
|
|
|
"github.com/ouqiang/cron-scheduler/routers"
|
|
|
|
|
"github.com/urfave/cli"
|
|
|
|
|
"gopkg.in/macaron.v1"
|
2017-04-04 06:42:33 +00:00
|
|
|
|
"os"
|
|
|
|
|
"os/signal"
|
|
|
|
|
"path/filepath"
|
|
|
|
|
"os/exec"
|
|
|
|
|
"syscall"
|
|
|
|
|
"github.com/ouqiang/cron-scheduler/modules/logger"
|
2017-03-10 09:24:06 +00:00
|
|
|
|
)
|
|
|
|
|
|
2017-04-06 06:40:48 +00:00
|
|
|
|
// 1号进程id
|
2017-04-04 06:42:33 +00:00
|
|
|
|
const InitProcess = 1
|
|
|
|
|
|
2017-03-10 09:24:06 +00:00
|
|
|
|
// web服务器默认端口
|
|
|
|
|
const DefaultPort = 5920
|
2017-04-02 02:19:52 +00:00
|
|
|
|
|
2017-03-10 09:24:06 +00:00
|
|
|
|
// 静态文件目录
|
|
|
|
|
const StaticDir = "public"
|
|
|
|
|
|
|
|
|
|
var CmdWeb = cli.Command{
|
2017-04-02 02:38:49 +00:00
|
|
|
|
Name: "server",
|
|
|
|
|
Usage: "start scheduler web server",
|
|
|
|
|
Action: run,
|
|
|
|
|
Flags: []cli.Flag{
|
|
|
|
|
cli.IntFlag{
|
|
|
|
|
Name: "port,p",
|
|
|
|
|
Value: DefaultPort,
|
|
|
|
|
Usage: "bind port number",
|
|
|
|
|
},
|
2017-04-03 07:27:19 +00:00
|
|
|
|
cli.StringFlag{
|
|
|
|
|
Name: "env,e",
|
|
|
|
|
Value: "dev",
|
|
|
|
|
Usage: "runtime environment, dev|test|prod",
|
|
|
|
|
},
|
2017-04-04 06:42:33 +00:00
|
|
|
|
cli.StringFlag{
|
|
|
|
|
Name: "d",
|
|
|
|
|
Value: "false",
|
2017-04-06 06:58:34 +00:00
|
|
|
|
Usage: "-d=true, run app as daemon, not support windows",
|
2017-04-04 06:42:33 +00:00
|
|
|
|
},
|
2017-04-02 02:38:49 +00:00
|
|
|
|
},
|
2017-03-10 09:24:06 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func run(ctx *cli.Context) {
|
2017-04-04 06:42:33 +00:00
|
|
|
|
// 作为守护进程运行
|
|
|
|
|
becomeDaemon(ctx);
|
|
|
|
|
// 设置运行环境
|
2017-04-03 07:27:19 +00:00
|
|
|
|
setEnvironment(ctx)
|
2017-04-04 06:42:33 +00:00
|
|
|
|
// 初始化应用
|
2017-04-02 02:38:49 +00:00
|
|
|
|
app.InitEnv()
|
2017-04-04 06:42:33 +00:00
|
|
|
|
// 捕捉信号,配置热更新等
|
|
|
|
|
go catchSignal()
|
2017-04-02 02:38:49 +00:00
|
|
|
|
m := macaron.Classic()
|
|
|
|
|
// 注册路由
|
|
|
|
|
routers.Register(m)
|
|
|
|
|
// 注册中间件
|
|
|
|
|
registerMiddleware(m)
|
|
|
|
|
port := parsePort(ctx)
|
|
|
|
|
m.Run(port)
|
2017-03-10 09:24:06 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 中间件注册
|
2017-04-02 02:19:52 +00:00
|
|
|
|
func registerMiddleware(m *macaron.Macaron) {
|
2017-04-02 02:38:49 +00:00
|
|
|
|
m.Use(macaron.Logger())
|
|
|
|
|
m.Use(macaron.Recovery())
|
|
|
|
|
m.Use(gzip.Gziper())
|
|
|
|
|
m.Use(macaron.Static(StaticDir))
|
|
|
|
|
m.Use(macaron.Renderer(macaron.RenderOptions{
|
|
|
|
|
Directory: "templates",
|
|
|
|
|
Extensions: []string{".html"},
|
|
|
|
|
// 模板语法分隔符,默认为 ["{{", "}}"]
|
|
|
|
|
Delims: macaron.Delims{"{{{", "}}}"},
|
|
|
|
|
// 追加的 Content-Type 头信息,默认为 "UTF-8"
|
|
|
|
|
Charset: "UTF-8",
|
|
|
|
|
// 渲染具有缩进格式的 JSON,默认为不缩进
|
|
|
|
|
IndentJSON: true,
|
|
|
|
|
// 渲染具有缩进格式的 XML,默认为不缩进
|
|
|
|
|
IndentXML: true,
|
|
|
|
|
}))
|
|
|
|
|
m.Use(session.Sessioner())
|
|
|
|
|
m.Use(csrf.Csrfer())
|
2017-03-10 09:24:06 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 解析端口
|
|
|
|
|
func parsePort(ctx *cli.Context) int {
|
2017-04-03 07:27:19 +00:00
|
|
|
|
var port int = DefaultPort
|
2017-04-02 02:38:49 +00:00
|
|
|
|
if ctx.IsSet("port") {
|
|
|
|
|
port = ctx.Int("port")
|
|
|
|
|
}
|
|
|
|
|
if port <= 0 || port >= 65535 {
|
|
|
|
|
port = DefaultPort
|
|
|
|
|
}
|
2017-03-10 09:24:06 +00:00
|
|
|
|
|
2017-04-02 02:38:49 +00:00
|
|
|
|
return port
|
2017-04-02 02:19:52 +00:00
|
|
|
|
}
|
2017-04-03 07:27:19 +00:00
|
|
|
|
|
|
|
|
|
func setEnvironment(ctx *cli.Context) {
|
|
|
|
|
var env string = ""
|
|
|
|
|
if ctx.IsSet("env") {
|
|
|
|
|
env = ctx.String("env")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if env == "prod" {
|
|
|
|
|
macaron.Env = macaron.PROD
|
|
|
|
|
}
|
2017-04-04 06:42:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 捕捉信号
|
|
|
|
|
func catchSignal() {
|
|
|
|
|
c := make(chan os.Signal)
|
2017-04-06 06:40:48 +00:00
|
|
|
|
// todo 配置热更新, windows 不支持 syscall.SIGUSR1, syscall.SIGUSR2
|
|
|
|
|
signal.Notify(c, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM)
|
2017-04-04 09:05:55 +00:00
|
|
|
|
for {
|
|
|
|
|
s := <- c
|
|
|
|
|
logger.Info("收到信号 -- ", s)
|
|
|
|
|
switch s {
|
|
|
|
|
case syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM:
|
|
|
|
|
os.Exit(1)
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-04-04 06:42:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func becomeDaemon(ctx *cli.Context) {
|
2017-04-06 06:58:34 +00:00
|
|
|
|
// 不支持windows
|
|
|
|
|
if app.IsWindows {
|
|
|
|
|
return
|
|
|
|
|
}
|
2017-04-04 06:42:33 +00:00
|
|
|
|
var daemond string = "false"
|
|
|
|
|
if ctx.IsSet("d") {
|
|
|
|
|
daemond = ctx.String("d")
|
|
|
|
|
}
|
|
|
|
|
if (daemond != "true") {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if os.Getppid() == InitProcess {
|
2017-04-06 06:40:48 +00:00
|
|
|
|
// 已是守护进程,不再处理
|
2017-04-04 06:42:33 +00:00
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
filePath, _:= filepath.Abs(os.Args[0])
|
|
|
|
|
cmd := exec.Command(filePath, os.Args[1:]...)
|
|
|
|
|
cmd.Stdin = os.Stdin
|
|
|
|
|
cmd.Stdout = os.Stdout
|
|
|
|
|
cmd.Stderr = os.Stderr
|
|
|
|
|
cmd.Start()
|
|
|
|
|
|
|
|
|
|
// 父进程退出, 子进程由init-1号进程收养
|
|
|
|
|
os.Exit(0)
|
2017-04-03 07:27:19 +00:00
|
|
|
|
}
|