diff --git a/models/task.go b/models/task.go index ea8c033..0de5458 100644 --- a/models/task.go +++ b/models/task.go @@ -9,6 +9,7 @@ type TaskProtocol int8 const ( TaskHTTP TaskProtocol = iota + 1 // HTTP协议 TaskSSH // SSH命令 + TaskLocalCommand // 本地命令 ) // 任务 @@ -16,7 +17,7 @@ type Task struct { Id int `xorm:"int pk autoincr"` Name string `xorm:"varchar(64) notnull"` // 任务名称 Spec string `xorm:"varchar(64) notnull"` // crontab - Protocol TaskProtocol `xorm:"tinyint notnull"` // 协议 1:http 2:ssh-command + Protocol TaskProtocol `xorm:"tinyint notnull"` // 协议 1:http 2:ssh-command 3: 本地命令 Command string `xorm:"varchar(512) notnull"` // URL地址或shell命令 Timeout int `xorm:"mediumint notnull default 0"` // 任务执行超时时间(单位秒),0不限制 HostId int16 `xorm:"smallint notnull default 0"` // SSH host id, diff --git a/modules/app/app.go b/modules/app/app.go index 301c53d..d7f35c4 100644 --- a/modules/app/app.go +++ b/modules/app/app.go @@ -25,6 +25,7 @@ func init() { } func InitEnv() { + runtime.GOMAXPROCS(runtime.NumCPU()) logger.InitLogger() wd, err := os.Getwd() if err != nil { diff --git a/modules/ssh/ssh.go b/modules/ssh/ssh.go index 873a0ae..0d6232a 100644 --- a/modules/ssh/ssh.go +++ b/modules/ssh/ssh.go @@ -23,9 +23,26 @@ type Result struct { // 执行shell命令 func Exec(sshConfig SSHConfig, cmd string) (output string, err error) { + client, err := getClient(sshConfig) + if err != nil { + return "", err + } + defer client.Close() + + session, err := client.NewSession() + + if err != nil { + return "", err + } + defer session.Close() + var resultChan chan Result = make(chan Result) var timeoutChan chan bool = make(chan bool) - go execCommand(sshConfig, cmd, resultChan) + go func() { + cmd += fmt.Sprintf(" & { sleep %d; eval 'kill $!' &> /dev/null; }", sshConfig.ExecTimeout) + output, err := session.CombinedOutput(cmd) + resultChan <- Result{string(output), err} + }() go triggerTimeout(timeoutChan, sshConfig.ExecTimeout) select { case result := <- resultChan: @@ -55,24 +72,6 @@ func getClient(sshConfig SSHConfig) (*ssh.Client, error) { return ssh.Dial("tcp", addr, config) } -func execCommand(sshConfig SSHConfig, cmd string, result chan Result) { - client, err := getClient(sshConfig) - if err != nil { - result <- Result{"", err} - return - } - defer client.Close() - - session, err := client.NewSession() - - if err != nil { - result <- Result{"", err} - return - } - defer session.Close() - output, err := session.CombinedOutput(cmd) - result <- Result{string(output), err} -} func triggerTimeout(ch chan bool, timeout int){ // 最长执行时间不能超过24小时 diff --git a/routers/task/task.go b/routers/task/task.go index 524e748..424b453 100644 --- a/routers/task/task.go +++ b/routers/task/task.go @@ -37,7 +37,7 @@ func Create(ctx *macaron.Context) { type TaskForm struct { Name string `binding:"Required;"` Spec string `binding:"Required;MaxSize(64)"` - Protocol models.TaskProtocol `binding:"In(1,2)"` + Protocol models.TaskProtocol `binding:"In(1,2,3)"` Command string `binding:"Required;MaxSize(512)"` Timeout int `binding:"Range(0,86400)"` HostId int16 diff --git a/service/task.go b/service/task.go index e85c6f2..8b7b61d 100644 --- a/service/task.go +++ b/service/task.go @@ -9,6 +9,8 @@ import ( "github.com/ouqiang/gocron/modules/logger" "github.com/ouqiang/gocron/modules/ssh" "github.com/jakecoffman/cron" + "github.com/ouqiang/gocron/modules/utils" + "strings" ) var Cron *cron.Cron @@ -54,6 +56,19 @@ type Handler interface { Run(taskModel models.TaskHost) (string, error) } + +type LocalCommandHandler struct {} + +func (h *LocalCommandHandler) Run(taskModel models.TaskHost) (string, error) { + args := strings.Split(taskModel.Command, " ") + + if len(args) > 1 { + return utils.ExecShell(args[0], args[1:]...) + } + + return utils.ExecShell(args[0]) +} + // HTTP任务 type HTTPHandler struct{} @@ -138,10 +153,12 @@ func updateTaskLog(taskLogId int64, result string, err error) (int64, error) { func createHandlerJob(taskModel models.TaskHost) cron.FuncJob { var handler Handler = nil switch taskModel.Protocol { - case models.TaskHTTP: - handler = new(HTTPHandler) - case models.TaskSSH: - handler = new(SSHCommandHandler) + case models.TaskHTTP: + handler = new(HTTPHandler) + case models.TaskSSH: + handler = new(SSHCommandHandler) + case models.TaskLocalCommand: + handler = new(LocalCommandHandler) } if handler == nil { return nil @@ -152,17 +169,7 @@ func createHandlerJob(taskModel models.TaskHost) cron.FuncJob { logger.Error("任务开始执行#写入任务日志失败-", err) return } - // err != nil 执行失败, 失败重试3次 - retryTime := 4 - var result string = "" - for i := 0; i < retryTime; i++ { - result, err = handler.Run(taskModel) - if err == nil { - break - } else { - logger.Error("任务执行失败#tasklog.id-" + strconv.FormatInt(taskLogId, 10) + "#尝试次数-" + strconv.Itoa(i + 1) + "#" + err.Error() + " " + result) - } - } + result, err := handler.Run(taskModel) _, err = updateTaskLog(taskLogId, result, err) if err != nil { logger.Error("任务结束#更新任务日志失败-", err) diff --git a/templates/task/log.html b/templates/task/log.html index 73fcfd8..bdfb6b4 100644 --- a/templates/task/log.html +++ b/templates/task/log.html @@ -42,7 +42,7 @@