Skip to content

Commit

Permalink
增加超时设置
Browse files Browse the repository at this point in the history
  • Loading branch information
lisijie committed Mar 15, 2016
1 parent 063015b commit 5c5be7f
Show file tree
Hide file tree
Showing 9 changed files with 99 additions and 25 deletions.
4 changes: 2 additions & 2 deletions app/controllers/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func (this *MainController) Index() {
}

// 最近执行失败的日志
logs, _ = models.TaskLogGetList(1, 20, "status", -1)
logs, _ = models.TaskLogGetList(1, 20, "status__lt", 0)
errLogs := make([]map[string]interface{}, len(logs))
for k, v := range logs {
task, err := models.TaskGetById(v.TaskId)
Expand All @@ -67,7 +67,7 @@ func (this *MainController) Index() {
row["start_time"] = beego.Date(time.Unix(v.CreateTime, 0), "Y-m-d H:i:s")
row["process_time"] = float64(v.ProcessTime) / 1000
row["ouput_size"] = libs.SizeFormat(float64(len(v.Output)))
row["output"] = beego.Substr(v.Output, 0, 100)
row["error"] = beego.Substr(v.Error, 0, 100)
row["status"] = v.Status
errLogs[k] = row
}
Expand Down
2 changes: 2 additions & 0 deletions app/controllers/task.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ func (this *TaskController) Add() {
task.CronSpec = strings.TrimSpace(this.GetString("cron_spec"))
task.Command = strings.TrimSpace(this.GetString("command"))
task.Notify, _ = this.GetInt("notify")
task.Timeout, _ = this.GetInt("timeout")

notifyEmail := strings.TrimSpace(this.GetString("notify_email"))
if notifyEmail != "" {
Expand Down Expand Up @@ -136,6 +137,7 @@ func (this *TaskController) Edit() {
task.CronSpec = strings.TrimSpace(this.GetString("cron_spec"))
task.Command = strings.TrimSpace(this.GetString("command"))
task.Notify, _ = this.GetInt("notify")
task.Timeout, _ = this.GetInt("timeout")

notifyEmail := strings.TrimSpace(this.GetString("notify_email"))
if notifyEmail != "" {
Expand Down
25 changes: 25 additions & 0 deletions app/jobs/init.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package jobs

import (
"fmt"
"github.com/astaxie/beego"
"github.com/lisijie/webcron/app/models"
"os/exec"
"time"
)

func InitJobs() {
Expand All @@ -16,3 +19,25 @@ func InitJobs() {
AddJob(task.CronSpec, job)
}
}

func runCmdWithTimeout(cmd *exec.Cmd, timeout time.Duration) (error, bool) {
done := make(chan error)
go func() {
done <- cmd.Wait()
}()

var err error
select {
case <-time.After(timeout):
beego.Warn(fmt.Sprintf("任务执行时间超过%d秒,进程将被强制杀掉: %d", int(timeout/time.Second), cmd.Process.Pid))
go func() {
<-done // 读出上面的goroutine数据,避免阻塞导致无法退出
}()
if err = cmd.Process.Kill(); err != nil {
beego.Error(fmt.Sprintf("进程无法杀掉: %d, 错误信息: %s", cmd.Process.Pid, err))
}
return err, true
case err = <-done:
return err, false
}
}
49 changes: 30 additions & 19 deletions app/jobs/job.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ type Job struct {
logId int64
name string
task *models.Task
runFunc func() ([]byte, []byte, error)
runFunc func(time.Duration) (string, string, error, bool)
running sync.Mutex
status int
Concurrent bool
Expand All @@ -66,15 +66,16 @@ func NewCommandJob(id int, name string, command string) *Job {
id: id,
name: name,
}
job.runFunc = func() ([]byte, []byte, error) {
job.runFunc = func(timeout time.Duration) (string, string, error, bool) {
bufOut := new(bytes.Buffer)
bufErr := new(bytes.Buffer)
cmd := exec.Command("/bin/bash", "-c", command)
cmd.Stdout = bufOut
cmd.Stderr = bufErr
err := cmd.Run()
cmd.Start()
err, isTimeout := runCmdWithTimeout(cmd, timeout)

return bufOut.Bytes(), bufErr.Bytes(), err
return bufOut.String(), bufErr.String(), err, isTimeout
}
return job
}
Expand Down Expand Up @@ -121,20 +122,29 @@ func (j *Job) Run() {
j.status = 0
}()

bout, berr, err := j.runFunc()
timeout := time.Duration(time.Hour * 24)
if j.task.Timeout > 0 {
timeout = time.Second * time.Duration(j.task.Timeout)
}

cmdOut, cmdErr, err, isTimeout := j.runFunc(timeout)

ut := time.Now().Sub(t) / time.Millisecond

// 插入日志
log := new(models.TaskLog)
log.TaskId = j.id
log.Output = string(bout)
log.Error = string(berr)
log.Output = cmdOut
log.Error = cmdErr
log.ProcessTime = int(ut)
log.CreateTime = t.Unix()
if err != nil {
log.Status = -1
log.Error = err.Error() + ":" + string(berr)

if isTimeout {
log.Status = models.TASK_TIMEOUT
log.Error = fmt.Sprintf("任务执行超过 %d 秒\n----------------------\n%s\n", int(timeout/time.Second), cmdErr)
} else if err != nil {
log.Status = models.TASK_ERROR
log.Error = err.Error() + ":" + cmdErr
}
j.logId, _ = models.TaskLogAdd(log)

Expand All @@ -150,24 +160,25 @@ func (j *Job) Run() {
return
}

title := ""
if err != nil {
title = fmt.Sprintf("任务执行结果通知 #%d: %s", j.task.Id, "失败")
} else {
title = fmt.Sprintf("任务执行结果通知 #%d: %s", j.task.Id, "成功")
}
var title string

data := make(map[string]interface{})
data["task_id"] = j.task.Id
data["username"] = user.UserName
data["task_name"] = j.task.TaskName
data["start_time"] = beego.Date(t, "Y-m-d H:i:s")
data["process_time"] = float64(ut) / 1000
if err != nil {
data["output"] = cmdOut

if isTimeout {
title = fmt.Sprintf("任务执行结果通知 #%d: %s", j.task.Id, "超时")
data["status"] = fmt.Sprintf("超时(%d秒)", int(timeout/time.Second))
} else if err != nil {
title = fmt.Sprintf("任务执行结果通知 #%d: %s", j.task.Id, "失败")
data["status"] = "失败(" + err.Error() + ")"
data["output"] = string(berr)
} else {
title = fmt.Sprintf("任务执行结果通知 #%d: %s", j.task.Id, "成功")
data["status"] = "成功"
data["output"] = string(bout)
}

content := new(bytes.Buffer)
Expand Down
6 changes: 6 additions & 0 deletions app/models/task.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ import (
"time"
)

const (
TASK_SUCCESS = 0 // 任务执行成功
TASK_ERROR = -1 // 任务执行出错
TASK_TIMEOUT = -2 // 任务执行超时
)

type Task struct {
Id int
UserId int
Expand Down
16 changes: 14 additions & 2 deletions views/main/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,13 @@ <h3>执行失败的任务</h3>
<div class="news-item-detail">
<a href="{{urlfor "TaskController.ViewLog" "id" $v.id}}" class="news-item-title">{{$v.task_name}} # {{$v.id}}</a>
<p class="news-item-preview">
开始时间:{{$v.start_time}} | 执行时间:{{$v.process_time}}秒 | 输出:{{$v.ouput_size}} | 状态:{{if eq $v.status 0}}正常{{else}}<span style="color:red">异常</span>{{end}}
开始时间:{{$v.start_time}} | 执行时间:{{$v.process_time}}秒 | 输出:{{$v.ouput_size}} | 状态:{{if eq $v.status 0}}
正常
{{else if eq $v.status -1}}
<span style="color:red">异常</span>
{{else}}
<span style="color:red">超时</span>
{{end}}
</p>
<blockquote>{{$v.error}}</blockquote>
</div>
Expand Down Expand Up @@ -71,7 +77,13 @@ <h3>最近执行任务</h3>
<div class="news-item-detail">
<a href="{{urlfor "TaskController.ViewLog" "id" $v.id}}" class="news-item-title">{{$v.task_name}} # {{$v.id}}</a>
<p class="news-item-preview">
开始时间:{{$v.start_time}} | 执行时间:{{$v.process_time}}秒 | 输出:{{$v.ouput_size}} | 状态:{{if eq $v.status 0}}正常{{else}}<span style="color:red">异常</span>{{end}}
开始时间:{{$v.start_time}} | 执行时间:{{$v.process_time}}秒 | 输出:{{$v.ouput_size}} | 状态:{{if eq $v.status 0}}
正常
{{else if eq $v.status -1}}
<span style="color:red">异常</span>
{{else}}
<span style="color:red">超时</span>
{{end}}
</p>
<blockquote>{{$v.output}}</blockquote>
</div>
Expand Down
8 changes: 8 additions & 0 deletions views/task/add.html
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,14 @@ <h3>添加任务</h3>
</div> <!-- /controls -->
</div> <!-- /control-group -->

<div class="control-group">
<label class="control-label" for="timeout">超时设置</label>
<div class="controls">
<input type="text" name="timeout" class="span1" id="timeout" value="0">
<span class="help-block">不设置的话,默认超时时间为1天</span>
</div> <!-- /controls -->
</div> <!-- /control-group -->

<div class="control-group">
<label class="control-label">邮件通知</label>
<div class="controls">
Expand Down
8 changes: 8 additions & 0 deletions views/task/edit.html
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,14 @@ <h3>编辑任务</h3>
</div> <!-- /controls -->
</div> <!-- /control-group -->

<div class="control-group">
<label class="control-label" for="timeout">超时设置</label>
<div class="controls">
<input type="text" name="timeout" class="span1" id="timeout" value="{{.task.Timeout}}">
<span class="help-block">不设置的话,默认超时时间为1天</span>
</div> <!-- /controls -->
</div> <!-- /control-group -->

<div class="control-group">
<label class="control-label">邮件通知</label>
<div class="controls">
Expand Down
6 changes: 4 additions & 2 deletions views/task/logs.html
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,10 @@ <h3>{{.task.TaskName}} (#{{.task.Id}})</h3>
<td>
{{if eq $v.status 0}}
<span class="icon-ok-sign" style="color:green"> 正常</span>
{{else}}
<span class=" icon-remove-sign" style="color:#ff7f74"> 异常</span>
{{else if eq $v.status -1}}
<span class=" icon-remove-sign" style="color:#ff7f74"> 出错</span>
{{else if eq $v.status -2}}
<span class=" icon-remove-sign" style="color:#ff7f74"> 超时</span>
{{end}}
</td>
<td>
Expand Down

0 comments on commit 5c5be7f

Please sign in to comment.