fix: shell call bin

This commit is contained in:
engigu
2026-01-11 21:02:14 +08:00
parent 809b02fcfa
commit 0f10b02cc4
2 changed files with 115 additions and 117 deletions
-117
View File
@@ -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()
@@ -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)
}