mirror of
https://github.com/acepanel/panel.git
synced 2026-02-04 07:57:21 +08:00
feat: 优化docker兼容
This commit is contained in:
@@ -10,7 +10,10 @@ import (
|
||||
"os/exec"
|
||||
"slices"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/creack/pty"
|
||||
)
|
||||
|
||||
// Execf 执行 shell 命令
|
||||
@@ -26,12 +29,11 @@ func Execf(shell string, args ...any) (string, error) {
|
||||
cmd.Stdout = &stdout
|
||||
cmd.Stderr = &stderr
|
||||
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
return strings.TrimSpace(stdout.String()), errors.New(strings.TrimSpace(stderr.String()))
|
||||
if err := cmd.Run(); err != nil {
|
||||
return strings.TrimSpace(stdout.String()), fmt.Errorf("run %s failed, err: %s", fmt.Sprintf(shell, args...), strings.TrimSpace(stderr.String()))
|
||||
}
|
||||
|
||||
return strings.TrimSpace(stdout.String()), err
|
||||
return strings.TrimSpace(stdout.String()), nil
|
||||
}
|
||||
|
||||
// ExecfAsync 异步执行 shell 命令
|
||||
@@ -50,7 +52,7 @@ func ExecfAsync(shell string, args ...any) error {
|
||||
|
||||
go func() {
|
||||
if err = cmd.Wait(); err != nil {
|
||||
fmt.Println(err.Error())
|
||||
fmt.Println(fmt.Errorf("run %s failed, err: %s", fmt.Sprintf(shell, args...), strings.TrimSpace(err.Error())))
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -72,7 +74,7 @@ func ExecfWithTimeout(timeout time.Duration, shell string, args ...any) (string,
|
||||
|
||||
err := cmd.Start()
|
||||
if err != nil {
|
||||
return "", err
|
||||
return strings.TrimSpace(stdout.String()), fmt.Errorf("run %s failed, err: %s", fmt.Sprintf(shell, args...), strings.TrimSpace(stderr.String()))
|
||||
}
|
||||
|
||||
done := make(chan error)
|
||||
@@ -83,10 +85,10 @@ func ExecfWithTimeout(timeout time.Duration, shell string, args ...any) (string,
|
||||
select {
|
||||
case <-time.After(timeout):
|
||||
_ = cmd.Process.Kill()
|
||||
return strings.TrimSpace(stdout.String()), errors.New("执行超时")
|
||||
return strings.TrimSpace(stdout.String()), fmt.Errorf("run %s failed, err: %s", fmt.Sprintf(shell, args...), "timeout")
|
||||
case err = <-done:
|
||||
if err != nil {
|
||||
return strings.TrimSpace(stdout.String()), errors.New(strings.TrimSpace(stderr.String()))
|
||||
return strings.TrimSpace(stdout.String()), fmt.Errorf("run %s failed, err: %s", fmt.Sprintf(shell, args...), strings.TrimSpace(stderr.String()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,12 +142,40 @@ func ExecfWithDir(dir, shell string, args ...any) (string, error) {
|
||||
cmd.Stdout = &stdout
|
||||
cmd.Stderr = &stderr
|
||||
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
return strings.TrimSpace(stdout.String()), errors.New(strings.TrimSpace(stderr.String()))
|
||||
if err := cmd.Run(); err != nil {
|
||||
return strings.TrimSpace(stdout.String()), fmt.Errorf("run %s failed, err: %s", fmt.Sprintf(shell, args...), strings.TrimSpace(stderr.String()))
|
||||
}
|
||||
|
||||
return strings.TrimSpace(stdout.String()), err
|
||||
return strings.TrimSpace(stdout.String()), nil
|
||||
}
|
||||
|
||||
// ExecfWithTTY 在伪终端下执行 shell 命令
|
||||
func ExecfWithTTY(shell string, args ...any) (string, error) {
|
||||
if !preCheckArg(args) {
|
||||
return "", errors.New("command contains illegal characters")
|
||||
}
|
||||
|
||||
_ = os.Setenv("LC_ALL", "C")
|
||||
cmd := exec.Command("bash", "-i", "-c", fmt.Sprintf(shell, args...))
|
||||
|
||||
var out bytes.Buffer
|
||||
var stderr bytes.Buffer
|
||||
cmd.Stderr = &stderr // https://github.com/creack/pty/issues/147 取 stderr
|
||||
|
||||
f, err := pty.Start(cmd)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("run %s failed", fmt.Sprintf(shell, args...))
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
if _, err = io.Copy(&out, f); ptyError(err) != nil {
|
||||
return "", fmt.Errorf("run %s failed, out: %s, err: %w", fmt.Sprintf(shell, args...), strings.TrimSpace(out.String()), err)
|
||||
}
|
||||
if stderr.Len() > 0 {
|
||||
return "", fmt.Errorf("run %s failed, out: %s", fmt.Sprintf(shell, args...), strings.TrimSpace(stderr.String()))
|
||||
}
|
||||
|
||||
return strings.TrimSpace(out.String()), nil
|
||||
}
|
||||
|
||||
func preCheckArg(args []any) bool {
|
||||
@@ -158,3 +188,15 @@ func preCheckArg(args []any) bool {
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// Linux kernel return EIO when attempting to read from a master pseudo
|
||||
// terminal which no longer has an open slave. So ignore error here.
|
||||
// See https://github.com/creack/pty/issues/21
|
||||
func ptyError(err error) error {
|
||||
var pathErr *os.PathError
|
||||
if !errors.As(err, &pathErr) || !errors.Is(pathErr.Err, syscall.EIO) {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user