新增任务分类,杀死进程等
常驻任务和定时任务 常驻任务暂停时杀死进程
This commit is contained in:
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
|
||||
22
jobs/init.go
22
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
|
||||
// }
|
||||
//}
|
||||
|
||||
@@ -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
14
kill_process.sh
Executable 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
|
||||
9
main.go
9
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()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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字段不能为空")
|
||||
}
|
||||
|
||||
@@ -23,17 +23,27 @@
|
||||
<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;">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<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>
|
||||
|
||||
|
||||
@@ -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" >
|
||||
|
||||
@@ -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}}
|
||||
|
||||
{{$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>
|
||||
<a class="btn btn-info btn-run btn-xs" href="{{urlfor "TaskController.Run"}}?id={{$v.id}}">
|
||||
|
||||
{{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>
|
||||
</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>
|
||||
|
||||
Reference in New Issue
Block a user