From 4d8e6475237622b8516816caf3221315b075722e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=83=9D=E5=A4=A7=E5=85=A8?= Date: Fri, 30 Jun 2017 15:49:33 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E4=BB=BB=E5=8A=A1=E5=88=86?= =?UTF-8?q?=E7=B1=BB=EF=BC=8C=E6=9D=80=E6=AD=BB=E8=BF=9B=E7=A8=8B=E7=AD=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 常驻任务和定时任务 常驻任务暂停时杀死进程 --- controllers/task.go | 29 +++++++++++++++++++++++++++-- crons/cron.go | 1 + jobs/init.go | 22 ++++++++++++++++++++++ jobs/job.go | 7 ++++++- kill_process.sh | 14 ++++++++++++++ main.go | 9 +++++++-- models/task.go | 5 +++++ views/task/add.html | 42 +++++++++++++++++++++++++++++++++--------- views/task/edit.html | 25 +++++++++++++++++++++++++ views/task/list.html | 23 ++++++++++++++++++++--- 10 files changed, 160 insertions(+), 17 deletions(-) create mode 100755 kill_process.sh diff --git a/controllers/task.go b/controllers/task.go index 2c982d0..d8f6c5e 100644 --- a/controllers/task.go +++ b/controllers/task.go @@ -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) +} diff --git a/crons/cron.go b/crons/cron.go index d53bee9..c5cb065 100644 --- a/crons/cron.go +++ b/crons/cron.go @@ -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() } diff --git a/jobs/init.go b/jobs/init.go index 54850cb..4024cd6 100644 --- a/jobs/init.go +++ b/jobs/init.go @@ -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 +// } +//} diff --git a/jobs/job.go b/jobs/job.go index 82f4a61..00f402b 100644 --- a/jobs/job.go +++ b/jobs/job.go @@ -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 diff --git a/kill_process.sh b/kill_process.sh new file mode 100755 index 0000000..4610ae0 --- /dev/null +++ b/kill_process.sh @@ -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 \ No newline at end of file diff --git a/main.go b/main.go index 28e78db..d45569c 100644 --- a/main.go +++ b/main.go @@ -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() -} \ No newline at end of file +} + + diff --git a/models/task.go b/models/task.go index 3be97af..b56e343 100644 --- a/models/task.go +++ b/models/task.go @@ -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字段不能为空") } diff --git a/views/task/add.html b/views/task/add.html index 26d63b0..76cf7f1 100644 --- a/views/task/add.html +++ b/views/task/add.html @@ -23,17 +23,27 @@
- +
- + * +
+
+ +
+ +
+ +
+
+
- +
@@ -66,7 +76,22 @@
- 设为“是”的话,如果该任务在上一个时间点还没执行完,则略过不执行 + 设为“是”的话,如果该任务在上一个时间点还没执行完,则略过不执行 +
+
+ +
+ +
+ + +
+
+
@@ -76,17 +101,16 @@
- 参见使用帮助 + 支持秒级定时,详见《参见使用帮助》
- +
-
@@ -94,10 +118,10 @@
- +
- 单位秒,不设置的话,默认超时时间为1天 +
diff --git a/views/task/edit.html b/views/task/edit.html index 0182622..c7e10c3 100644 --- a/views/task/edit.html +++ b/views/task/edit.html @@ -30,6 +30,16 @@ +
+ +
+ +
+
+ +
+
+
@@ -70,6 +80,21 @@
+
+ +
+ + +
+
+ +
+
+
diff --git a/views/task/list.html b/views/task/list.html index c972ac0..ef2b1fd 100644 --- a/views/task/list.html +++ b/views/task/list.html @@ -61,6 +61,8 @@ ID 任务名称 时间表达式 + 任务说明 + 任务类型 上次执行时间 下次执行时间 操作 @@ -77,9 +79,19 @@ {{else}} {{end}} +   {{$v.name}} {{$v.cron_spec}} + {{$v.description}} + + {{if eq $v.task_type 0}} + 定时任务 + {{else}} + 常驻任务 + {{end}} + + {{$v.prev_time}} {{$v.next_time}} @@ -95,9 +107,14 @@ 编辑 - + + {{if eq $v.task_type 0}} + 执行 - + + {{end}} + + 日志 @@ -108,7 +125,7 @@ - +
{{str2html .pageBar}}