mirror of https://github.com/ouqiang/gocron
执行本机系统命令Windows和*nix分别实现
parent
14295049d2
commit
dfa96bc9f2
|
@ -111,7 +111,9 @@ func catchSignal() {
|
|||
s := <- c
|
||||
logger.Info("收到信号 -- ", s)
|
||||
switch s {
|
||||
case syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM:
|
||||
case syscall.SIGHUP:
|
||||
logger.Info("收到终端断开信号, 忽略")
|
||||
case syscall.SIGINT, syscall.SIGTERM:
|
||||
shutdown()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,48 +4,14 @@ import (
|
|||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"math/rand"
|
||||
"os/exec"
|
||||
"time"
|
||||
"runtime"
|
||||
"github.com/Tang-RoseChild/mahonia"
|
||||
"strings"
|
||||
"os"
|
||||
"syscall"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
|
||||
// 执行shell命令,可设置执行超时时间
|
||||
// todo Windows不能KILL掉子进程, 需特殊处理
|
||||
func ExecShellWithTimeout(timeout int, command string, args... string) (string, error) {
|
||||
cmd := exec.Command(command, args...)
|
||||
cmd.SysProcAttr = &syscall.SysProcAttr{
|
||||
Setpgid: true,
|
||||
}
|
||||
|
||||
// 后台运行
|
||||
if timeout == -1 {
|
||||
go cmd.CombinedOutput()
|
||||
return "", nil
|
||||
}
|
||||
// 不限制超时
|
||||
if timeout == 0 {
|
||||
output ,err := cmd.CombinedOutput()
|
||||
return string(output), err
|
||||
}
|
||||
|
||||
d := time.Duration(timeout) * time.Second
|
||||
timer := time.AfterFunc(d, func() {
|
||||
// 超时kill进程
|
||||
syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL)
|
||||
})
|
||||
output ,err := cmd.CombinedOutput()
|
||||
timer.Stop()
|
||||
|
||||
return string(output), err
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 生成长度为length的随机字符串
|
||||
func RandString(length int64) string {
|
||||
sources := []byte("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
|
||||
|
@ -122,6 +88,7 @@ func EscapeJson(s string) string {
|
|||
return ReplaceStrings(s, specialChars, replaceChars)
|
||||
}
|
||||
|
||||
// 判断文件是否存在及是否有权限访问
|
||||
func FileExist(file string) bool {
|
||||
_, err := os.Stat(file)
|
||||
if os.IsNotExist(err) {
|
||||
|
@ -132,4 +99,9 @@ func FileExist(file string) bool {
|
|||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// 格式化环境变量
|
||||
func FormatUnixEnv(key, value string) string {
|
||||
return fmt.Sprintf("export %s=%s; ", key, value)
|
||||
}
|
|
@ -2,13 +2,6 @@ package utils
|
|||
|
||||
import "testing"
|
||||
|
||||
func TestExecShell(t *testing.T) {
|
||||
_, err := ExecShell("ls")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRandString(t *testing.T) {
|
||||
str := RandString(32)
|
||||
if len(str) != 32 {
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
// +build !windows
|
||||
|
||||
package utils
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
"syscall"
|
||||
"time"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// 执行shell命令,可设置执行超时时间
|
||||
func ExecShellWithTimeout(timeout int, command string, args... string) (string, error) {
|
||||
cmd := exec.Command(command, args...)
|
||||
cmd.SysProcAttr = &syscall.SysProcAttr{
|
||||
Setpgid: true,
|
||||
}
|
||||
|
||||
// 后台运行
|
||||
if timeout == -1 {
|
||||
go cmd.CombinedOutput()
|
||||
return "", nil
|
||||
}
|
||||
// 不限制超时
|
||||
if timeout == 0 {
|
||||
output ,err := cmd.CombinedOutput()
|
||||
return string(output), err
|
||||
}
|
||||
|
||||
d := time.Duration(timeout) * time.Second
|
||||
timer := time.AfterFunc(d, func() {
|
||||
// 超时kill进程
|
||||
syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL)
|
||||
})
|
||||
output ,err := cmd.CombinedOutput()
|
||||
timer.Stop()
|
||||
|
||||
return string(output), err
|
||||
}
|
||||
|
||||
// 格式化环境变量
|
||||
func FormatEnv(key, value string) string {
|
||||
return fmt.Sprintf("export %s=%s;", key, value)
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
// +build windows
|
||||
|
||||
package utils
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"time"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// 执行shell命令,可设置执行超时时间
|
||||
func ExecShellWithTimeout(timeout int, command string, args... string) (string, error) {
|
||||
cmd := exec.Command(command, args...)
|
||||
// 隐藏cmd窗口
|
||||
cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true}
|
||||
// 后台运行
|
||||
if timeout == -1 {
|
||||
go cmd.CombinedOutput()
|
||||
return "", nil
|
||||
}
|
||||
// 不限制超时
|
||||
if timeout <= 0 {
|
||||
output ,err := cmd.CombinedOutput()
|
||||
return string(output), err
|
||||
}
|
||||
|
||||
d := time.Duration(timeout) * time.Second
|
||||
timer := time.AfterFunc(d, func() {
|
||||
// 超时kill进程
|
||||
exec.Command("taskkill", "/F", "/T", "/PID", strconv.Itoa(cmd.Process.Pid)).Run()
|
||||
cmd.Process.Kill()
|
||||
})
|
||||
output ,err := cmd.CombinedOutput()
|
||||
timer.Stop()
|
||||
|
||||
return string(output), err
|
||||
}
|
||||
|
||||
// 格式化环境变量
|
||||
func FormatEnv(key, value string) string {
|
||||
return fmt.Sprintf("set %s=%s & ", key, value)
|
||||
}
|
|
@ -310,9 +310,16 @@ func beforeExecJob(taskModel *models.TaskHost) (taskLogId int64) {
|
|||
}
|
||||
// 设置notifyId到环境变量中
|
||||
if notifyId != "" {
|
||||
taskModel.Command = fmt.Sprintf("export GOCRON_TASK_ID=%s;%s", notifyId, taskModel.Command)
|
||||
envName := "GOCRON_TASK_ID"
|
||||
if taskModel.Protocol == models.TaskSSH {
|
||||
taskModel.Command = fmt.Sprintf("%s%s", utils.FormatUnixEnv(envName, notifyId), taskModel.Command)
|
||||
} else {
|
||||
taskModel.Command = fmt.Sprintf("%s%s", utils.FormatEnv(envName, notifyId), taskModel.Command)
|
||||
}
|
||||
}
|
||||
|
||||
logger.Debugf("任务命令-%s", taskModel.Command)
|
||||
|
||||
return taskLogId
|
||||
}
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@
|
|||
<p>cron表达式: {{{.Spec}}}</p>
|
||||
<p>执行方式: {{{if eq .Protocol 1}}} HTTP {{{else if eq .Protocol 2}}} SSH {{{else if eq .Protocol 3}}}本地命令{{{end}}}</p>
|
||||
<p class="sensorStatus">命令:{{{.Command}}}</p>
|
||||
<p class="sensorStatus">超时时间:{{{if gt .Timeout 0}}}{{{.Timeout}}}秒{{{else}}}不限制{{{end}}}</p>
|
||||
<p class="sensorStatus">超时时间:{{{if eq .Timeout -1}}}后台运行{{{else if eq .Timeout 0}}}{{{.Timeout}}}秒{{{else}}}不限制{{{end}}}</p>
|
||||
<p>重试次数: {{{.RetryTimes}}}</p>
|
||||
<p class="sensorStatus">是否允许多实例运行:{{{if gt .Multi 0}}}是{{{else}}}否{{{end}}}</p>
|
||||
{{{if eq .Protocol 2}}}
|
||||
|
|
|
@ -72,7 +72,7 @@
|
|||
<td>{{{.Name}}}</td>
|
||||
<td>{{{.Spec}}}</td>
|
||||
<td>{{{if eq .Protocol 1}}} HTTP {{{else if eq .Protocol 2}}} SSH {{{else}}} 系统命令 {{{end}}}</td>
|
||||
<td>{{{if gt .Timeout 0}}}{{{.Timeout}}}秒{{{else}}}不限制{{{end}}}</td>
|
||||
<td>{{{if eq .Timeout -1}}}后台运行{{{else if eq .Timeout 0}}}{{{.Timeout}}}秒{{{else}}}不限制{{{end}}}</td>
|
||||
<td>{{{.RetryTimes}}}</td>
|
||||
<td>{{{.Hostname}}}</td>
|
||||
<td>
|
||||
|
|
Loading…
Reference in New Issue