gocron/service/task.go

176 lines
4.9 KiB
Go
Raw Normal View History

2017-03-10 09:24:06 +00:00
package service
import (
2017-04-07 01:22:00 +00:00
"github.com/ouqiang/gocron/models"
"github.com/ouqiang/gocron/modules/crontask"
2017-04-02 02:38:49 +00:00
"github.com/robfig/cron"
"io/ioutil"
"net/http"
"strconv"
"time"
2017-04-07 01:22:00 +00:00
"github.com/ouqiang/gocron/modules/logger"
"github.com/ouqiang/gocron/modules/ssh"
2017-03-10 09:24:06 +00:00
)
2017-04-02 02:19:52 +00:00
type Task struct{}
2017-03-10 09:24:06 +00:00
2017-03-24 09:55:44 +00:00
// 初始化任务, 从数据库取出所有任务, 添加到定时任务并运行
2017-04-02 02:19:52 +00:00
func (task *Task) Initialize() {
2017-04-02 02:38:49 +00:00
taskModel := new(models.Task)
taskList, err := taskModel.ActiveList()
if err != nil {
2017-04-03 07:27:19 +00:00
logger.Error("获取任务列表错误-", err.Error())
2017-04-02 02:38:49 +00:00
return
}
if len(taskList) == 0 {
2017-04-03 07:27:19 +00:00
logger.Debug("任务列表为空")
2017-04-02 02:38:49 +00:00
return
}
for _, item := range taskList {
task.Add(item)
}
2017-03-10 09:24:06 +00:00
}
// 添加任务
func (task *Task) Add(taskModel models.TaskHost) {
2017-04-02 02:38:49 +00:00
taskFunc := createHandlerJob(taskModel)
if taskFunc == nil {
2017-04-03 07:27:19 +00:00
logger.Error("添加任务#不存在的任务协议编号", taskModel.Protocol)
2017-04-02 02:38:49 +00:00
return
}
// 定时任务
if taskModel.Type == models.Timing {
2017-04-06 06:40:48 +00:00
err := crontask.DefaultCronTask.Update(strconv.Itoa(taskModel.Id), taskModel.Spec, taskFunc)
2017-04-02 02:38:49 +00:00
if err != nil {
2017-04-03 07:27:19 +00:00
logger.Error(err)
2017-04-02 02:38:49 +00:00
}
} else if taskModel.Type == models.Delay {
// 延时任务
delay := time.Duration(taskModel.Delay) * time.Second
time.AfterFunc(delay, taskFunc)
2017-04-02 02:38:49 +00:00
}
2017-03-10 09:24:06 +00:00
}
type Handler interface {
Run(taskModel models.TaskHost) (string, error)
2017-03-10 09:24:06 +00:00
}
2017-03-23 05:31:16 +00:00
// HTTP任务
2017-04-02 02:19:52 +00:00
type HTTPHandler struct{}
2017-03-10 09:24:06 +00:00
func (h *HTTPHandler) Run(taskModel models.TaskHost) (result string, err error) {
2017-04-02 02:38:49 +00:00
client := &http.Client{}
if taskModel.Timeout > 0 {
client.Timeout = time.Duration(taskModel.Timeout) * time.Second
}
req, err := http.NewRequest("POST", taskModel.Command, nil)
if err != nil {
2017-04-03 07:27:19 +00:00
logger.Error("创建HTTP请求错误-", err.Error())
2017-04-02 02:38:49 +00:00
return
}
req.Header.Set("Content-type", "application/x-www-form-urlencoded")
2017-04-07 01:22:00 +00:00
req.Header.Set("User-Agent", "golang/gocron")
2017-04-02 02:38:49 +00:00
resp, err := client.Do(req)
defer func() {
if resp != nil {
resp.Body.Close()
}
}()
if err != nil {
2017-04-03 07:27:19 +00:00
logger.Error("HTTP请求错误-", err.Error())
2017-04-02 02:38:49 +00:00
return
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
2017-04-03 07:27:19 +00:00
logger.Error("读取HTTP请求返回值失败-", err.Error())
2017-04-02 02:38:49 +00:00
}
return string(body), err
2017-03-10 09:24:06 +00:00
}
// SSH-command任务
2017-04-02 02:19:52 +00:00
type SSHCommandHandler struct{}
2017-03-10 09:24:06 +00:00
func (h *SSHCommandHandler) Run(taskModel models.TaskHost) (string, error) {
sshConfig := ssh.SSHConfig{
User: taskModel.Username,
Password: taskModel.Password,
Host: taskModel.Name,
Port: taskModel.Port,
ExecTimeout: taskModel.Timeout,
2017-04-02 02:38:49 +00:00
}
return ssh.Exec(sshConfig, taskModel.Command)
2017-03-23 05:31:16 +00:00
}
func createTaskLog(taskModel models.TaskHost) (int, error) {
2017-04-02 02:38:49 +00:00
taskLogModel := new(models.TaskLog)
taskLogModel.Name = taskModel.Task.Name
2017-04-06 06:40:48 +00:00
taskLogModel.Spec = taskModel.Spec
taskLogModel.Protocol = taskModel.Protocol
taskLogModel.Type = taskModel.Type
taskLogModel.Command = taskModel.Command
taskLogModel.Timeout = taskModel.Timeout
taskLogModel.Delay = taskModel.Delay
taskLogModel.Hostname = taskModel.Name
2017-04-02 02:38:49 +00:00
taskLogModel.StartTime = time.Now()
taskLogModel.Status = models.Running
insertId, err := taskLogModel.Create()
2017-03-23 05:31:16 +00:00
2017-04-02 02:38:49 +00:00
return insertId, err
2017-03-24 05:06:53 +00:00
}
2017-03-24 09:55:44 +00:00
func updateTaskLog(taskLogId int, result string, err error) (int64, error) {
2017-04-02 02:38:49 +00:00
taskLogModel := new(models.TaskLog)
var status models.Status
if err != nil {
result = err.Error() + " " + result
status = models.Failure
} else {
status = models.Finish
}
return taskLogModel.Update(taskLogId, models.CommonMap{
"status": status,
"result": result,
})
2017-03-23 05:31:16 +00:00
}
func createHandlerJob(taskModel models.TaskHost) cron.FuncJob {
2017-04-02 02:38:49 +00:00
var handler Handler = nil
switch taskModel.Protocol {
case models.HTTP:
handler = new(HTTPHandler)
case models.SSHCommand:
handler = new(SSHCommandHandler)
}
if handler == nil {
return nil
}
2017-04-02 02:38:49 +00:00
taskFunc := func() {
2017-04-06 06:40:48 +00:00
taskLogId, err := createTaskLog(taskModel)
2017-04-02 02:38:49 +00:00
if err != nil {
2017-04-03 07:27:19 +00:00
logger.Error("写入任务日志失败-", err)
2017-04-02 02:38:49 +00:00
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.Itoa(taskLogId) + "#尝试次数-" + strconv.Itoa(i + 1) + "#" + err.Error() + " " + result)
}
}
2017-04-02 02:38:49 +00:00
_, err = updateTaskLog(int(taskLogId), result, err)
if err != nil {
2017-04-03 07:27:19 +00:00
logger.Error("更新任务日志失败-", err)
2017-04-02 02:38:49 +00:00
}
}
return taskFunc
2017-04-02 02:19:52 +00:00
}