143 lines
4.5 KiB
Go
143 lines
4.5 KiB
Go
package service
|
||
|
||
import (
|
||
"bytes"
|
||
"errors"
|
||
"log"
|
||
"os/exec"
|
||
"strings"
|
||
"time"
|
||
"videoplayer/dao"
|
||
"videoplayer/proto"
|
||
"videoplayer/worker"
|
||
)
|
||
|
||
func CreateShell(shellName, shellContent, server string, uid int) uint {
|
||
id := dao.CreateShell(shellName, shellContent, server, uint(uid))
|
||
return id
|
||
}
|
||
|
||
func FindShellByAuthID(id int) []dao.Shell {
|
||
return dao.FindShellByAuthID(id)
|
||
}
|
||
|
||
func DeleteShellByID(id, authId uint) bool {
|
||
user := GetUserByIDFromUserCenter(int(authId))
|
||
if user.Role == "admin" {
|
||
return dao.DeleteShellByIDV2(id)
|
||
}
|
||
return dao.DeleteShellByID(id, authId)
|
||
}
|
||
|
||
func UpdateShellByID(id, authId uint, shellName, shellContent, server string, status int, shellResult string) bool {
|
||
return dao.UpdateShellByID(id, authId, shellName, shellContent, status, shellResult, 0, 0)
|
||
}
|
||
|
||
func UpdateShellByIDV2(id, authId uint, shellName, shellContent, server string, status int, shellResult string, shellRuntime float64) bool {
|
||
//查看shell是否存在
|
||
pd := dao.FindShellByID(id, authId)
|
||
if len(pd) < 1 && pd[0].ID == 0 {
|
||
return false
|
||
}
|
||
shell := pd[0]
|
||
//如果状态为2,3转为0,1是不允许的,为了防止出现1确认包阻塞问题
|
||
if (shell.Status == 2 || shell.Status == 3) && (status == 0 || status == 1) {
|
||
log.Println("UpdateShellByIDV2: status change from 2/3 to 0/1 is not allowed, shell id:", id)
|
||
return false
|
||
}
|
||
var elapsed float64 //持续时间
|
||
if (shell.Status == 0 || shell.Status == 1) && (status == 2 || status == 3) { //如果状态为执行中,且新更新时间状态为2或3,则获取持续时间
|
||
elapsed = time.Since(shell.CreatedAt).Seconds()
|
||
}
|
||
return dao.UpdateShellByID(id, authId, shellName, shellContent, status, shellResult, shellRuntime, elapsed)
|
||
}
|
||
|
||
func FindShellWillRunByServer(server string, uid int) ([]dao.Shell, error) {
|
||
var shells []dao.Shell
|
||
var err error
|
||
if server == "" {
|
||
//err设置为server为空
|
||
err = errors.New("server is empty")
|
||
return shells, err
|
||
}
|
||
shells = dao.FindShellWillRunByServer(server, uint(uid))
|
||
//设置状态为执行中
|
||
for _, v := range shells {
|
||
dao.UpdateShellByID(v.ID, uint(uid), v.ShellName, v.ShellContent, v.Status+1, v.ShellResult, 0, 0) //将状态设置为执行中
|
||
}
|
||
return shells, err
|
||
}
|
||
|
||
// 从服务器定时获取shell、执行并返回结果
|
||
func ShellWillRunFromServer() {
|
||
shells, err := GetShellWillRunFromMaster(proto.Config.SERVER_NAME)
|
||
if err != nil {
|
||
return
|
||
}
|
||
var resp []proto.UpdateShellReq
|
||
|
||
for _, v := range shells {
|
||
//执行shell脚本,go执行命令
|
||
start := time.Now()
|
||
res, err2 := RunShell(v.ShellContent)
|
||
//执行时间,转成秒
|
||
shellRuntime := time.Since(start).Seconds()
|
||
if err2 != "" {
|
||
resp = append(resp, proto.UpdateShellReq{ID: v.ID, Server: v.Server, Status: 3, ShellResult: "err:" + err2 + "\nresult:" + res, ShellRuntime: shellRuntime}) //执行出错
|
||
} else {
|
||
resp = append(resp, proto.UpdateShellReq{ID: v.ID, Server: v.Server, Status: 2, ShellResult: res, ShellRuntime: shellRuntime}) //执行成功
|
||
}
|
||
}
|
||
if len(resp) == 0 {
|
||
return
|
||
}
|
||
//返回执行结果
|
||
url := "https://" + proto.Config.MASTER_SERVER_DOMAIN + "/shell/update?super_id=1"
|
||
var req proto.SyncUserShellResp
|
||
req.Token = worker.GetRedisSetMembers("super_permission_tokens")[0]
|
||
req.Shells = resp
|
||
resp_data, err := worker.SyncDataFromMasterShellReq3(url, req)
|
||
if err != nil {
|
||
return
|
||
}
|
||
//更新执行结果
|
||
for _, v := range resp_data {
|
||
if v.Status < 0 {
|
||
log.Fatalln("update shell failed:", v.ID, v.Status)
|
||
}
|
||
}
|
||
}
|
||
|
||
// 从服务器从主服务器获取待执行的shell
|
||
func GetShellWillRunFromMaster(server string) ([]dao.Shell, error) {
|
||
master := proto.Config.MASTER_SERVER_DOMAIN
|
||
//发起请求获取待执行的shell
|
||
url := "https://" + master + "/shell/server_will_run_list?super_id=1"
|
||
var req proto.SyncUserShellReq
|
||
req.Server = server
|
||
superPermissions := worker.GetRedisSetMembers("super_permission_tokens")
|
||
if len(superPermissions) == 0 {
|
||
log.Println("get shell will run from master error: no super permission tokens found, please check the configuration or redis!")
|
||
return nil, errors.New("no super permission tokens found")
|
||
}
|
||
req.Token = superPermissions[0]
|
||
shells, err := worker.SyncDataFromMasterShellReq2(url, req)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
return shells, nil
|
||
}
|
||
|
||
func RunShell(script string) (res, err string) {
|
||
cmd := exec.Command("/bin/bash", "-c", script)
|
||
// 使用bytes.Buffer捕获输出
|
||
var out bytes.Buffer
|
||
cmd.Stdout = &out
|
||
err3 := cmd.Run()
|
||
err3_info := ""
|
||
if err3 != nil {
|
||
err3_info = err3.Error()
|
||
}
|
||
return strings.TrimSpace(out.String()), err3_info
|
||
}
|