From b424f6ff8afaf1e3583085c6c91c26869df221a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=AB=98=E7=84=B6?= Date: Sun, 8 Mar 2026 15:44:48 +0800 Subject: [PATCH] chore(execd): complete the work for #332, and fix the linter errors. --- components/execd/main.go | 3 +- components/execd/pkg/runtime/command.go | 29 ++++++++----------- components/execd/pkg/runtime/types.go | 19 ++++++------ .../execd/pkg/web/controller/command.go | 4 +++ .../execd/pkg/web/model/codeinterpreting.go | 3 ++ 5 files changed, 31 insertions(+), 27 deletions(-) diff --git a/components/execd/main.go b/components/execd/main.go index 8e09e90f..f53f198d 100644 --- a/components/execd/main.go +++ b/components/execd/main.go @@ -17,6 +17,8 @@ package main import ( "fmt" + "github.com/alibaba/opensandbox/internal/version" + _ "go.uber.org/automaxprocs/maxprocs" "github.com/alibaba/opensandbox/execd/pkg/flag" @@ -24,7 +26,6 @@ import ( _ "github.com/alibaba/opensandbox/execd/pkg/util/safego" "github.com/alibaba/opensandbox/execd/pkg/web" "github.com/alibaba/opensandbox/execd/pkg/web/controller" - "github.com/alibaba/opensandbox/internal/version" ) // main initializes and starts the execd server. diff --git a/components/execd/pkg/runtime/command.go b/components/execd/pkg/runtime/command.go index c300a97a..cec6213c 100644 --- a/components/execd/pkg/runtime/command.go +++ b/components/execd/pkg/runtime/command.go @@ -37,7 +37,7 @@ import ( func buildCredential(uid, gid *uint32) (*syscall.Credential, error) { if uid == nil && gid == nil { - return nil, nil + return nil, nil //nolint:nilnil } cred := &syscall.Credential{} @@ -95,9 +95,20 @@ func (c *Controller) runCommand(ctx context.Context, request *ExecuteCodeRequest log.Info("received command: %v", request.Code) cmd := exec.CommandContext(ctx, "bash", "-c", request.Code) + // Configure credentials and process group + cred, err := buildCredential(request.Uid, request.Gid) + if err != nil { + return fmt.Errorf("failed to build credential: %w", err) + } + cmd.SysProcAttr = &syscall.SysProcAttr{ + Setpgid: true, + Credential: cred, + } + cmd.Stdout = stdout cmd.Stderr = stderr cmd.Env = mergeEnvs(os.Environ(), loadExtraEnvFromFile()) + cmd.Dir = request.Cwd done := make(chan struct{}, 1) var wg sync.WaitGroup @@ -111,20 +122,7 @@ func (c *Controller) runCommand(ctx context.Context, request *ExecuteCodeRequest c.tailStdPipe(stderrPath, request.Hooks.OnExecuteStderr, done) }) - cmd.Dir = request.Cwd - - // Configure credentials and process group - cred, err := buildCredential(request.Uid, request.Gid) - if err != nil { - log.Error("failed to build credentials: %v", err) - } - cmd.SysProcAttr = &syscall.SysProcAttr{ - Setpgid: true, - Credential: cred, - } - err = cmd.Start() - if err != nil { request.Hooks.OnExecuteInit(session) request.Hooks.OnExecuteError(&execute.ErrorOutput{EName: "CommandExecError", EValue: err.Error()}) @@ -219,9 +217,7 @@ func (c *Controller) runBackgroundCommand(ctx context.Context, cancel context.Ca startAt := time.Now() log.Info("received command: %v", request.Code) cmd := exec.CommandContext(ctx, "bash", "-c", request.Code) - cmd.Dir = request.Cwd - // Configure credentials and process group cred, err := buildCredential(request.Uid, request.Gid) if err != nil { @@ -233,7 +229,6 @@ func (c *Controller) runBackgroundCommand(ctx context.Context, cancel context.Ca } cmd.Stdout = pipe - cmd.Stderr = pipe cmd.Env = mergeEnvs(os.Environ(), loadExtraEnvFromFile()) diff --git a/components/execd/pkg/runtime/types.go b/components/execd/pkg/runtime/types.go index b4322f8d..4dc459b3 100644 --- a/components/execd/pkg/runtime/types.go +++ b/components/execd/pkg/runtime/types.go @@ -34,16 +34,17 @@ type ExecuteResultHook struct { // ExecuteCodeRequest represents a code execution request with context and hooks. type ExecuteCodeRequest struct { - Language Language `json:"language"` - Code string `json:"code"` - Context string `json:"context"` - Timeout time.Duration `json:"timeout"` - Cwd string `json:"cwd"` - Envs map[string]string `json:"envs"` - Uid *uint32 `json:"uid,omitempty"` - Gid *uint32 `json:"gid,omitempty"` - Hooks ExecuteResultHook + Language Language `json:"language"` + Code string `json:"code"` + Context string `json:"context"` + Timeout time.Duration `json:"timeout"` + Cwd string `json:"cwd"` + Envs map[string]string `json:"envs"` + Uid *uint32 `json:"uid,omitempty"` + Gid *uint32 `json:"gid,omitempty"` + Hooks ExecuteResultHook } + // SetDefaultHooks installs stdout logging fallbacks for unset hooks. func (req *ExecuteCodeRequest) SetDefaultHooks() { if req.Hooks.OnExecuteResult == nil { diff --git a/components/execd/pkg/web/controller/command.go b/components/execd/pkg/web/controller/command.go index 9d61308b..98590ae4 100644 --- a/components/execd/pkg/web/controller/command.go +++ b/components/execd/pkg/web/controller/command.go @@ -133,6 +133,8 @@ func (c *CodeInterpretingController) buildExecuteCommandRequest(request model.Ru Code: request.Command, Cwd: request.Cwd, Timeout: timeout, + Gid: request.Gid, + Uid: request.Uid, } } else { return &runtime.ExecuteCodeRequest{ @@ -140,6 +142,8 @@ func (c *CodeInterpretingController) buildExecuteCommandRequest(request model.Ru Code: request.Command, Cwd: request.Cwd, Timeout: timeout, + Gid: request.Gid, + Uid: request.Uid, } } } diff --git a/components/execd/pkg/web/model/codeinterpreting.go b/components/execd/pkg/web/model/codeinterpreting.go index adc6452c..aa028f1f 100644 --- a/components/execd/pkg/web/model/codeinterpreting.go +++ b/components/execd/pkg/web/model/codeinterpreting.go @@ -53,6 +53,9 @@ type RunCommandRequest struct { Background bool `json:"background,omitempty"` // TimeoutMs caps execution duration; 0 uses server default. TimeoutMs int64 `json:"timeout,omitempty" validate:"omitempty,gte=1"` + + Uid *uint32 `json:"uid,omitempty"` + Gid *uint32 `json:"gid,omitempty"` } func (r *RunCommandRequest) Validate() error {