任务增加手动执行方式

pull/21/merge
ouqiang 2017-04-21 13:36:45 +08:00
parent d1d2685827
commit 4978778579
10 changed files with 108 additions and 42 deletions

View File

@ -119,7 +119,7 @@ func (task *Task) NameExist(name string, id int) (bool, error) {
func(task *Task) Detail(id int) (TaskHost, error) { func(task *Task) Detail(id int) (TaskHost, error) {
taskHost := TaskHost{} taskHost := TaskHost{}
fields := "t.*, host.name,host.username,host.password,host.port,host.auth_type,host.private_key" fields := "t.*, host.alias,host.name,host.username,host.password,host.port,host.auth_type,host.private_key"
_, err := Db.Alias("t").Join("LEFT", "host", "t.host_id=host.id").Where("t.id=?", id).Cols(fields).Get(&taskHost) _, err := Db.Alias("t").Join("LEFT", "host", "t.host_id=host.id").Where("t.id=?", id).Cols(fields).Get(&taskHost)
return taskHost, err return taskHost, err

View File

@ -23,6 +23,7 @@ type TaskLog struct {
Result string `xorm:"varchar(65535) notnull defalut '' "` // 执行结果 Result string `xorm:"varchar(65535) notnull defalut '' "` // 执行结果
Page int `xorm:"-"` Page int `xorm:"-"`
PageSize int `xorm:"-"` PageSize int `xorm:"-"`
TotalTime int `xorm:"-"` // 执行总时长
} }
func (taskLog *TaskLog) Create() (insertId int64, err error) { func (taskLog *TaskLog) Create() (insertId int64, err error) {
@ -49,6 +50,16 @@ func (taskLog *TaskLog) List() ([]TaskLog, error) {
taskLog.parsePageAndPageSize() taskLog.parsePageAndPageSize()
list := make([]TaskLog, 0) list := make([]TaskLog, 0)
err := Db.Desc("id").Limit(taskLog.PageSize, taskLog.pageLimitOffset()).Find(&list) err := Db.Desc("id").Limit(taskLog.PageSize, taskLog.pageLimitOffset()).Find(&list)
if len(list) > 0 {
for i, item := range list {
endTime := item.EndTime
if item.Status == Running {
endTime = time.Now()
}
execSeconds := endTime.Sub(item.StartTime).Seconds()
list[i].TotalTime = int(execSeconds)
}
}
return list, err return list, err
} }

View File

@ -15,7 +15,9 @@ function Util() {
swal(FAILURE_MESSAGE, response.message ,'error'); swal(FAILURE_MESSAGE, response.message ,'error');
return; return;
} }
if (callback !== undefined) {
callback(response.code, response.message, response.data); callback(response.code, response.message, response.data);
}
}; };
util.ajaxFailure = function() { util.ajaxFailure = function() {
// todo 错误处理 // todo 错误处理

View File

@ -67,6 +67,7 @@ func Register(m *macaron.Macaron) {
m.Post("/remove/:id", task.Remove) m.Post("/remove/:id", task.Remove)
m.Post("/enable/:id", task.Enable) m.Post("/enable/:id", task.Enable)
m.Post("/disable/:id", task.Disable) m.Post("/disable/:id", task.Disable)
m.Get("/run/:id", task.Run)
}) })
// 主机 // 主机

View File

