2017-03-10 09:24:06 +00:00
|
|
|
package service
|
|
|
|
|
|
|
|
import (
|
2017-04-02 02:38:49 +00:00
|
|
|
"github.com/ouqiang/cron-scheduler/models"
|
|
|
|
"github.com/ouqiang/cron-scheduler/modules/ansible"
|
|
|
|
"github.com/ouqiang/cron-scheduler/modules/crontask"
|
|
|
|
"github.com/robfig/cron"
|
|
|
|
"io/ioutil"
|
|
|
|
"net/http"
|
|
|
|
"strconv"
|
|
|
|
"time"
|
2017-04-03 07:27:19 +00:00
|
|
|
"github.com/ouqiang/cron-scheduler/modules/logger"
|
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
|
|
|
}
|
|
|
|
|
|
|
|
// 添加任务
|
2017-04-02 02:19:52 +00:00
|
|
|
func (task *Task) Add(taskModel models.Task) {
|
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 {
|
|
|
|
err := crontask.DefaultCronTask.AddOrReplace(strconv.Itoa(taskModel.Id), taskModel.Spec, taskFunc)
|
|
|
|
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 {
|
|
|
|
// 延时任务
|
2017-04-03 10:04:49 +00:00
|
|
|
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 {
|
2017-04-02 02:38:49 +00:00
|
|
|
Run(taskModel models.Task) (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
|
|
|
|
2017-04-02 02:19:52 +00:00
|
|
|
func (h *HTTPHandler) Run(taskModel models.Task) (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")
|
|
|
|
req.Header.Set("User-Agent", "golang-cron/scheduler")
|
|
|
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2017-04-01 12:28:30 +00:00
|
|
|
// SSH-command任务
|
2017-04-02 02:19:52 +00:00
|
|
|
type SSHCommandHandler struct{}
|
2017-03-10 09:24:06 +00:00
|
|
|
|
2017-04-02 02:19:52 +00:00
|
|
|
func (ssh *SSHCommandHandler) Run(taskModel models.Task) (string, error) {
|
2017-04-02 02:38:49 +00:00
|
|
|
return execSSHHandler("shell", taskModel)
|
2017-04-01 12:28:30 +00:00
|
|
|
}
|
2017-03-24 09:55:44 +00:00
|
|
|
|
2017-04-01 12:28:30 +00:00
|
|
|
// SSH-script任务
|
2017-04-02 02:19:52 +00:00
|
|
|
type SSHScriptHandler struct{}
|
2017-04-01 12:28:30 +00:00
|
|
|
|
2017-04-02 02:19:52 +00:00
|
|
|
func (ssh *SSHScriptHandler) Run(taskModel models.Task) (string, error) {
|
2017-04-02 02:38:49 +00:00
|
|
|
return execSSHHandler("script", taskModel)
|
2017-04-01 12:28:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// SSH任务
|
2017-04-02 02:19:52 +00:00
|
|
|
func execSSHHandler(module string, taskModel models.Task) (string, error) {
|
2017-04-02 02:38:49 +00:00
|
|
|
var args []string = []string{taskModel.Command}
|
|
|
|
if taskModel.Timeout > 0 {
|
|
|
|
// -B 异步执行超时时间, -P 轮询时间
|
|
|
|
args = append(args, "-B", strconv.Itoa(taskModel.Timeout), "-P", "10")
|
|
|
|
}
|
|
|
|
if module == "shell" {
|
|
|
|
return ansible.Shell(taskModel.SshHosts, ansible.DefaultHosts.GetFilename(), args...)
|
|
|
|
}
|
|
|
|
if module == "script" {
|
|
|
|
return ansible.Script(taskModel.SshHosts, ansible.DefaultHosts.GetFilename(), args...)
|
|
|
|
}
|
|
|
|
|
|
|
|
return "", nil
|
2017-03-23 05:31:16 +00:00
|
|
|
}
|
|
|
|
|
2017-03-24 09:55:44 +00:00
|
|
|
func createTaskLog(taskId int) (int, error) {
|
2017-04-02 02:38:49 +00:00
|
|
|
taskLogModel := new(models.TaskLog)
|
|
|
|
taskLogModel.TaskId = taskId
|
|
|
|
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
|
|
|
|
|
|
|
}
|
|
|
|
|
2017-03-24 05:06:53 +00:00
|
|
|
func createHandlerJob(taskModel models.Task) 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)
|
|
|
|
case models.SSHScript:
|
|
|
|
handler = new(SSHScriptHandler)
|
|
|
|
}
|
|
|
|
taskFunc := func() {
|
|
|
|
taskLogId, err := createTaskLog(taskModel.Id)
|
|
|
|
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 执行失败
|
|
|
|
result, err := handler.Run(taskModel)
|
|
|
|
_, 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
|
|
|
}
|