diff --git a/hrp/build.go b/hrp/build.go index 9cecccfb..bf950fde 100644 --- a/hrp/build.go +++ b/hrp/build.go @@ -6,7 +6,6 @@ import ( "fmt" "html/template" "os" - "os/exec" "path/filepath" "regexp" "strings" @@ -16,6 +15,7 @@ import ( "github.com/rs/zerolog/log" "github.com/httprunner/httprunner/v4/hrp/internal/builtin" + "github.com/httprunner/httprunner/v4/hrp/internal/myexec" "github.com/httprunner/httprunner/v4/hrp/internal/version" ) @@ -128,26 +128,26 @@ func (pt *pluginTemplate) generateGo(output string) error { } // check go sdk in tempDir - if err := builtin.ExecCommandInDir(exec.Command("go", "version"), pluginDir); err != nil { + if err := myexec.RunCommand("go", "version"); err != nil { return errors.Wrap(err, "go sdk not installed") } if !builtin.IsFilePathExists(filepath.Join(pluginDir, "go.mod")) { // create go mod - if err := builtin.ExecCommandInDir(exec.Command("go", "mod", "init", "main"), pluginDir); err != nil { + if err := myexec.ExecCommandInDir(myexec.Command("go", "mod", "init", "main"), pluginDir); err != nil { return err } // download plugin dependency // funplugin version should be locked funplugin := fmt.Sprintf("github.com/httprunner/funplugin@%s", shared.Version) - if err := builtin.ExecCommandInDir(exec.Command("go", "get", funplugin), pluginDir); err != nil { + if err := myexec.ExecCommandInDir(myexec.Command("go", "get", funplugin), pluginDir); err != nil { return errors.Wrap(err, "go get funplugin failed") } } // add missing and remove unused modules - if err := builtin.ExecCommandInDir(exec.Command("go", "mod", "tidy"), pluginDir); err != nil { + if err := myexec.ExecCommandInDir(myexec.Command("go", "mod", "tidy"), pluginDir); err != nil { return errors.Wrap(err, "go mod tidy failed") } @@ -161,8 +161,8 @@ func (pt *pluginTemplate) generateGo(output string) error { outputPath, _ := filepath.Abs(output) // build go plugin to debugtalk.bin - cmd := exec.Command("go", "build", "-o", outputPath, PluginGoSourceGenFile, filepath.Base(pt.path)) - if err := builtin.ExecCommandInDir(cmd, pluginDir); err != nil { + cmd := myexec.Command("go", "build", "-o", outputPath, PluginGoSourceGenFile, filepath.Base(pt.path)) + if err := myexec.ExecCommandInDir(cmd, pluginDir); err != nil { return errors.Wrap(err, "go build plugin failed") } log.Info().Str("output", outputPath).Str("plugin", pt.path).Msg("build go plugin successfully") @@ -194,7 +194,7 @@ func buildGo(path string, output string) error { func buildPy(path string, output string) error { log.Info().Str("path", path).Str("output", output).Msg("start to prepare python plugin") // check the syntax of debugtalk.py - err := builtin.ExecPython3Command("py_compile", path) + err := myexec.ExecPython3Command("py_compile", path) if err != nil { return errors.Wrap(err, "python plugin syntax invalid") } diff --git a/hrp/cmd/convert.go b/hrp/cmd/convert.go index 96d3e985..51f25a9e 100644 --- a/hrp/cmd/convert.go +++ b/hrp/cmd/convert.go @@ -7,7 +7,7 @@ import ( "github.com/rs/zerolog/log" "github.com/spf13/cobra" - "github.com/httprunner/httprunner/v4/hrp/internal/builtin" + "github.com/httprunner/httprunner/v4/hrp/internal/myexec" "github.com/httprunner/httprunner/v4/hrp/internal/version" "github.com/httprunner/httprunner/v4/hrp/pkg/convert" ) @@ -63,7 +63,7 @@ func convertRun(cmd *cobra.Command, args []string) error { packages := []string{ fmt.Sprintf("httprunner==%s", version.VERSION), } - _, err := builtin.EnsurePython3Venv(venv, packages...) + _, err := myexec.EnsurePython3Venv(venv, packages...) if err != nil { log.Error().Err(err).Msg("python3 venv is not ready") return err diff --git a/hrp/cmd/pytest.go b/hrp/cmd/pytest.go index 2e1933ad..0ebfaa69 100644 --- a/hrp/cmd/pytest.go +++ b/hrp/cmd/pytest.go @@ -6,7 +6,7 @@ import ( "github.com/rs/zerolog/log" "github.com/spf13/cobra" - "github.com/httprunner/httprunner/v4/hrp/internal/builtin" + "github.com/httprunner/httprunner/v4/hrp/internal/myexec" "github.com/httprunner/httprunner/v4/hrp/internal/pytest" "github.com/httprunner/httprunner/v4/hrp/internal/version" ) @@ -23,7 +23,7 @@ var pytestCmd = &cobra.Command{ packages := []string{ fmt.Sprintf("httprunner==%s", version.VERSION), } - _, err := builtin.EnsurePython3Venv(venv, packages...) + _, err := myexec.EnsurePython3Venv(venv, packages...) if err != nil { log.Error().Err(err).Msg("python3 venv is not ready") return err diff --git a/hrp/internal/builtin/utils.go b/hrp/internal/builtin/utils.go index 18b60a93..c79939c8 100644 --- a/hrp/internal/builtin/utils.go +++ b/hrp/internal/builtin/utils.go @@ -12,7 +12,6 @@ import ( "math" "math/rand" "os" - "os/exec" "path/filepath" "reflect" "strconv" @@ -23,7 +22,6 @@ import ( "github.com/rs/zerolog/log" "gopkg.in/yaml.v3" - "github.com/httprunner/httprunner/v4/hrp/internal/env" "github.com/httprunner/httprunner/v4/hrp/internal/json" ) @@ -94,117 +92,6 @@ func FormatResponse(raw interface{}) interface{} { return formattedResponse } -var python3Executable string = "python3" // system default python3 - -// EnsurePython3Venv ensures python3 venv with specified packages -// venv should be directory path of target venv -func EnsurePython3Venv(venv string, packages ...string) (python3 string, err error) { - // priority: specified > $HOME/.hrp/venv - if venv == "" { - home, err := os.UserHomeDir() - if err != nil { - return "", errors.Wrap(err, "get user home dir failed") - } - venv = filepath.Join(home, ".hrp", "venv") - } - python3, err = ensurePython3Venv(venv, packages...) - if err != nil { - return "", errors.Wrap(err, "prepare python3 venv failed") - } - python3Executable = python3 - log.Info().Str("Python3Executable", python3Executable).Msg("set python3 executable path") - return python3, nil -} - -func ExecPython3Command(cmdName string, args ...string) error { - args = append([]string{"-m", cmdName}, args...) - return ExecCommand(python3Executable, args...) -} - -func AssertPythonPackage(python3 string, pkgName, pkgVersion string) error { - out, err := exec.Command( - python3, "-c", fmt.Sprintf("import %s; print(%s.__version__)", pkgName, pkgName), - ).Output() - if err != nil { - return fmt.Errorf("python package %s not found", pkgName) - } - - // do not check version if pkgVersion is empty - if pkgVersion == "" { - log.Info().Str("name", pkgName).Msg("python package is ready") - return nil - } - - // check package version equality - version := strings.TrimSpace(string(out)) - if strings.TrimLeft(version, "v") != strings.TrimLeft(pkgVersion, "v") { - return fmt.Errorf("python package %s version %s not matched, please upgrade to %s", - pkgName, version, pkgVersion) - } - - log.Info().Str("name", pkgName).Str("version", pkgVersion).Msg("python package is ready") - return nil -} - -func InstallPythonPackage(python3 string, pkg string) (err error) { - var pkgName, pkgVersion string - if strings.Contains(pkg, "==") { - // funppy==0.5.0 - pkgInfo := strings.Split(pkg, "==") - pkgName = pkgInfo[0] - pkgVersion = pkgInfo[1] - } else { - // funppy - pkgName = pkg - } - - // check if package installed and version matched - err = AssertPythonPackage(python3, pkgName, pkgVersion) - if err == nil { - return nil - } - - // check if pip available - err = ExecCommand(python3, "-m", "pip", "--version") - if err != nil { - log.Warn().Msg("pip is not available") - return errors.Wrap(err, "pip is not available") - } - - log.Info().Str("pkgName", pkgName).Str("pkgVersion", pkgVersion).Msg("installing python package") - - // install package - pypiIndexURL := env.PYPI_INDEX_URL - if pypiIndexURL == "" { - pypiIndexURL = "https://pypi.org/simple" // default - } - err = ExecCommand(python3, "-m", "pip", "install", "--upgrade", pkg, - "--index-url", pypiIndexURL, - "--quiet", "--disable-pip-version-check") - if err != nil { - return errors.Wrap(err, "pip install package failed") - } - - return AssertPythonPackage(python3, pkgName, pkgVersion) -} - -func ExecCommandInDir(cmd *exec.Cmd, dir string) error { - log.Info().Str("cmd", cmd.String()).Str("dir", dir).Msg("exec command") - cmd.Dir = dir - - // print output with colors - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - - err := cmd.Run() - if err != nil { - log.Error().Err(err).Msg("exec command failed") - return err - } - - return nil -} - func CreateFolder(folderPath string) error { log.Info().Str("path", folderPath).Msg("create folder") err := os.MkdirAll(folderPath, os.ModePerm) @@ -289,19 +176,19 @@ func GetRandomNumber(min, max int) int { } func Interface2Float64(i interface{}) (float64, error) { - switch i.(type) { + switch v := i.(type) { case int: - return float64(i.(int)), nil + return float64(v), nil case int32: - return float64(i.(int32)), nil + return float64(v), nil case int64: - return float64(i.(int64)), nil + return float64(v), nil case float32: - return float64(i.(float32)), nil + return float64(v), nil case float64: - return i.(float64), nil + return v, nil case string: - intVar, err := strconv.Atoi(i.(string)) + intVar, err := strconv.Atoi(v) if err != nil { return 0, err } diff --git a/hrp/internal/dial/curl.go b/hrp/internal/dial/curl.go index 8cd3436a..f3940799 100644 --- a/hrp/internal/dial/curl.go +++ b/hrp/internal/dial/curl.go @@ -4,13 +4,13 @@ import ( "bytes" "fmt" "os" - "os/exec" "path/filepath" "time" "github.com/rs/zerolog/log" "github.com/httprunner/httprunner/v4/hrp/internal/builtin" + "github.com/httprunner/httprunner/v4/hrp/internal/myexec" ) const ( @@ -46,7 +46,7 @@ func DoCurl(args []string) (err error) { } }() - cmd := exec.Command("curl", args...) + cmd := myexec.Command("curl", args...) var stdout, stderr bytes.Buffer cmd.Stdout = &stdout cmd.Stderr = &stderr @@ -60,11 +60,11 @@ func DoCurl(args []string) (err error) { return } if stdout.String() != "" { - fmt.Printf(stdout.String()) + fmt.Println(stdout.String()) curlResult.Result = stdout.String() curlResult.ResultType = normalResult } else if stderr.String() != "" { - fmt.Printf(stderr.String()) + fmt.Println(stderr.String()) curlResult.ErrorMsg = stderr.String() curlResult.ResultType = errorResult } diff --git a/hrp/internal/dial/traceroute_unix.go b/hrp/internal/dial/traceroute_unix.go index d9d309c8..52742666 100644 --- a/hrp/internal/dial/traceroute_unix.go +++ b/hrp/internal/dial/traceroute_unix.go @@ -7,7 +7,6 @@ import ( "fmt" "net/url" "os" - "os/exec" "path/filepath" "regexp" "strconv" @@ -18,6 +17,7 @@ import ( "github.com/rs/zerolog/log" "github.com/httprunner/httprunner/v4/hrp/internal/builtin" + "github.com/httprunner/httprunner/v4/hrp/internal/myexec" ) var ( @@ -51,7 +51,7 @@ func DoTraceRoute(traceRouteOptions *TraceRouteOptions, args []string) (err erro traceRouteTarget = strings.Split(parsedURL.Host, ":")[0] } - cmd := exec.Command("traceroute", "-m", strconv.Itoa(traceRouteOptions.MaxTTL), + cmd := myexec.Command("traceroute", "-m", strconv.Itoa(traceRouteOptions.MaxTTL), "-q", strconv.Itoa(traceRouteOptions.Queries), traceRouteTarget) stdout, _ := cmd.StdoutPipe() diff --git a/hrp/internal/dial/traceroute_windows.go b/hrp/internal/dial/traceroute_windows.go index f8ce4743..7aa0581c 100644 --- a/hrp/internal/dial/traceroute_windows.go +++ b/hrp/internal/dial/traceroute_windows.go @@ -7,7 +7,6 @@ import ( "fmt" "net/url" "os" - "os/exec" "path/filepath" "regexp" "strconv" @@ -49,7 +48,7 @@ func DoTraceRoute(traceRouteOptions *TraceRouteOptions, args []string) (err erro traceRouteTarget = strings.Split(parsedURL.Host, ":")[0] } - cmd := exec.Command("tracert", "-h", strconv.Itoa(traceRouteOptions.MaxTTL), traceRouteTarget) + cmd := myexec.Command("tracert", "-h", strconv.Itoa(traceRouteOptions.MaxTTL), traceRouteTarget) stdout, _ := cmd.StdoutPipe() startT := time.Now() diff --git a/hrp/internal/myexec/cmd.go b/hrp/internal/myexec/cmd.go new file mode 100644 index 00000000..3876008e --- /dev/null +++ b/hrp/internal/myexec/cmd.go @@ -0,0 +1,162 @@ +package myexec + +import ( + "fmt" + "os" + "os/exec" + "path/filepath" + "strings" + + "github.com/pkg/errors" + "github.com/rs/zerolog/log" + + "github.com/httprunner/httprunner/v4/hrp/internal/env" +) + +var python3Executable string = "python3" // system default python3 + +func isPython3(python string) bool { + out, err := Command(python, "--version").Output() + if err != nil { + return false + } + if strings.HasPrefix(string(out), "Python 3") { + return true + } + return false +} + +// EnsurePython3Venv ensures python3 venv with specified packages +// venv should be directory path of target venv +func EnsurePython3Venv(venv string, packages ...string) (python3 string, err error) { + // priority: specified > $HOME/.hrp/venv + if venv == "" { + home, err := os.UserHomeDir() + if err != nil { + return "", errors.Wrap(err, "get user home dir failed") + } + venv = filepath.Join(home, ".hrp", "venv") + } + python3, err = ensurePython3Venv(venv, packages...) + if err != nil { + return "", errors.Wrap(err, "prepare python3 venv failed") + } + python3Executable = python3 + log.Info().Str("Python3Executable", python3Executable).Msg("set python3 executable path") + return python3, nil +} + +func ExecPython3Command(cmdName string, args ...string) error { + args = append([]string{"-m", cmdName}, args...) + return RunCommand(python3Executable, args...) +} + +func AssertPythonPackage(python3 string, pkgName, pkgVersion string) error { + out, err := exec.Command( + python3, "-c", fmt.Sprintf("import %s; print(%s.__version__)", pkgName, pkgName), + ).Output() + if err != nil { + return fmt.Errorf("python package %s not found", pkgName) + } + + // do not check version if pkgVersion is empty + if pkgVersion == "" { + log.Info().Str("name", pkgName).Msg("python package is ready") + return nil + } + + // check package version equality + version := strings.TrimSpace(string(out)) + if strings.TrimLeft(version, "v") != strings.TrimLeft(pkgVersion, "v") { + return fmt.Errorf("python package %s version %s not matched, please upgrade to %s", + pkgName, version, pkgVersion) + } + + log.Info().Str("name", pkgName).Str("version", pkgVersion).Msg("python package is ready") + return nil +} + +func InstallPythonPackage(python3 string, pkg string) (err error) { + var pkgName, pkgVersion string + if strings.Contains(pkg, "==") { + // funppy==0.5.0 + pkgInfo := strings.Split(pkg, "==") + pkgName = pkgInfo[0] + pkgVersion = pkgInfo[1] + } else { + // funppy + pkgName = pkg + } + + // check if package installed and version matched + err = AssertPythonPackage(python3, pkgName, pkgVersion) + if err == nil { + return nil + } + + // check if pip available + err = RunCommand(python3, "-m", "pip", "--version") + if err != nil { + log.Warn().Msg("pip is not available") + return errors.Wrap(err, "pip is not available") + } + + log.Info().Str("pkgName", pkgName).Str("pkgVersion", pkgVersion).Msg("installing python package") + + // install package + pypiIndexURL := env.PYPI_INDEX_URL + if pypiIndexURL == "" { + pypiIndexURL = "https://pypi.org/simple" // default + } + err = RunCommand(python3, "-m", "pip", "install", "--upgrade", pkg, + "--index-url", pypiIndexURL, + "--quiet", "--disable-pip-version-check") + if err != nil { + return errors.Wrap(err, "pip install package failed") + } + + return AssertPythonPackage(python3, pkgName, pkgVersion) +} + +func RunCommand(cmdName string, args ...string) error { + cmd := Command(cmdName, args...) + log.Info().Str("cmd", cmd.String()).Msg("exec command") + + // add cmd dir path to $PATH + if cmdDir := filepath.Dir(cmdName); cmdDir != "" { + path := fmt.Sprintf("%s:%s", cmdDir, env.PATH) + if err := os.Setenv("PATH", path); err != nil { + log.Error().Err(err).Msg("set env $PATH failed") + return err + } + } + + // print output with colors + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + + err := cmd.Run() + if err != nil { + log.Error().Err(err).Msg("exec command failed") + return err + } + + return nil +} + +func ExecCommandInDir(cmd *exec.Cmd, dir string) error { + log.Info().Str("cmd", cmd.String()).Str("dir", dir).Msg("exec command") + cmd.Dir = dir + + // print output with colors + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + + err := cmd.Run() + if err != nil { + log.Error().Err(err).Msg("exec command failed") + return err + } + + return nil +} diff --git a/hrp/internal/builtin/utils_unix.go b/hrp/internal/myexec/cmd_uixt.go similarity index 51% rename from hrp/internal/builtin/utils_unix.go rename to hrp/internal/myexec/cmd_uixt.go index 89b6a4f5..39c64085 100644 --- a/hrp/internal/builtin/utils_unix.go +++ b/hrp/internal/myexec/cmd_uixt.go @@ -1,31 +1,18 @@ //go:build darwin || linux -package builtin +package myexec import ( "fmt" "os" "os/exec" "path/filepath" - "strings" + "syscall" "github.com/pkg/errors" "github.com/rs/zerolog/log" - - "github.com/httprunner/httprunner/v4/hrp/internal/env" ) -func isPython3(python string) bool { - out, err := exec.Command(python, "--version").Output() - if err != nil { - return false - } - if strings.HasPrefix(string(out), "Python 3") { - return true - } - return false -} - func getPython3Executable(venvDir string) string { return filepath.Join(venvDir, "bin", "python3") } @@ -42,20 +29,20 @@ func ensurePython3Venv(venv string, packages ...string) (python3 string, err err if !isPython3(python3) { // python3 venv not available, create one // check if system python3 is available - if err := ExecCommand("python3", "--version"); err != nil { + if err := RunCommand("python3", "--version"); err != nil { return "", errors.Wrap(err, "python3 not found") } // check if .venv exists if _, err := os.Stat(venv); err == nil { // .venv exists, remove first - if err := ExecCommand("rm", "-rf", venv); err != nil { + if err := RunCommand("rm", "-rf", venv); err != nil { return "", errors.Wrap(err, "remove existed venv failed") } } // create python3 .venv - if err := ExecCommand("python3", "-m", "venv", venv); err != nil { + if err := RunCommand("python3", "-m", "venv", venv); err != nil { return "", errors.Wrap(err, "create python3 venv failed") } } @@ -72,32 +59,13 @@ func ensurePython3Venv(venv string, packages ...string) (python3 string, err err } func Command(name string, arg ...string) *exec.Cmd { - args := strings.Join(arg, " ") - return exec.Command("bash", "-c", name, args) + cmd := exec.Command(name, arg...) + cmd.SysProcAttr = &syscall.SysProcAttr{ + Setpgid: true, + } + return cmd } -func ExecCommand(cmdName string, args ...string) error { - cmd := exec.Command(cmdName, args...) - log.Info().Str("cmd", cmd.String()).Msg("exec command") - - // add cmd dir path to $PATH - if cmdDir := filepath.Dir(cmdName); cmdDir != "" { - PATH := fmt.Sprintf("%s:%s", cmdDir, env.PATH) - if err := os.Setenv("PATH", PATH); err != nil { - log.Error().Err(err).Msg("set env $PATH failed") - return err - } - } - - // print output with colors - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - - err := cmd.Run() - if err != nil { - log.Error().Err(err).Msg("exec command failed") - return err - } - - return nil +func KillProcessesByGpid(cmd *exec.Cmd) error { + return syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL) } diff --git a/hrp/internal/builtin/utils_windows.go b/hrp/internal/myexec/cmd_windows.go similarity index 77% rename from hrp/internal/builtin/utils_windows.go rename to hrp/internal/myexec/cmd_windows.go index 52aea058..c70cac84 100644 --- a/hrp/internal/builtin/utils_windows.go +++ b/hrp/internal/myexec/cmd_windows.go @@ -1,15 +1,11 @@ //go:build windows -package builtin +package myexec import ( - "fmt" - "os" "os/exec" - "path/filepath" - "strings" + "syscall" - "github.com/pkg/errors" "github.com/rs/zerolog/log" ) @@ -20,17 +16,6 @@ func init() { } } -func isPython3(python string) bool { - out, err := exec.Command("cmd", "/c", python, "--version").Output() - if err != nil { - return false - } - if strings.HasPrefix(string(out), "Python 3") { - return true - } - return false -} - func getPython3Executable(venvDir string) string { python := filepath.Join(venvDir, "Scripts", "python3.exe") if isPython3(python) { @@ -101,26 +86,17 @@ func ensurePython3Venv(venvDir string, packages ...string) (python3 string, err } func Command(name string, arg ...string) *exec.Cmd { - args := strings.Join(arg, " ") - return exec.Command("cmd", "/c", name, args) -} - -func ExecCommand(cmdName string, args ...string) error { // "cmd /c" carries out the command specified by string and then stops // refer: https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/cmd - cmdStr := fmt.Sprintf("%s %s", cmdName, strings.Join(args, " ")) - cmd := exec.Command("cmd", "/c", cmdStr) - log.Info().Str("cmd", cmd.String()).Msg("exec command") - - // print output with colors - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - - err := cmd.Run() - if err != nil { - log.Error().Err(err).Msg("exec command failed") - return err + cmd := exec.Command("cmd.exe") + cmd.SysProcAttr = &syscall.SysProcAttr{ + CmdLine: strings.Join(append([]string{"/c", name}, arg...), " "), + HideWindow: true, } - - return nil + return cmd +} + +func KillProcessesByGpid(cmd *exec.Cmd) error { + killCmd := Command("taskkill", "/T", "/F", "/PID ", strconv.Itoa(cmd.Process.Pid)) + return killCmd.Run() } diff --git a/hrp/internal/pytest/main.go b/hrp/internal/pytest/main.go index dde5f0ae..c9bec74b 100644 --- a/hrp/internal/pytest/main.go +++ b/hrp/internal/pytest/main.go @@ -1,7 +1,7 @@ package pytest import ( - "github.com/httprunner/httprunner/v4/hrp/internal/builtin" + "github.com/httprunner/httprunner/v4/hrp/internal/myexec" "github.com/httprunner/httprunner/v4/hrp/internal/sdk" ) @@ -12,5 +12,5 @@ func RunPytest(args []string) error { }) args = append([]string{"run"}, args...) - return builtin.ExecPython3Command("httprunner", args...) + return myexec.ExecPython3Command("httprunner", args...) } diff --git a/hrp/internal/scaffold/main.go b/hrp/internal/scaffold/main.go index f27a035a..28b2c851 100644 --- a/hrp/internal/scaffold/main.go +++ b/hrp/internal/scaffold/main.go @@ -4,7 +4,6 @@ import ( "embed" "fmt" "os" - "os/exec" "path/filepath" "time" @@ -14,6 +13,7 @@ import ( "github.com/httprunner/httprunner/v4/hrp" "github.com/httprunner/httprunner/v4/hrp/internal/builtin" + "github.com/httprunner/httprunner/v4/hrp/internal/myexec" "github.com/httprunner/httprunner/v4/hrp/internal/sdk" "github.com/httprunner/httprunner/v4/hrp/internal/version" ) @@ -177,7 +177,7 @@ func CreateScaffold(projectName string, pluginType PluginType, venv string, forc func createGoPlugin(projectName string) error { log.Info().Msg("start to create hashicorp go plugin") // check go sdk - if err := builtin.ExecCommandInDir(exec.Command("go", "version"), projectName); err != nil { + if err := myexec.RunCommand("go", "version"); err != nil { return errors.Wrap(err, "go sdk not installed") } @@ -209,7 +209,7 @@ func createPythonPlugin(projectName, venv string) error { fmt.Sprintf("funppy==%s", fungo.Version), fmt.Sprintf("httprunner==%s", version.VERSION), } - _, err = builtin.EnsurePython3Venv(venv, packages...) + _, err = myexec.EnsurePython3Venv(venv, packages...) if err != nil { return err } diff --git a/hrp/internal/wiki/main.go b/hrp/internal/wiki/main.go index 108edca6..2557e499 100644 --- a/hrp/internal/wiki/main.go +++ b/hrp/internal/wiki/main.go @@ -1,10 +1,9 @@ package wiki import ( - "os/exec" - "github.com/rs/zerolog/log" + "github.com/httprunner/httprunner/v4/hrp/internal/myexec" "github.com/httprunner/httprunner/v4/hrp/internal/sdk" ) @@ -14,5 +13,5 @@ func OpenWiki() error { Action: "hrp wiki", }) log.Info().Msgf("%s https://httprunner.com", openCmd) - return exec.Command(openCmd, "https://httprunner.com").Run() + return myexec.RunCommand(openCmd, "https://httprunner.com") } diff --git a/hrp/pkg/convert/converter.go b/hrp/pkg/convert/converter.go index 4c69296e..cf537869 100644 --- a/hrp/pkg/convert/converter.go +++ b/hrp/pkg/convert/converter.go @@ -13,6 +13,7 @@ import ( "github.com/httprunner/httprunner/v4/hrp" "github.com/httprunner/httprunner/v4/hrp/internal/builtin" + "github.com/httprunner/httprunner/v4/hrp/internal/myexec" "github.com/httprunner/httprunner/v4/hrp/internal/sdk" ) @@ -212,7 +213,7 @@ func (c *TCaseConverter) ToPyTest() (string, error) { } args := append([]string{"make"}, jsonPath) - err = builtin.ExecPython3Command("httprunner", args...) + err = myexec.ExecPython3Command("httprunner", args...) if err != nil { return "", err } diff --git a/hrp/pkg/convert/from_gotest.go b/hrp/pkg/convert/from_gotest.go index 04897c76..eecde5a5 100644 --- a/hrp/pkg/convert/from_gotest.go +++ b/hrp/pkg/convert/from_gotest.go @@ -7,7 +7,7 @@ import ( "github.com/rs/zerolog/log" "github.com/httprunner/httprunner/v4/hrp" - "github.com/httprunner/httprunner/v4/hrp/internal/builtin" + "github.com/httprunner/httprunner/v4/hrp/internal/myexec" ) func convert2GoTestScripts(paths ...string) error { @@ -48,7 +48,7 @@ func convert2GoTestScripts(paths ...string) error { } // format pytest scripts with black - return builtin.ExecPython3Command("black", pytestPaths...) + return myexec.ExecPython3Command("black", pytestPaths...) } //go:embed testcase.tmpl diff --git a/hrp/pkg/uixt/android_device.go b/hrp/pkg/uixt/android_device.go index d2dad7e3..8fbd713b 100644 --- a/hrp/pkg/uixt/android_device.go +++ b/hrp/pkg/uixt/android_device.go @@ -8,14 +8,13 @@ import ( "os/exec" "reflect" "strings" - "syscall" "github.com/electricbubble/gadb" "github.com/pkg/errors" "github.com/rs/zerolog/log" - "github.com/httprunner/httprunner/v4/hrp/internal/builtin" "github.com/httprunner/httprunner/v4/hrp/internal/json" + "github.com/httprunner/httprunner/v4/hrp/internal/myexec" ) var ( @@ -250,20 +249,25 @@ func (l *DeviceLogcat) Errors() (err error) { func (l *DeviceLogcat) CatchLogcat() (err error) { if l.cmd != nil { - err = fmt.Errorf("logcat already start") + log.Warn().Msg("logcat already start") + return nil + } + + // clear logcat + if err = myexec.RunCommand("adb", "-s", l.serial, "logcat", "-c"); err != nil { return } - cmdLine := fmt.Sprintf("adb -s %s logcat -c && adb -s %s logcat -v time -s iesqaMonitor:V", l.serial, l.serial) - l.cmd = builtin.Command(cmdLine) + + // start logcat + l.cmd = myexec.Command("adb", "-s", l.serial, "logcat", "-v", "time", "-s", "iesqaMonitor:V") l.cmd.Stderr = l.logBuffer l.cmd.Stdout = l.logBuffer - l.cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true} if err = l.cmd.Start(); err != nil { return } go func() { <-l.stopping - if e := syscall.Kill(-l.cmd.Process.Pid, syscall.SIGKILL); e != nil { + if e := myexec.KillProcessesByGpid(l.cmd); e != nil { l.errs = append(l.errs, fmt.Errorf("kill logcat process err:%v", e)) } l.done <- struct{}{} @@ -273,8 +277,7 @@ func (l *DeviceLogcat) CatchLogcat() (err error) { func (l *DeviceLogcat) BufferedLogcat() (err error) { // -d: dump the current buffered logcat result and exits - cmdLine := fmt.Sprintf("adb -s %s logcat -d", l.serial) - cmd := builtin.Command(cmdLine) + cmd := myexec.Command("adb", "-s", l.serial, "logcat", "-d") cmd.Stdout = l.logBuffer cmd.Stderr = l.logBuffer if err = cmd.Run(); err != nil { diff --git a/hrp/plugin.go b/hrp/plugin.go index fad9aa7a..f28558a2 100644 --- a/hrp/plugin.go +++ b/hrp/plugin.go @@ -11,7 +11,7 @@ import ( "github.com/httprunner/funplugin/fungo" "github.com/rs/zerolog/log" - "github.com/httprunner/httprunner/v4/hrp/internal/builtin" + "github.com/httprunner/httprunner/v4/hrp/internal/myexec" "github.com/httprunner/httprunner/v4/hrp/internal/sdk" ) @@ -59,7 +59,7 @@ func initPlugin(path, venv string, logOn bool) (plugin funplugin.IPlugin, err er packages := []string{ fmt.Sprintf("funppy==%s", fungo.Version), } - python3, err := builtin.EnsurePython3Venv(venv, packages...) + python3, err := myexec.EnsurePython3Venv(venv, packages...) if err != nil { log.Error().Err(err). Interface("packages", packages).