110 lines
2.1 KiB
Go
110 lines
2.1 KiB
Go
package runner
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"git.0x7f.app/WOJ/woj-server/pkg/file"
|
|
"git.0x7f.app/WOJ/woj-server/pkg/utils"
|
|
"os"
|
|
"os/exec"
|
|
"time"
|
|
)
|
|
|
|
func (s *service) execute(exe string, args ...string) error {
|
|
cmd := exec.Command(exe, args...)
|
|
cmd.Dir = Prefix
|
|
if s.verbose {
|
|
cmd.Stdout = os.Stderr
|
|
cmd.Stderr = os.Stderr
|
|
}
|
|
return cmd.Run()
|
|
}
|
|
|
|
type executeArgs struct {
|
|
exe string
|
|
args []string
|
|
|
|
timeout time.Duration
|
|
kill func() error
|
|
|
|
output *os.File
|
|
limit int64
|
|
}
|
|
|
|
func (s *service) executeTimeout(arg *executeArgs) error {
|
|
ctx, cancel := context.WithTimeout(context.Background(), arg.timeout)
|
|
defer cancel()
|
|
|
|
cmd := exec.CommandContext(ctx, arg.exe, arg.args...)
|
|
cmd.Dir = Prefix
|
|
if arg.kill != nil {
|
|
cmd.Cancel = arg.kill
|
|
}
|
|
if s.verbose && arg.output == nil {
|
|
cmd.Stdout = os.Stderr
|
|
cmd.Stderr = os.Stderr
|
|
} else if arg.output != nil {
|
|
if arg.limit == 0 {
|
|
cmd.Stdout = arg.output
|
|
cmd.Stderr = arg.output
|
|
} else {
|
|
lw := &file.LimitedWriter{
|
|
File: arg.output,
|
|
Limit: arg.limit,
|
|
}
|
|
cmd.Stdout = lw
|
|
cmd.Stderr = lw
|
|
}
|
|
}
|
|
|
|
err := cmd.Start()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = cmd.Wait()
|
|
|
|
// make sure the process is killed
|
|
_ = cmd.Process.Kill()
|
|
|
|
if errors.Is(ctx.Err(), context.DeadlineExceeded) {
|
|
return fmt.Errorf("command timed out")
|
|
}
|
|
|
|
return err
|
|
}
|
|
|
|
type podmanArgs struct {
|
|
executeArgs
|
|
memory string
|
|
}
|
|
|
|
func (s *service) podmanRun(arg *podmanArgs) error {
|
|
name := fmt.Sprintf("woj-%d-%s", time.Now().UnixNano(), utils.RandomString(8))
|
|
execArgs := &executeArgs{
|
|
exe: "podman",
|
|
output: utils.If(arg.output == nil, os.Stderr, arg.output),
|
|
limit: utils.If(arg.limit == 0, 4*1024, arg.limit),
|
|
timeout: utils.If(arg.timeout == 0, 10*time.Second, arg.timeout),
|
|
kill: func() error {
|
|
if arg.kill != nil {
|
|
_ = arg.kill()
|
|
}
|
|
return s.execute("podman", "kill", name)
|
|
},
|
|
}
|
|
|
|
args := []string{
|
|
"run",
|
|
"--rm",
|
|
"--name", name,
|
|
"--memory", utils.If(arg.memory == "", "256m", arg.memory),
|
|
}
|
|
args = append(args, arg.args...)
|
|
|
|
execArgs.args = args
|
|
|
|
return s.executeTimeout(execArgs)
|
|
}
|