新增任务分类,杀死进程等

常驻任务和定时任务
常驻任务暂停时杀死进程
This commit is contained in:
郝大全
2017-06-30 15:49:33 +08:00
parent fbd1f9e1a7
commit 4d8e647523
10 changed files with 160 additions and 17 deletions

View File

@@ -16,6 +16,9 @@ import (
"strconv"
"strings"
"time"
"os/exec"
"log"
"os"
)
type TaskController struct {
@@ -44,6 +47,8 @@ func (this *TaskController) List() {
row["status"] = v.Status
row["description"] = v.Description
row["task_type"] = v.TaskType
e := jobs.GetEntryById(v.Id)
if e != nil {
row["next_time"] = beego.Date(e.Next, "Y-m-d H:i:s")
@@ -85,6 +90,8 @@ func (this *TaskController) Add() {
task.UserId = this.userId
task.GroupId, _ = this.GetInt("group_id")
task.TaskName = strings.TrimSpace(this.GetString("task_name"))
task.TaskTag = strings.TrimSpace(this.GetString("task_tag"))
task.TaskType, _ = this.GetInt("task_type")
task.Description = strings.TrimSpace(this.GetString("description"))
task.Concurrent, _ = this.GetInt("concurrent")
task.CronSpec = strings.TrimSpace(this.GetString("cron_spec"))
@@ -92,6 +99,7 @@ func (this *TaskController) Add() {
task.Notify, _ = this.GetInt("notify")
task.Timeout, _ = this.GetInt("timeout")
notifyEmail := strings.TrimSpace(this.GetString("notify_email"))
if notifyEmail != "" {
emailList := make([]string, 0)
@@ -138,6 +146,8 @@ func (this *TaskController) Edit() {
if this.isPost() {
task.TaskName = strings.TrimSpace(this.GetString("task_name"))
task.TaskTag = strings.TrimSpace(this.GetString("task_tag"))
task.TaskType, _ = this.GetInt("task_type")
task.Description = strings.TrimSpace(this.GetString("description"))
task.GroupId, _ = this.GetInt("group_id")
task.Concurrent, _ = this.GetInt("concurrent")
@@ -290,10 +300,15 @@ func (this *TaskController) Batch() {
}
case "pause":
jobs.RemoveJob(id)
if task, err := models.TaskGetById(id); err == nil {
task.Status = 0
task.Update()
if task.TaskType==1 {
stopProcess(task.TaskTag)//杀死进程
}
}
case "delete":
models.TaskDel(id)
models.TaskLogDelByTaskId(id)
@@ -343,6 +358,10 @@ func (this *TaskController) Pause() {
task.Status = 0
task.Update()
//如果是常驻进程kill
if task.TaskType==1 {
stopProcess(task.TaskTag)
}
refer := this.Ctx.Request.Referer()
if refer == "" {
refer = beego.URLFor("TaskController.List")
@@ -363,8 +382,14 @@ func (this *TaskController) Run() {
if err != nil {
this.showMsg(err.Error())
}
job.Run()
this.redirect(beego.URLFor("TaskController.ViewLog", "id", job.GetLogId()))
}
//杀死进程
func stopProcess(taskTag string) {
ppPath,_ := os.Getwd() //项目根目录
shellFile := ppPath+"/kill_process.sh "
cmd:= exec.Command("sh","-c", shellFile + taskTag)
out,err:=cmd.Output()
log.Printf("==========================out:%s err:%s",out,err)
}

View File

@@ -134,6 +134,7 @@ func (c *Cron) Entries() []*Entry {
// Start the cron scheduler in its own go-routine.
func (c *Cron) Start() {
c.running = true
go c.run()
}

View File

@@ -48,3 +48,25 @@ func runCmdWithTimeout(cmd *exec.Cmd, timeout time.Duration) (error, bool) {
return err, false
}
}
//func stopCmd(cmd *exec.Cmd) (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
// }
//}

View File

@@ -74,7 +74,8 @@ func NewCommandJob(id int, name string, command string) *Job {
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 := exec.Command("/bin/bash", "-c", command)
cmd := exec.Command("sh", "-c", command)
cmd.Stdout = bufOut
cmd.Stderr = bufErr
cmd.Start()
@@ -134,6 +135,10 @@ func (j *Job) Run() {
}
cmdOut, cmdErr, err, isTimeout := j.runFunc(timeout)
if err.Error() == "signal: killed" {
cmdOut += err.Error()
err = nil
}
ut := time.Now().Sub(t) / time.Millisecond

14
kill_process.sh Executable file
View File

@@ -0,0 +1,14 @@
#!/bin/bash
# @Author: haodaquan
# @Date: 2017-06-29 17:44:45
# @Last Modified by: haodaquan
# @Last Modified time: 2017-06-29 17:44:45
process_tag=$1
arrproc=$(ps -ef | grep "${process_tag}" | grep -v grep | awk '{print $2}')
for p in $arrproc; do
if [ "${p}"=~^[0-9]+$ ]; then
kill -9 "${p}"
echo `date "+%Y/%m/%d %H:%M:%S> "` ${p} " 进程已杀死!"
fi
done

View File

@@ -5,6 +5,7 @@ import (
_ "github.com/george518/PPGo_Job/mail"
"github.com/george518/PPGo_Job/models"
_ "github.com/george518/PPGo_Job/routers"
"os"
)
const (
@@ -13,10 +14,14 @@ const (
func init() {
//初始化数据模型
beego.LoadAppConfig("ini", "src/github.com/george518/PPGo_Job/conf/app.conf")
PP_PATH,_ := os.Getwd()
CONFIG := PP_PATH + "/config/app.conf"
beego.LoadAppConfig("ini", CONFIG)
models.Init()
}
func main() {
beego.Run()
}

View File

@@ -25,6 +25,7 @@ type Task struct {
GroupId int
TaskName string
TaskType int
TaskTag string
Description string
CronSpec string
Concurrent int
@@ -53,6 +54,10 @@ func TaskAdd(task *Task) (int64, error) {
if task.TaskName == "" {
return 0, fmt.Errorf("TaskName字段不能为空")
}
if task.TaskTag == "" {
return 0, fmt.Errorf("TaskTag字段不能为空")
}
if task.CronSpec == "" {
return 0, fmt.Errorf("CronSpec字段不能为空")
}

View File

@@ -23,7 +23,17 @@
<div class="form-group" style="margin-top: 15px">
<label class="col-sm-3 control-label" for="task_name">任务名称</label>
<div class="col-sm-3" >
<input type="text" class="form-control input-sm" placeholder="" name="task_name" value="" required />
<input type="text" class="form-control input-sm" placeholder="不需要带分组名称" name="task_name" value="" required />
</div>
<div class="col-sm-6" style="padding-top:5px;">
<i style="color:red">*</i>
</div>
</div>
<div class="form-group" style="margin-top: 15px">
<label class="col-sm-3 control-label" for="task_tag">进程标志</label>
<div class="col-sm-3" >
<input type="text" class="form-control input-sm" placeholder="用于查找进程,一般为方法名称" name="task_tag" value="" required />
</div>
<div class="col-sm-6" style="padding-top:5px;">
@@ -33,7 +43,7 @@
<div class="form-group" style="margin-top: 15px">
<label class="col-sm-3 control-label" for="description">任务说明</label>
<div class="col-sm-5" >
<textarea name="description" class="form-control" id="description" rows="3"></textarea>
<textarea name="description" class="form-control" id="description" rows="3" placeholder="注明执行周期"></textarea>
</div>
<div class="col-sm-4" style="padding-top:5px;">
@@ -66,7 +76,22 @@
</label>
</div>
<div class="col-sm-6" style="padding-top:5px;">
<i>设为“是”的话,如果该任务在上一个时间点还没执行完,则略过不执行</i>
<i style="font-size: 12px">设为“是”的话,如果该任务在上一个时间点还没执行完,则略过不执行</i>
</div>
</div>
<div class="form-group" style="margin-top: 15px">
<label class="col-sm-3 control-label" for="task_type">任务类型</label>
<div class="col-sm-3" >
<label class="radio-inline">
<input type="radio" name="task_type" value="0" checked> 定时任务
</label>
<label class="radio-inline">
<input type="radio" name="task_type" value="1"> 常驻任务
</label>
</div>
<div class="col-sm-6" style="padding-top:5px;">
<i></i>
</div>
</div>
@@ -76,17 +101,16 @@
<input type="text" class="form-control input-sm" placeholder="" name="cron_spec" value="" />
</div>
<div class="col-sm-6" style="padding-top:5px;">
<a href="{{urlfor "HelpController.Index"}}" target="_blank">参见使用帮助</a>
<a href="{{urlfor "HelpController.Index"}}" target="_blank"><i style="font-size: 12px">支持秒级定时,详见《参见使用帮助》</i></a>
</div>
</div>
<div class="form-group" style="margin-top: 15px">
<label class="col-sm-3 control-label" for="command">命令脚本</label>
<div class="col-sm-5" >
<textarea name="command" class="form-control" id="command" rows="3"></textarea>
<textarea name="command" class="form-control" id="command" rows="3" placeholder="支持bash命令和shell文件"></textarea>
</div>
<div class="col-sm-4" style="padding-top:5px;">
</div>
</div>
@@ -94,10 +118,10 @@
<div class="form-group" style="margin-top: 15px">
<label class="col-sm-3 control-label" for="timeout">超时设置</label>
<div class="col-sm-3" >
<input type="text" class="form-control input-sm" placeholder="秒" name="timeout" value="" />
<input type="text" class="form-control input-sm" placeholder="秒,默认一天" name="timeout" value="" />
</div>
<div class="col-sm-6" style="padding-top:5px;">
单位秒不设置的话默认超时时间为1天
</div>
</div>

View File

@@ -30,6 +30,16 @@
</div>
</div>
<div class="form-group" style="margin-top: 15px">
<label class="col-sm-3 control-label" for="task_tag">进程标志</label>
<div class="col-sm-3" >
<input type="text" class="form-control input-sm" placeholder="用于查找进程,一般为方法名称" name="task_tag" value="{{.task.TaskTag}}" required />
</div>
<div class="col-sm-6" style="padding-top:5px;">
</div>
</div>
<div class="form-group" style="margin-top: 15px">
<label class="col-sm-3 control-label" for="task_name">任务说明</label>
<div class="col-sm-5" >
@@ -70,6 +80,21 @@
</div>
</div>
<div class="form-group" style="margin-top: 15px">
<label class="col-sm-3 control-label" for="task_type">任务类型</label>
<div class="col-sm-3" >
<label class="radio-inline">
<input type="radio" name="task_type" value="0" {{if eq .task.TaskType 0}}checked{{end}}> 定时任务
</label>
<label class="radio-inline">
<input type="radio" name="task_type" value="1" {{if eq .task.TaskType 1}}checked{{end}}> 常驻任务
</label>
</div>
<div class="col-sm-6" style="padding-top:5px;">
<i></i>
</div>
</div>
<div class="form-group" style="margin-top: 15px">
<label class="col-sm-3 control-label" for="cron_spec">时间表达式</label>
<div class="col-sm-3" >

View File

@@ -61,6 +61,8 @@
<td>ID</td>
<td width="20%">任务名称</td>
<td>时间表达式</td>
<td>任务说明</td>
<td>任务类型</td>
<td>上次执行时间</td>
<td>下次执行时间</td>
<td width="25%">操作</td>
@@ -77,9 +79,19 @@
{{else}}
<span class="glyphicon glyphicon-ok-sign brand-success " aria-hidden="true"></span>
{{end}}
&nbsp;
{{$v.name}}
</td>
<td> {{$v.cron_spec}} </td>
<td> {{$v.description}} </td>
<td>
{{if eq $v.task_type 0}}
定时任务
{{else}}
<i style="color:red">常驻任务</i>
{{end}}
</td>
<td> {{$v.prev_time}} </td>
<td> {{$v.next_time}} </td>
<td>
@@ -95,9 +107,14 @@
<a class="btn btn-info btn-xs" href="{{urlfor "TaskController.Edit"}}?id={{$v.id}}">
<span class="glyphicon glyphicon-edit" aria-hidden="true"></span> 编辑
</a>
{{if eq $v.task_type 0}}
<a class="btn btn-info btn-run btn-xs" href="{{urlfor "TaskController.Run"}}?id={{$v.id}}">
<span class="glyphicon glyphicon-flash" aria-hidden="true"></span> 执行
</a>
{{end}}
<a class="btn btn-info btn-xs" href="{{urlfor "TaskController.Logs"}}?id={{$v.id}}">
<span class="glyphicon glyphicon-file" aria-hidden="true"></span> 日志
</a>
@@ -108,7 +125,7 @@
</tbody>
<tfoot>
<tr>
<td colspan="7">
<td colspan="9">
<div class="pull-right">
{{str2html .pageBar}}
</div>