新增任务复制功能
This commit is contained in:
@@ -8,14 +8,15 @@
|
|||||||
package controllers
|
package controllers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/astaxie/beego"
|
"github.com/astaxie/beego"
|
||||||
crons "github.com/george518/PPGo_Job/crons"
|
crons "github.com/george518/PPGo_Job/crons"
|
||||||
"github.com/george518/PPGo_Job/jobs"
|
"github.com/george518/PPGo_Job/jobs"
|
||||||
"github.com/george518/PPGo_Job/libs"
|
"github.com/george518/PPGo_Job/libs"
|
||||||
"github.com/george518/PPGo_Job/models"
|
"github.com/george518/PPGo_Job/models"
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type TaskController struct {
|
type TaskController struct {
|
||||||
@@ -44,7 +45,6 @@ func (this *TaskController) List() {
|
|||||||
|
|
||||||
list := make([]map[string]interface{}, len(result))
|
list := make([]map[string]interface{}, len(result))
|
||||||
|
|
||||||
|
|
||||||
// 分组列表
|
// 分组列表
|
||||||
groups, _ := models.TaskGroupGetList(1, 100)
|
groups, _ := models.TaskGroupGetList(1, 100)
|
||||||
groups_map := make(map[int]string)
|
groups_map := make(map[int]string)
|
||||||
@@ -183,6 +183,26 @@ func (this *TaskController) Edit() {
|
|||||||
this.display()
|
this.display()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//复制任务
|
||||||
|
func (this *TaskController) Copy() {
|
||||||
|
|
||||||
|
id, _ := this.GetInt("id")
|
||||||
|
task, err := models.TaskGetById(id)
|
||||||
|
if err != nil {
|
||||||
|
this.showMsg(err.Error())
|
||||||
|
}
|
||||||
|
// 分组列表
|
||||||
|
groups, _ := models.TaskGroupGetList(1, 100)
|
||||||
|
this.Data["groups"] = groups
|
||||||
|
//服务器分组
|
||||||
|
servers, _ := models.TaskServerGetList(1, 100)
|
||||||
|
this.Data["servers"] = servers
|
||||||
|
|
||||||
|
this.Data["task"] = task
|
||||||
|
this.Data["pageTitle"] = "复制任务"
|
||||||
|
this.display()
|
||||||
|
}
|
||||||
|
|
||||||
// 任务执行日志列表
|
// 任务执行日志列表
|
||||||
func (this *TaskController) Logs() {
|
func (this *TaskController) Logs() {
|
||||||
taskId, _ := this.GetInt("id")
|
taskId, _ := this.GetInt("id")
|
||||||
|
|||||||
19
jobs/job.go
19
jobs/job.go
@@ -10,18 +10,17 @@ package jobs
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/astaxie/beego"
|
"io/ioutil"
|
||||||
"github.com/george518/PPGo_Job/models"
|
"net"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
"time"
|
"time"
|
||||||
"io/ioutil"
|
|
||||||
|
"github.com/astaxie/beego"
|
||||||
|
"github.com/george518/PPGo_Job/models"
|
||||||
"golang.org/x/crypto/ssh"
|
"golang.org/x/crypto/ssh"
|
||||||
"net"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
type Job struct {
|
type Job struct {
|
||||||
id int // 任务ID
|
id int // 任务ID
|
||||||
logId int64 // 日志记录ID
|
logId int64 // 日志记录ID
|
||||||
@@ -32,13 +31,12 @@ type Job struct {
|
|||||||
Concurrent bool // 同一个任务是否允许并行执行
|
Concurrent bool // 同一个任务是否允许并行执行
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func NewJobFromTask(task *models.Task) (*Job, error) {
|
func NewJobFromTask(task *models.Task) (*Job, error) {
|
||||||
if task.Id < 1 {
|
if task.Id < 1 {
|
||||||
return nil, fmt.Errorf("ToJob: 缺少id")
|
return nil, fmt.Errorf("ToJob: 缺少id")
|
||||||
}
|
}
|
||||||
//本地程序执行
|
//本地程序执行
|
||||||
if(task.ServerId==0) {
|
if task.ServerId == 0 {
|
||||||
job := NewCommandJob(task.Id, task.TaskName, task.Command)
|
job := NewCommandJob(task.Id, task.TaskName, task.Command)
|
||||||
job.task = task
|
job.task = task
|
||||||
job.Concurrent = task.Concurrent == 1
|
job.Concurrent = task.Concurrent == 1
|
||||||
@@ -46,7 +44,7 @@ func NewJobFromTask(task *models.Task) (*Job, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
server, _ := models.TaskServerGetById(task.ServerId)
|
server, _ := models.TaskServerGetById(task.ServerId)
|
||||||
if(server.Type==0){
|
if server.Type == 0 {
|
||||||
//密码验证登录服务器
|
//密码验证登录服务器
|
||||||
job := RemoteCommandJobByPassword(task.Id, task.TaskName, task.Command, server)
|
job := RemoteCommandJobByPassword(task.Id, task.TaskName, task.Command, server)
|
||||||
job.task = task
|
job.task = task
|
||||||
@@ -80,6 +78,7 @@ func NewCommandJob(id int, name string, command string) *Job {
|
|||||||
}
|
}
|
||||||
return job
|
return job
|
||||||
}
|
}
|
||||||
|
|
||||||
//远程执行任务 密钥验证
|
//远程执行任务 密钥验证
|
||||||
func RemoteCommandJob(id int, name string, command string, servers *models.TaskServer) *Job {
|
func RemoteCommandJob(id int, name string, command string, servers *models.TaskServer) *Job {
|
||||||
job := &Job{
|
job := &Job{
|
||||||
@@ -179,7 +178,6 @@ func RemoteCommandJobByPassword(id int,name string,command string,servers *model
|
|||||||
return "", "", err, false
|
return "", "", err, false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
var c bytes.Buffer
|
var c bytes.Buffer
|
||||||
session.Stdout = &b
|
session.Stdout = &b
|
||||||
@@ -196,7 +194,6 @@ func RemoteCommandJobByPassword(id int,name string,command string,servers *model
|
|||||||
return job
|
return job
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (j *Job) Status() int {
|
func (j *Job) Status() int {
|
||||||
return j.status
|
return j.status
|
||||||
}
|
}
|
||||||
|
|||||||
144
views/task/copy.html
Normal file
144
views/task/copy.html
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
<!-- 新增任务 -->
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="info-center">
|
||||||
|
<!--title-->
|
||||||
|
<div class="info-center">
|
||||||
|
<div class="page-header">
|
||||||
|
<div class="pull-left">
|
||||||
|
<h4>{{.pageTitle}}</h4>
|
||||||
|
</div>
|
||||||
|
<div class="pull-right">
|
||||||
|
<!-- <button type="button" class="btn btn-mystyle btn-sm refresh">刷新</button>
|
||||||
|
<button type="button" class="btn btn-mystyle btn-sm reback">返回</button> -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<!--content-list-->
|
||||||
|
<div class="content-list">
|
||||||
|
<form action="{{urlfor "TaskController.Add"}}" method="post" class="form-horizontal">
|
||||||
|
<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="{{.task.TaskName}}" />
|
||||||
|
</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" >
|
||||||
|
<textarea name="description" class="form-control" id="description" rows="3">{{.task.Description}}</textarea>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-4" 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-3" >
|
||||||
|
<select name="group_id" class="form-control">
|
||||||
|
<option value="0">未分组</option>
|
||||||
|
{{range $k, $v := .groups}}
|
||||||
|
<option value="{{$v.Id}}" {{if eq $v.Id $.task.GroupId}}selected{{end}}>{{$v.GroupName}}</option>
|
||||||
|
{{end}}
|
||||||
|
</select>
|
||||||
|
</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="server_id">服务器</label>
|
||||||
|
<div class="col-sm-3" >
|
||||||
|
<select name="server_id" class="form-control">
|
||||||
|
<option value="0">本地服务器</option>
|
||||||
|
{{range $ks, $vs := .servers}}
|
||||||
|
<option value="{{$vs.Id}}" {{if eq $vs.Id $.task.ServerId}}selected{{end}}>{{$vs.ServerName}}</option>
|
||||||
|
{{end}}
|
||||||
|
</select>
|
||||||
|
</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="concurrent">是否单例</label>
|
||||||
|
<div class="col-sm-3" >
|
||||||
|
<label class="radio-inline">
|
||||||
|
<input type="radio" name="concurrent" value="0" {{if eq .task.Concurrent 0}}checked{{end}}> 是
|
||||||
|
</label>
|
||||||
|
<label class="radio-inline">
|
||||||
|
<input type="radio" name="concurrent" value="1" {{if eq .task.Concurrent 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" >
|
||||||
|
<input type="text" class="form-control input-sm" placeholder="" name="cron_spec" value="{{.task.CronSpec}}" />
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6" style="padding-top:5px;">
|
||||||
|
<a href="{{urlfor "HelpController.Index"}}" target="_blank">参见使用帮助</a>
|
||||||
|
</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" >
|
||||||
|
<textarea name="command" class="form-control" id="command" rows="3">{{.task.Command}}</textarea>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-4" style="padding-top:5px;">
|
||||||
|
|
||||||
|
</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" >
|
||||||
|
<input type="text" class="form-control input-sm" placeholder="秒" name="timeout" value="{{.task.Timeout}}" />
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6" style="padding-top:5px;">
|
||||||
|
单位秒,不设置的话,默认超时时间为1天
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<div class="modal-footer" style="text-align:center">
|
||||||
|
<button type="submit" class="btn btn-primary submit_attr_button">保存</button>
|
||||||
|
<button type="button" class="btn btn-default reback">返回</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
$(function () {
|
||||||
|
$("form").submit(function () {
|
||||||
|
$("button[type='submit']").attr('disabled', true);
|
||||||
|
$.post('{{urlfor "TaskController.Add"}}', $(this).serialize(), function (out) {
|
||||||
|
if (out.status == 0) {
|
||||||
|
window.location.href = '{{urlfor "TaskController.List"}}';
|
||||||
|
} else {
|
||||||
|
alert_message(out.msg,"alert-danger","alert-success");
|
||||||
|
$("button[type='submit']").attr('disabled', false);
|
||||||
|
}
|
||||||
|
}, "json");
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
@@ -105,6 +105,10 @@
|
|||||||
<a class="btn btn-info btn-xs" href="{{urlfor "TaskController.Logs"}}?id={{$v.id}}">
|
<a class="btn btn-info btn-xs" href="{{urlfor "TaskController.Logs"}}?id={{$v.id}}">
|
||||||
<span class="glyphicon glyphicon-file" aria-hidden="true"></span> 日志
|
<span class="glyphicon glyphicon-file" aria-hidden="true"></span> 日志
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
<a class="btn btn-info btn-xs" href="{{urlfor "TaskController.Copy"}}?id={{$v.id}}">
|
||||||
|
<span class="glyphicon glyphicon-copy" aria-hidden="true"></span> 复制
|
||||||
|
</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|||||||
Reference in New Issue
Block a user