mirror of https://github.com/ouqiang/gocron
执行本机系统命令Windows和*nix分别实现
parent
14295049d2
commit
dfa96bc9f2
|
@ -111,7 +111,9 @@ func catchSignal() {
|
||||||
s := <- c
|
s := <- c
|
||||||
logger.Info("收到信号 -- ", s)
|
logger.Info("收到信号 -- ", s)
|
||||||
switch s {
|
switch s {
|
||||||
case syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM:
|
case syscall.SIGHUP:
|
||||||
|
logger.Info("收到终端断开信号, 忽略")
|
||||||
|
case syscall.SIGINT, syscall.SIGTERM:
|
||||||
shutdown()
|
shutdown()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,48 +4,14 @@ import (
|
||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"os/exec"
|
|
||||||
"time"
|
"time"
|
||||||
"runtime"
|
"runtime"
|
||||||
"github.com/Tang-RoseChild/mahonia"
|
"github.com/Tang-RoseChild/mahonia"
|
||||||
"strings"
|
"strings"
|
||||||
"os"
|
"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的随机字符串
|
// 生成长度为length的随机字符串
|
||||||
func RandString(length int64) string {
|
func RandString(length int64) string {
|
||||||
sources := []byte("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
|
sources := []byte("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
|
||||||
|
@ -122,6 +88,7 @@ func EscapeJson(s string) string {
|
||||||
return ReplaceStrings(s, specialChars, replaceChars)
|
return ReplaceStrings(s, specialChars, replaceChars)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 判断文件是否存在及是否有权限访问
|
||||||
func FileExist(file string) bool {
|
func FileExist(file string) bool {
|
||||||
_, err := os.Stat(file)
|
_, err := os.Stat(file)
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
|
@ -132,4 +99,9 @@ func FileExist(file string) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化环境变量
|
||||||
|
func FormatUnixEnv(key, value string) string {
|
||||||
|
return fmt.Sprintf("export %s=%s; ", key, value)
|
||||||
}
|
}
|
|
@ -2,13 +2,6 @@ package utils
|
||||||
|
|
||||||
import "testing"
|
import "testing"
|
||||||
|
|
||||||
func TestExecShell(t *testing.T) {
|
|
||||||
_, err := ExecShell("ls")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRandString(t *testing.T) {
|
func TestRandString(t *testing.T) {
|
||||||
str := RandString(32)
|
str := RandString(32)
|
||||||
if len(str) != 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到环境变量中
|
// 设置notifyId到环境变量中
|
||||||
if 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
|
return taskLogId
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,7 @@
|
||||||
<p>cron表达式: {{{.Spec}}}</p>
|
<p>cron表达式: {{{.Spec}}}</p>
|
||||||
<p>执行方式: {{{if eq .Protocol 1}}} HTTP {{{else if eq .Protocol 2}}} SSH {{{else if eq .Protocol 3}}}本地命令{{{end}}}</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">命令:{{{.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>重试次数: {{{.RetryTimes}}}</p>
|
||||||
<p class="sensorStatus">是否允许多实例运行:{{{if gt .Multi 0}}}是{{{else}}}否{{{end}}}</p>
|
<p class="sensorStatus">是否允许多实例运行:{{{if gt .Multi 0}}}是{{{else}}}否{{{end}}}</p>
|
||||||
{{{if eq .Protocol 2}}}
|
{{{if eq .Protocol 2}}}
|
||||||
|
|
|
@ -72,7 +72,7 @@
|
||||||
<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>{{{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>{{{.RetryTimes}}}</td>
|
||||||
<td>{{{.Hostname}}}</td>
|
<td>{{{.Hostname}}}</td>
|
||||||
<td>
|
<td>
|
||||||
|
|
Loading…
Reference in New Issue