@ -145,6 +145,23 @@ func Disable(ctx *macaron.Context) string {
return changeStatus(ctx, models.Disabled) return changeStatus(ctx, models.Disabled)
} }
// 手动运行任务
func Run(ctx *macaron.Context) string {
id := ctx.ParamsInt(":id")
json := utils.JsonResponse{}
taskModel := new(models.Task)
task , err := taskModel.Detail(id)
if err != nil || task.Id <= 0 {
return json.CommonFailure("获取任务详情失败", err)
}
task.Spec = "手动运行"
serviceTask := new(service.Task)
serviceTask.Run(task)
return json.Success("任务已开始运行, 请到任务日志中查看结果", nil);
}
// 改变任务状态 // 改变任务状态
func changeStatus(ctx *macaron.Context, status models.Status) string { func changeStatus(ctx *macaron.Context, status models.Status) string {
id := ctx.ParamsInt(":id") id := ctx.ParamsInt(":id")

View File

@ -57,11 +57,15 @@ func (task *Task) Add(taskModel models.TaskHost) {
} }
} }
// 直接运行任务
func (task *Task) Run(taskModel models.TaskHost) {
go createHandlerJob(taskModel)()
}
type Handler interface { type Handler interface {
Run(taskModel models.TaskHost) (string, error) Run(taskModel models.TaskHost) (string, error)
} }
// 本地命令 // 本地命令
type LocalCommandHandler struct {} type LocalCommandHandler struct {}
@ -142,7 +146,6 @@ func (h *SSHCommandHandler) Run(taskModel models.TaskHost) (string, error) {
return ssh.Exec(sshConfig, taskModel.Command) return ssh.Exec(sshConfig, taskModel.Command)
} }
func createTaskLog(taskModel models.TaskHost) (int64, error) { func createTaskLog(taskModel models.TaskHost) (int64, error) {
taskLogModel := new(models.TaskLog) taskLogModel := new(models.TaskLog)
taskLogModel.TaskId = taskModel.Id taskLogModel.TaskId = taskModel.Id

View File

@ -14,6 +14,11 @@
<script type="text/javascript" src="/resource/sweetalert/sweetalert.min.js"></script> <script type="text/javascript" src="/resource/sweetalert/sweetalert.min.js"></script>
<script type="text/javascript" src="/resource/javascript/vue.min.js"></script> <script type="text/javascript" src="/resource/javascript/vue.min.js"></script>
<script type="text/javascript" src="/resource/javascript/main.js"></script> <script type="text/javascript" src="/resource/javascript/main.js"></script>
<style type="text/css">
body {
overflow-x: hidden;
}
</style>
</head> </head>
<body> <body>
<div class="page"> <div class="page">

View File

@ -41,12 +41,15 @@
<td> <td>
<a class="ui purple button" href="/task/edit/{{{.Id}}}">编辑</a> <a class="ui purple button" href="/task/edit/{{{.Id}}}">编辑</a>
{{{if eq .Status 1}}} {{{if eq .Status 1}}}
<button class="ui primary button" onclick="changeStatus({{{.Id}}},{{{.Status}}})">暂停</button> <button class="ui primary button" @click="changeStatus({{{.Id}}},{{{.Status}}})">暂停</button>
{{{else}}} {{{else}}}
<button class="ui blue button" onclick="changeStatus({{{.Id}}},{{{.Status}}})">激活 </button> <button class="ui blue button" @click="changeStatus({{{.Id}}},{{{.Status}}})">激活 </button>
{{{end}}} {{{end}}}
<button class="ui positive button" onclick="util.removeConfirm('/task/remove/{{{.Id}}}')">删除</button> <button class="ui positive button" @click="remove({{{.Id}}})">删除</button> <br>
<div style="margin-top:10px;">
<button class="ui twitter button" @click="run({{{.Id}}})">手动运行</button>
<button class="ui instagram button">查看日志</button> <button class="ui instagram button">查看日志</button>
</div>
</td> </td>
</tr> </tr>
{{{end}}} {{{end}}}
@ -59,7 +62,11 @@
<script type="text/javascript"> <script type="text/javascript">
$('.ui.checkbox').checkbox(); $('.ui.checkbox').checkbox();
function changeStatus(id ,status) { var vue = new Vue(
{
el: '.ui.violet.table',
methods: {
changeStatus: function (id ,status) {
var url = ''; var url = '';
if (status) { if (status) {
url = '/task/disable'; url = '/task/disable';
@ -70,7 +77,20 @@
util.post(url,{}, function() { util.post(url,{}, function() {
location.reload(); location.reload();
}); });
},
remove: function(id) {
util.removeConfirm('/task/remove/' + id);
},
run: function(id) {
util.get("/task/run/" + id, function(code, message) {
swal('操作成功', message, 'success');
})
} }
}
}
);
</script> </script>

View File

@ -19,7 +19,6 @@
<div class="content"> <div class="content">
<button class="ui small teal button" onclick="clearLog()">清空日志</button> <button class="ui small teal button" onclick="clearLog()">清空日志</button>
</div> </div>
</h3> </h3>
</div> </div>
</div> </div>
@ -29,10 +28,9 @@
<th>任务名称</th> <th>任务名称</th>
<th>cron表达式</th> <th>cron表达式</th>
<th>协议</th> <th>协议</th>
<th>超时时间(秒)</th> <th>超时时间</th>
<th>主机</th> <th>主机</th>
<th>开始时间</th> <th>执行时长</th>
<th>结束时间</th>
<th>状态</th> <th>状态</th>
<th>执行结果</th> <th>执行结果</th>
</tr> </tr>
@ -43,13 +41,14 @@
<td>{{{.Name}}}</td> <td>{{{.Name}}}</td>
<td>{{{.Spec}}}</td> <td>{{{.Spec}}}</td>
<td>{{{if eq .Protocol 1}}} HTTP {{{else if eq .Protocol 2}}} SSH {{{else}}} 本地命令 {{{end}}}</td> <td>{{{if eq .Protocol 1}}} HTTP {{{else if eq .Protocol 2}}} SSH {{{else}}} 本地命令 {{{end}}}</td>
<td>{{{.Timeout}}}</td> <td>{{{.Timeout}}}</td>
<td>{{{.Hostname}}}</td> <td>{{{.Hostname}}}</td>
<td> <td>
{{{.StartTime.Format "2006-01-02 15:04:05" }}} {{{if gt .TotalTime 0}}}{{{.TotalTime}}}秒{{{else}}}1秒{{{end}}}<br>
</td> 开始时间: {{{.StartTime.Format "2006-01-02 15:04:05" }}}<br>
<td> {{{if ne .Status 1}}}
{{{.EndTime.Format "2006-01-02 15:04:05" }}} 结束时间: {{{.EndTime.Format "2006-01-02 15:04:05" }}}
{{{end}}}
</td> </td>
<td> <td>
{{{if eq .Status 2}}} {{{if eq .Status 2}}}
@ -63,10 +62,12 @@
{{{end}}} {{{end}}}
</td> </td>
<td> <td>
{{{if ne .Status 1}}}
<button class="ui small primary button" <button class="ui small primary button"
onclick="showResult('{{{.Name}}}', '{{{.Command}}}', '{{{.Result}}}')" onclick="showResult('{{{.Name}}}', '{{{.Command}}}', '{{{.Result}}}')"
>查看结果 >查看结果
</button> </button>
{{{end}}}
</td> </td>
</tr> </tr>
{{{end}}} {{{end}}}
@ -95,6 +96,10 @@
</script> </script>
<script type="text/javascript"> <script type="text/javascript">
function showTime(startTime, endTime, status) {
}
function showResult(name, command,result) { function showResult(name, command,result) {
$('.message').html($('#task-result').html()); $('.message').html($('#task-result').html());
new Vue( new Vue(

View File

@ -19,14 +19,14 @@
<div class="field"> <div class="field">
<label>任务名称</label> <label>任务名称</label>
<div class="ui small left icon input"> <div class="ui small left icon input">
<input type="text" placeholder="数据库备份" name="name" value="{{{.Task.Task.Name}}}"> <input type="text" name="name" value="{{{.Task.Task.Name}}}">
</div> </div>
</div> </div>
</div> </div>
<div class="two fields"> <div class="two fields">
<div class="field"> <div class="field">
<label>crontab表达式 (每行一个表达式)</label> <label>crontab表达式 (每行一个表达式)</label>
<textarea rows="5" name="spec" placeholder="*/5 * * * * * *">{{{.Task.Spec}}}</textarea> <textarea rows="5" name="spec">{{{.Task.Spec}}}</textarea>
</div> </div>
</div> </div>
<div class="three fields"> <div class="three fields">
@ -56,7 +56,7 @@
<div class="ui radio checkbox"> <div class="ui radio checkbox">
{{{if $.Task}}} {{{if $.Task}}}
<input type="radio" name="host_id" tabindex="0" class="hidden" value="{{{.Id}}}" <input type="radio" name="host_id" tabindex="0" class="hidden" value="{{{.Id}}}"
{{{if eq $.Task.HostId .Id}}} checked {{{end}}} {{{if and (eq $.Task.Protocol 2) (eq $.Task.HostId .Id) }}} checked {{{end}}}
> >
{{{else}}} {{{else}}}
<input type="radio" name="host_id" tabindex="0" class="hidden" value="{{{.Id}}}"> <input type="radio" name="host_id" tabindex="0" class="hidden" value="{{{.Id}}}">
@ -67,14 +67,16 @@
{{{end}}} {{{end}}}
</div> </div>
</div> </div>
<div class="two fields">
<div class="field"> <div class="field">
<label>命令(shell命令|URL地址, 多条shell命令";"分隔)</label> <label>命令(shell命令|URL地址, 多条shell命令";"分隔)</label>
<input type="text" name="command" placeholder="tail -n 10 /var/log/nginx/error.log" value="{{{.Task.Command}}}"> <textarea rows="5" name="command">{{{.Task.Command}}}</textarea>
</div>
</div> </div>
<div class="three fields"> <div class="three fields">
<div class="field"> <div class="field">
<label>任务超时时间 (单位秒,0不限制,不能超过24小时)</label> <label>任务超时时间 (单位秒,0不限制,不能超过24小时)</label>
<input type="text" name="timeout" placeholder="0" value="{{{.Task.Timeout}}}"> <input type="text" name="timeout" value="{{{.Task.Timeout}}}">
</div> </div>
</div> </div>
<div class="three fields"> <div class="three fields">
@ -95,10 +97,10 @@
</div> </div>
</div> </div>
</div> </div>
<div class="two field"> <div class="two fields">
<div class="field"> <div class="field">
<label>备注</label> <label>备注</label>
<textarea rows="5" name="remark" placeholder="任务备注">{{{.Task.Remark}}}</textarea> <textarea rows="5" name="remark">{{{.Task.Remark}}}</textarea>
</div> </div>
</div> </div>
<div class="ui primary submit button">保存</div> <div class="ui primary submit button">保存</div>