1 Star 0 Fork 0

坐公交也用券 / gcs

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
shell.go 5.12 KB
一键复制 编辑 原始数据 按行查看 历史
package gcs
import (
"context"
"fmt"
"gitee.com/liumou_site/logger"
"os/exec"
"strings"
"time"
"gitee.com/liumou_site/gbm"
"github.com/spf13/cast"
)
// RunShell 执行命令
func (api *ApiShell) RunShell(command ...string) {
api.args = command
api.shellSystem()
}
// RunScript 通过生成脚本的方式执行Shell,支持Shell管道
func (api *ApiShell) RunScript(command ...string) {
api.ScriptMode = true
api.args = command
api.Text = gbm.SliceToString(command, " ")
err := createScript(api.Text, api.Script)
if err == nil {
api.args = []string{api.Script}
api.shellSystem()
} else {
if api.PrintErr {
logs.Error("文件创建失败: ", api.Script)
}
}
api.ScriptMode = false
}
func (api *ApiShell) shellInit() {
var argTmp string
api.Strings = "" // 初始化输出
api.Result = false // 初始化执行结果
api.Err = nil // 初始化错误
if api.Debug {
logs.Debug("处理前参数: %d", len(api.args))
fmt.Println(api.args)
}
api.args = gbm.SliceToSlice(api.args, " ") // 去除空元素
if api.Debug {
logs.Debug("处理后参数: %d", len(api.args))
fmt.Println(api.args)
}
api.args = gbm.SliceRemoveNull(api.args)
if len(api.args) == 1 { // 判断命令参数数量
api.args = strings.Split(api.args[0], " ")
}
api.Text = gbm.SliceToString(api.args, " ")
api.cmdName = "/bin/bash" // 定义命令路径
if CheckCmd(api.args[0]) { // 如果命令在PATH中则使用命令执行并从参数中移除命令
api.cmdName = api.args[0] // 使用第一个参数作为命令
api.args, api.Err = gbm.SliceRemoveIndex(api.args, 0) // 移除第一个元素
if api.Err != nil {
return
}
argTmp = ""
api.argRun = api.args // 在切片头部添加/C参数
} else {
if api.OsType == "windows" {
api.cmdName = "cmd"
argTmp = "/C"
} else {
argTmp = "-c"
}
api.argRun = append([]string{argTmp}, api.args...) // 在切片头部添加-c参数
}
}
// shellSystem 执行命令并将结果赋值到结构体
func (api *ApiShell) shellSystem() {
var cmd *exec.Cmd
api.shellInit()
if len(api.args) > 0 {
cmd = exec.Command(api.cmdName, api.argRun...) // 创建命令实例
} else {
cmd = exec.Command(api.cmdName) // 创建命令实例
}
if api.Err != nil {
return
}
if api.ScriptMode {
cmd = exec.Command("/bin/bash", "-c", api.Script)
if api.Debug {
logs.Debug(api.Script)
}
}
// 命令的错误输出和标准输出都连接到同一个管道
stdout, err := cmd.StdoutPipe()
cmd.Stderr = cmd.Stdout
api.Err = err
if err != nil {
if api.PrintErr {
logs.Error("管道创建失败")
}
if api.Debug {
logs.Debug("Execute command: ", api.Text)
}
api.ExitCode = 1
return
}
api.Err = cmd.Start()
if api.Err != nil {
logs.Error("命令启动失败 :", api.Err)
logs.Debug("Execute command: ", api.Text)
api.ExitCode = 2
return
}
// 从管道中实时获取输出并打印到终端
for {
tmp := make([]byte, 1024)
_, err := stdout.Read(tmp)
// 如果开启了实时打印,则将信息逐行输出到终端
if api.Realtime {
fmt.Print(string(tmp))
}
api.Strings = api.Strings + cast.ToString(string(tmp))
if err != nil {
break
}
}
// 等待命令退出,并等待任何复制到stdin或从stdout或stderr复制完成。
api.Err = cmd.Wait()
// ExitCode返回已退出进程的退出代码,如果进程尚未退出或被信号终止,则返回-1。
api.ExitCode = cmd.ProcessState.ExitCode()
if api.PrintInfo {
logs.Info("Exit Code: %d", cmd.ProcessState.ExitCode())
}
if api.Err == nil {
if api.ExitCode != 0 {
if api.PrintErr {
logs.Error("Error :", api.Err)
}
if api.Debug {
logs.Debug("Execute command: ", api.Text)
}
}
if api.ExitCode == 0 {
api.Result = true
api.Err = nil
}
}
}
// argsHandle 参数处理
func (api *ApiShell) argsHandle() {
api.Strings = "" // 初始化输出
api.Result = false // 初始化执行结果
api.Err = nil // 初始化错误
api.Result = false // 重置执行结果
if api.Debug {
logs.Debug("处理前参数: %d", len(api.args))
}
api.args = gbm.SliceToSlice(api.args, " ") // 去除空元素
if api.Debug {
logs.Debug("处理后参数: %d", len(api.args))
}
api.args = append([]string{"-c"}, api.args...) // 在切片头部添加-S参数
}
// RunTimeout 执行系统命令并设置超时时间
func (api *ApiShell) RunTimeout(n time.Duration, command ...string) *ApiShell {
api.args = command
api.shellInit() // 处理参数
if api.Err != nil {
return api
}
ctx, cancel := context.WithTimeout(context.Background(), n*time.Second) // 创建带有超时时间的上下文对象
defer cancel()
if api.Debug {
logs.Debug("执行命令: %s", api.cmdName)
logs.Debug("执行参数: %s", api.argRun)
}
cmd := exec.CommandContext(ctx, api.cmdName, api.argRun...) // 创建命令对象,并将上下文对象传递给 CommandContext 方法
// 执行命令,并等待命令执行完成
if api.Err = cmd.Run(); api.Err != nil {
// 如果是超时错误,则返回超时信息
if ctx.Err() == context.DeadlineExceeded {
if api.PrintErr {
logger.Error("命令执行超时: ", api.Err.Error())
}
}
}
return api
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Go
1
https://gitee.com/liumou_site/gcs.git
git@gitee.com:liumou_site/gcs.git
liumou_site
gcs
gcs
v1.7.5

搜索帮助

344bd9b3 5694891 D2dac590 5694891