From 0f10b02cc430865101e8b7b7b151b7a3d91e370b Mon Sep 17 00:00:00 2001 From: engigu Date: Sun, 11 Jan 2026 21:02:14 +0800 Subject: [PATCH] fix: shell call bin --- internal/services/tasks/executor_service.go | 117 ------------------ .../services/tasks/task_execution_service.go | 115 +++++++++++++++++ 2 files changed, 115 insertions(+), 117 deletions(-) diff --git a/internal/services/tasks/executor_service.go b/internal/services/tasks/executor_service.go index 846030f..fa89cec 100644 --- a/internal/services/tasks/executor_service.go +++ b/internal/services/tasks/executor_service.go @@ -3,16 +3,12 @@ package tasks import ( "baihu/internal/constant" "baihu/internal/logger" - "baihu/internal/models" "baihu/internal/utils" "bytes" "context" - "encoding/json" "fmt" "os" "os/exec" - "path/filepath" - "strings" "sync" "time" ) @@ -232,119 +228,6 @@ func (es *ExecutorService) executeTaskInternal(taskID int) *ExecutionResult { return result } -// executeNormalTask 执行普通任务 -func (es *ExecutorService) executeNormalTask(task *models.Task) *ExecutionResult { - // 演示模式下使用 echo 替换实际命令 - if constant.DemoMode { - return es.ExecuteCommandWithOptions("echo '[演示模式] 任务执行已跳过,实际命令不会运行'", time.Minute, nil, "") - } - - // 加载环境变量 - envVars := es.envService.GetEnvVarsByIDs(task.Envs) - - // 确定工作目录 - workDir := task.WorkDir - if workDir == "" { - workDir = constant.ScriptsWorkDir - } - - // 使用任务配置的超时时间 - timeout := task.Timeout - if timeout <= 0 { - timeout = constant.DefaultTaskTimeout - } - return es.ExecuteCommandWithOptions(task.Command, time.Duration(timeout)*time.Minute, envVars, workDir) -} - -// executeRepoTask 执行仓库同步任务(调用 sync.py) -func (es *ExecutorService) executeRepoTask(task *models.Task) *ExecutionResult { - // 演示模式下使用 echo 替换实际命令 - if constant.DemoMode { - return es.ExecuteCommandWithOptions("echo '[演示模式] 仓库同步已跳过,实际命令不会运行'", time.Minute, nil, "") - } - - result := &ExecutionResult{ - Success: false, - Start: time.Now(), - } - - // 解析仓库配置 - var config models.RepoConfig - if err := json.Unmarshal([]byte(task.Config), &config); err != nil { - result.End = time.Now() - result.Error = "解析仓库配置失败: " + err.Error() - return result - } - - // 处理目标路径:为空则使用 scripts 目录,相对路径则基于 scripts 目录 - targetPath := config.TargetPath - if targetPath == "" { - targetPath = constant.ScriptsWorkDir - } else if !filepath.IsAbs(targetPath) { - targetPath = filepath.Join(constant.ScriptsWorkDir, targetPath) - } - // 转换为绝对路径 - absTargetPath, err := filepath.Abs(targetPath) - if err != nil { - absTargetPath = targetPath - } - - // 构建 sync.py 命令参数 - args := []string{ - "/opt/sync.py", - "--source-type", config.SourceType, - "--source-url", config.SourceURL, - "--target-path", absTargetPath, - } - - // Git 分支 - if config.Branch != "" { - args = append(args, "--branch", config.Branch) - } - - // 稀疏路径 - if config.SparsePath != "" { - args = append(args, "--path", config.SparsePath) - } - - // 单文件模式 - if config.SingleFile { - args = append(args, "--single-file") - } - - // 代理设置 - if config.Proxy != "" && config.Proxy != "none" { - args = append(args, "--proxy", config.Proxy) - if config.Proxy == "custom" && config.ProxyURL != "" { - args = append(args, "--proxy-url", config.ProxyURL) - } - } - - // 认证 Token - if config.AuthToken != "" { - args = append(args, "--auth-token", config.AuthToken) - } - - // 构建命令 - command := "python3 " + strings.Join(args, " ") - - // 使用任务配置的超时时间 - timeout := task.Timeout - if timeout <= 0 { - timeout = constant.DefaultTaskTimeout - } - - // 执行命令 - execResult := es.ExecuteCommandWithOptions(command, time.Duration(timeout)*time.Minute, nil, "/opt") - - result.End = time.Now() - result.Output = execResult.Output - result.Success = execResult.Success - result.Error = execResult.Error - - return result -} - // GetRunningCount 获取正在运行的任务数量 func (es *ExecutorService) GetRunningCount() int { es.mu.RLock() diff --git a/internal/services/tasks/task_execution_service.go b/internal/services/tasks/task_execution_service.go index 4151d68..86ff59c 100644 --- a/internal/services/tasks/task_execution_service.go +++ b/internal/services/tasks/task_execution_service.go @@ -8,6 +8,7 @@ import ( "baihu/internal/utils" "bytes" "context" + "encoding/json" "fmt" "os" "os/exec" @@ -92,6 +93,11 @@ func (s *TaskExecutionService) executeLocal(req *TaskExecutionRequest) error { task := req.Task logger.Infof("[TaskExecution] 本地执行任务 #%d: %s", task.ID, task.Name) + // 检查任务类型,仓库任务需要特殊处理 + if task.Type == "repo" { + return s.executeRepoTask(req) + } + start := time.Now() // 准备命令 @@ -308,3 +314,112 @@ func (s *TaskExecutionService) ProcessAgentResult(agentResult *models.AgentTaskR func (s *TaskExecutionService) GetScriptPath(scriptName string) string { return filepath.Join("data", "scripts", scriptName) } + +// executeRepoTask 执行仓库同步任务(调用 sync.py) +func (s *TaskExecutionService) executeRepoTask(req *TaskExecutionRequest) error { + task := req.Task + logger.Infof("[TaskExecution] 执行仓库同步任务 #%d: %s", task.ID, task.Name) + + start := time.Now() + + // 解析仓库配置 + var config models.RepoConfig + if err := json.Unmarshal([]byte(task.Config), &config); err != nil { + return s.handleExecutionError(task.ID, "", start, fmt.Errorf("解析仓库配置失败: %v", err)) + } + + // 处理目标路径:为空则使用 scripts 目录,相对路径则基于 scripts 目录 + targetPath := config.TargetPath + if targetPath == "" { + targetPath = constant.ScriptsWorkDir + } else if !filepath.IsAbs(targetPath) { + targetPath = filepath.Join(constant.ScriptsWorkDir, targetPath) + } + // 转换为绝对路径 + absTargetPath, err := filepath.Abs(targetPath) + if err != nil { + absTargetPath = targetPath + } + + // 构建 sync.py 命令参数 + args := []string{ + "/opt/sync.py", + "--source-type", config.SourceType, + "--source-url", config.SourceURL, + "--target-path", absTargetPath, + } + + // Git 分支 + if config.Branch != "" { + args = append(args, "--branch", config.Branch) + } + + // 稀疏路径 + if config.SparsePath != "" { + args = append(args, "--path", config.SparsePath) + } + + // 单文件模式 + if config.SingleFile { + args = append(args, "--single-file") + } + + // 代理设置 + if config.Proxy != "" && config.Proxy != "none" { + args = append(args, "--proxy", config.Proxy) + if config.Proxy == "custom" && config.ProxyURL != "" { + args = append(args, "--proxy-url", config.ProxyURL) + } + } + + // 认证 Token + if config.AuthToken != "" { + args = append(args, "--auth-token", config.AuthToken) + } + + // 准备命令 + ctx, cancel := s.createContext(task.Timeout) + defer cancel() + + // 直接使用 python3 和参数列表,而不是拼接成字符串 + cmd := exec.CommandContext(ctx, "python3", args...) + cmd.Dir = "/opt" + + // 执行命令 + var stdout, stderr bytes.Buffer + cmd.Stdout = &stdout + cmd.Stderr = &stderr + + execErr := cmd.Run() + end := time.Now() + + // 构建命令字符串用于日志记录 + commandStr := "python3 " + strings.Join(args, " ") + + // 构建结果 + result := &TaskExecutionResult{ + TaskID: task.ID, + AgentID: nil, + Command: commandStr, + Output: stdout.String(), + Start: start, + End: end, + Duration: end.Sub(start).Milliseconds(), + } + + if execErr != nil { + result.Status = "failed" + result.Output += "\n[ERROR]\n" + stderr.String() + "\n" + execErr.Error() + if exitErr, ok := execErr.(*exec.ExitError); ok { + result.ExitCode = exitErr.ExitCode() + } else { + result.ExitCode = 1 + } + } else { + result.Status = "success" + result.ExitCode = 0 + } + + // 处理执行结果 + return s.processExecutionResult(result) +}