func (lc *LocalCommand) Start() error { if lc.Shell == "" { lc.Shell = "sh" } var cmd *exec.Cmd if lc.ScriptMode { cmd = exec.Command(lc.Shell) cmd.Stdin = strings.NewReader(lc.CmdString) } else { cmd = exec.Command(lc.Shell, "-c", lc.CmdString) } // create the command, set the options if lc.WorkingDirectory != "" { cmd.Dir = lc.WorkingDirectory } cmd.Env = lc.Environment if cmd.Env == nil { cmd.Env = os.Environ() } cmd.Stdout = lc.Stdout cmd.Stderr = lc.Stderr // cache the command running lc.Cmd = cmd // start the command return cmd.Start() }
func (a *ERBAsset) Compile() (io.Reader, error) { data, err := a.input.Compile() if err != nil { return nil, err } a.l.Info("Compiling ERB") var buf bytes.Buffer var cmd *exec.Cmd if _, err := os.Stat("Gemfile"); err == nil { cmd = exec.Command("bundle", "exec", "ruby", a.erbRBPath) } else { cmd = exec.Command("ruby", a.erbRBPath) } cmd.Stdin = data cmd.Stdout = &buf cmd.Stderr = os.Stderr cmd.Env = os.Environ() cmd.Env = append(cmd.Env, fmt.Sprintf("CACHE_BREAKER=%s", a.cacheBreaker)) if err := cmd.Run(); err != nil { return nil, err } return &buf, nil }
// Exec the given command in the background using the systemd // notification protocol. This function returns once the command has // either exited or signaled that it is ready. If the command exits // with a non-zero status before signaling readiness, returns an // exec.ExitError. func Exec(cmd *exec.Cmd) error { l, err := listen() if err != nil { return err } defer func() { _ = l.close() }() if cmd.Env == nil { // Default the environment to the parent process's, minus any // existing versions of our variable. varPrefix := fmt.Sprintf("%s=", envName) for _, v := range os.Environ() { if !strings.HasPrefix(v, varPrefix) { cmd.Env = append(cmd.Env, v) } } } cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", envName, l.Path)) if err := cmd.Start(); err != nil { return err } // This can leak goroutines, but we don't really care because we // always exit after calling this function. ch := make(chan error, 2) go func() { ch <- l.wait() }() go func() { ch <- cmd.Wait() }() return <-ch }
func main() { flag.Usage = func() { fmt.Fprintf(os.Stderr, "%s", Help) os.Exit(1) } flag.Parse() if *version { fmt.Printf("%s", Version) os.Exit(0) } if *unset != "" { os.Unsetenv(*unset) } cmd := new(exec.Cmd) cmd.Env = env // Check for "-" as an argument, because it means the same as "-i" if flag.Arg(0) == "-" { cmd.Env = make([]string, 0) } for i, arg := range flag.Args() { if strings.Index(arg, delim) > 0 { cmd.Env = append(cmd.Env, arg) } else if arg != "-" { if *nullEol { fatal.Fatalln("cannot specify --null (-0) with command") } cmd.Path = arg cmd.Args = append(cmd.Args, flag.Args()[i:]...) cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr err := execvp(cmd) if err != nil { fatal.Fatalln(err) } return } i++ } eol := '\n' if *nullEol { eol = '\x00' } for _, e := range env { fmt.Printf("%s%c", e, eol) } return }
func (self *LocalCommand) Start() error { var cmd *exec.Cmd if self.ScriptMode { cmd = exec.Command("sh") cmd.Stdin = strings.NewReader(self.CmdString) } else { cmd = exec.Command("sh", "-c", self.CmdString) } // create the command, set the options if self.WorkingDirectory != "" { cmd.Dir = self.WorkingDirectory } cmd.Env = self.Environment if cmd.Env == nil { cmd.Env = os.Environ() } cmd.Stdout = self.Stdout cmd.Stderr = self.Stderr // cache the command running self.Cmd = cmd // start the command return cmd.Start() }
func setupCommMapping(cmd *exec.Cmd, comm *Mapping, rOut, wIn *os.File) { syscall.SetHandleInformation(syscall.Handle(comm.mapping), syscall.HANDLE_FLAG_INHERIT, 1) syscall.SetHandleInformation(syscall.Handle(rOut.Fd()), syscall.HANDLE_FLAG_INHERIT, 1) syscall.SetHandleInformation(syscall.Handle(wIn.Fd()), syscall.HANDLE_FLAG_INHERIT, 1) cmd.Env = append(cmd.Env, fmt.Sprintf("GO_FUZZ_COMM_FD=%v", comm.mapping)) cmd.Env = append(cmd.Env, fmt.Sprintf("GO_FUZZ_IN_FD=%v", rOut.Fd())) cmd.Env = append(cmd.Env, fmt.Sprintf("GO_FUZZ_OUT_FD=%v", wIn.Fd())) }
func (runner *runner) withEnv(cmd *exec.Cmd) *exec.Cmd { if len(cmd.Env) == 0 { cmd.Env = append(os.Environ(), runner.env.Array()...) } else { cmd.Env = append(cmd.Env, runner.env.Array()...) } return cmd }
func SetCmdEnv(cmd *exec.Cmd, key string, value string) error { if len(cmd.Env) == 0 { cmd.Env = os.Environ() } env, err := NewEnvFromArray(cmd.Env) if err != nil { return err } env.Values[key] = value cmd.Env = env.ToArray() return nil }
func setGopath(cmd *exec.Cmd, gopath string) { cmd.Env = os.Environ() sawGopath := false for i := range cmd.Env { keyVal := strings.SplitN(cmd.Env[i], "=", 2) if keyVal[0] == "GOPATH" { cmd.Env[i] = "GOPATH=" + gopath + string(filepath.ListSeparator) + keyVal[1] } } if !sawGopath { cmd.Env = append(cmd.Env, "GOPATH="+gopath) } }
func TestDoAll_cached_sample(t *testing.T) { cleanup("go-cache") var gitCmd *exec.Cmd var srcCmd *exec.Cmd gitCmd = exec.Command("git", "checkout", "071610bf3a597bc41aae05e27c5407444b7ea0d1") gitCmd.Dir = filepath.Join(testdataPath, "go-cached") if o, err := gitCmd.CombinedOutput(); err != nil { t.Fatal(string(o), err) } srcCmd = exec.Command("src", "do-all") srcCmd.Dir = filepath.Join(testdataPath, "go-cached") srcCmd.Env = append([]string{"SRCLIBPATH=" + srclibPath}, os.Environ()...) if o, err := srcCmd.CombinedOutput(); err != nil { t.Fatal(string(o), err) } gitCmd = exec.Command("git", "checkout", "34dd0f240fe12cdd8c9c6e24620cc0013518a55e") gitCmd.Dir = filepath.Join(testdataPath, "go-cached") if o, err := gitCmd.CombinedOutput(); err != nil { t.Fatal(string(o), err) } srcCmd = exec.Command("src", "do-all") srcCmd.Dir = filepath.Join(testdataPath, "go-cached") srcCmd.Env = append([]string{"SRCLIBPATH=" + srclibPath}, os.Environ()...) if o, err := srcCmd.CombinedOutput(); err != nil { t.Fatal(string(o), err) } firstOne, err := ioutil.ReadFile(filepath.Join(testdataPath, "go-cached", buildstore.BuildDataDirName, "071610bf3a597bc41aae05e27c5407444b7ea0d1", "one", "sample.graph.json")) if err != nil { t.Fatal(err) } secondOne, err := ioutil.ReadFile(filepath.Join(testdataPath, "go-cached", buildstore.BuildDataDirName, "34dd0f240fe12cdd8c9c6e24620cc0013518a55e", "one", "sample.graph.json")) if err != nil { t.Fatal(err) } if string(firstOne) != string(secondOne) { t.Error("Source unit \"one\" should have been cached: string(firstOne) != string(secondOne)") } firstTwo, err := ioutil.ReadFile(filepath.Join(testdataPath, "go-cached", buildstore.BuildDataDirName, "071610bf3a597bc41aae05e27c5407444b7ea0d1", "two", "sample.graph.json")) if err != nil { t.Fatal(err) } secondTwo, err := ioutil.ReadFile(filepath.Join(testdataPath, "go-cached", buildstore.BuildDataDirName, "34dd0f240fe12cdd8c9c6e24620cc0013518a55e", "two", "sample.graph.json")) if err != nil { t.Fatal(err) } if string(firstTwo) == string(secondTwo) { t.Error("Source unit \"two\" should not be cached: string(firstTwo) == string(secondTwo)") } cleanup("go-cache") }
func runTestOnce(test test, mallocNumToFail int64) (passed bool, err error) { prog := path.Join(*buildDir, test[0]) args := test[1:] var cmd *exec.Cmd if *useValgrind { cmd = valgrindOf(false, prog, args...) } else if *useCallgrind { cmd = callgrindOf(prog, args...) } else if *useGDB { cmd = gdbOf(prog, args...) } else { cmd = exec.Command(prog, args...) } var stdoutBuf bytes.Buffer var stderrBuf bytes.Buffer cmd.Stdout = &stdoutBuf cmd.Stderr = &stderrBuf if mallocNumToFail >= 0 { cmd.Env = os.Environ() cmd.Env = append(cmd.Env, "MALLOC_NUMBER_TO_FAIL="+strconv.FormatInt(mallocNumToFail, 10)) if *mallocTestDebug { cmd.Env = append(cmd.Env, "MALLOC_ABORT_ON_FAIL=1") } cmd.Env = append(cmd.Env, "_MALLOC_CHECK=1") } if err := cmd.Start(); err != nil { return false, err } if err := cmd.Wait(); err != nil { if exitError, ok := err.(*exec.ExitError); ok { if exitError.Sys().(syscall.WaitStatus).ExitStatus() == 88 { return false, errMoreMallocs } } fmt.Print(string(stderrBuf.Bytes())) return false, err } fmt.Print(string(stderrBuf.Bytes())) // Account for Windows line-endings. stdout := bytes.Replace(stdoutBuf.Bytes(), []byte("\r\n"), []byte("\n"), -1) if bytes.HasSuffix(stdout, []byte("PASS\n")) && (len(stdout) == 5 || stdout[len(stdout)-6] == '\n') { return true, nil } return false, nil }
func setCmdEnv(cmd *exec.Cmd, username string) { userWorkspace := conf.GetUserWorkspace(username) cmd.Env = append(cmd.Env, "GOPATH="+userWorkspace, "GOOS="+runtime.GOOS, "GOARCH="+runtime.GOARCH, "GOROOT="+runtime.GOROOT(), "PATH="+os.Getenv("PATH")) if util.OS.IsWindows() { // FIXME: for some weird issues on Windows, such as: The requested service provider could not be loaded or initialized. cmd.Env = append(cmd.Env, os.Environ()...) } }
// Capture runs an executable from a directory returns the output, exit code // and error if appropriate. It sets the environment variables specified. func Capture(wd string, env []string, args ...string) (string, int, error) { exitCode := -1 //log.Printf("Capture(%s, %s, %s)", wd, env, args) var c *exec.Cmd switch len(args) { case 0: return "", -1, errors.New("no command specified") case 1: c = exec.Command(args[0]) default: c = exec.Command(args[0], args[1:]...) } if wd == "" { return "", -1, errors.New("wd is required") } c.Dir = wd procEnv := map[string]string{} for _, item := range os.Environ() { items := strings.SplitN(item, "=", 2) procEnv[items[0]] = items[1] } procEnv["LANG"] = "en_US.UTF-8" procEnv["LANGUAGE"] = "en_US.UTF-8" for _, item := range env { items := strings.SplitN(item, "=", 2) if items[1] == "" { // Remove it instead. delete(procEnv, items[0]) } else { procEnv[items[0]] = items[1] } } c.Env = make([]string, 0, len(procEnv)) for k, v := range procEnv { c.Env = append(c.Env, k+"="+v) } out, err := c.CombinedOutput() if c.ProcessState != nil { if waitStatus, ok := c.ProcessState.Sys().(syscall.WaitStatus); ok { exitCode = waitStatus.ExitStatus() if exitCode != 0 { err = nil } } } // TODO(maruel): Handle code page on Windows. return string(out), exitCode, err }
func setupCommand(cmd *exec.Cmd, taskp TaskDef, outdir string, replacements map[string]string) (stdin, stdout string, err error) { if taskp.Vwd != nil { for k, v := range taskp.Vwd { v = substitute(v, replacements) err = checkOutputFilename(outdir, k) if err != nil { return "", "", err } os.Symlink(v, outdir+"/"+k) } } if taskp.Stdin != "" { // Set up stdin redirection stdin = substitute(taskp.Stdin, replacements) cmd.Stdin, err = os.Open(stdin) if err != nil { return "", "", err } } if taskp.Stdout != "" { err = checkOutputFilename(outdir, taskp.Stdout) if err != nil { return "", "", err } // Set up stdout redirection stdout = outdir + "/" + taskp.Stdout cmd.Stdout, err = os.Create(stdout) if err != nil { return "", "", err } } else { cmd.Stdout = os.Stdout } cmd.Stderr = os.Stderr if taskp.Env != nil { // Set up subprocess environment cmd.Env = os.Environ() for k, v := range taskp.Env { v = substitute(v, replacements) cmd.Env = append(cmd.Env, k+"="+v) } } return stdin, stdout, nil }
func pluginInfo(name string) (ver, short, long string) { if os.Getenv("HKPLUGINMODE") == "info" { return "", "plugin exec loop", "plugin exec loop" } short = "no description" long = name + ": unknown description" var cmd exec.Cmd cmd.Args = []string{name} cmd.Path = lookupPlugin(name) cmd.Env = append([]string{"HKPLUGINMODE=info"}, os.Environ()...) buf, err := cmd.Output() if err != nil { return } info := string(buf) if !strings.HasPrefix(info, name+" ") { return } info = info[len(name)+1:] i := strings.Index(info, ": ") if i < 0 { return } ver, info = info[:i], info[i+2:] i = strings.Index(info, "\n\n") if i < 0 || 50 < i || strings.Contains(info[:i], "\n") { return } short, long = info[:i], info[i+2:] return ver, strings.TrimSpace(short), strings.TrimSpace(long) }
func runCmd(cmd *exec.Cmd) error { if buildX { dir := "" if cmd.Dir != "" { dir = "PWD=" + cmd.Dir + " " } env := strings.Join(cmd.Env, " ") if env != "" { env += " " } printcmd("%s%s%s", dir, env, strings.Join(cmd.Args, " ")) } buf := new(bytes.Buffer) buf.WriteByte('\n') if buildV { cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr } else { cmd.Stdout = buf cmd.Stderr = buf } if !buildN { cmd.Env = environ(cmd.Env) if err := cmd.Run(); err != nil { return fmt.Errorf("%s failed: %v%s", strings.Join(cmd.Args, " "), err, buf) } } return nil }
func TestStatStdin(t *testing.T) { switch runtime.GOOS { case "android", "plan9": t.Skipf("%s doesn't have /bin/sh", runtime.GOOS) } testenv.MustHaveExec(t) if Getenv("GO_WANT_HELPER_PROCESS") == "1" { st, err := Stdin.Stat() if err != nil { t.Fatalf("Stat failed: %v", err) } fmt.Println(st.Mode() & ModeNamedPipe) Exit(0) } var cmd *osexec.Cmd if runtime.GOOS == "windows" { cmd = osexec.Command("cmd", "/c", "echo output | "+Args[0]+" -test.run=TestStatStdin") } else { cmd = osexec.Command("/bin/sh", "-c", "echo output | "+Args[0]+" -test.run=TestStatStdin") } cmd.Env = append(Environ(), "GO_WANT_HELPER_PROCESS=1") output, err := cmd.CombinedOutput() if err != nil { t.Fatalf("Failed to spawn child process: %v %q", err, string(output)) } // result will be like "prw-rw-rw" if len(output) < 1 || output[0] != 'p' { t.Fatalf("Child process reports stdin is not pipe '%v'", string(output)) } }
// setEnv sets the given environment variables for the command, ensuring they // are only set once. func setEnv(cmd *exec.Cmd, envs map[string]string) { env := os.Environ() cmd.Env = make([]string, 0, len(env)+len(envs)) outer: for _, e := range env { for k := range envs { if strings.HasPrefix(e, k+"=") { continue outer } } cmd.Env = append(cmd.Env, e) } for k, v := range envs { cmd.Env = append(cmd.Env, k+"="+v) } }
func (c *linuxContainer) newInitProcess(p *Process, cmd *exec.Cmd, parentPipe, childPipe *os.File) (*initProcess, error) { t := "_LIBCONTAINER_INITTYPE=standard" cloneFlags := c.config.Namespaces.CloneFlags() if cloneFlags&syscall.CLONE_NEWUSER != 0 { if err := c.addUidGidMappings(cmd.SysProcAttr); err != nil { // user mappings are not supported return nil, err } enableSetgroups(cmd.SysProcAttr) // Default to root user when user namespaces are enabled. if cmd.SysProcAttr.Credential == nil { cmd.SysProcAttr.Credential = &syscall.Credential{} } } cmd.Env = append(cmd.Env, t) cmd.SysProcAttr.Cloneflags = cloneFlags return &initProcess{ cmd: cmd, childPipe: childPipe, parentPipe: parentPipe, manager: c.cgroupManager, config: c.newInitConfig(p), container: c, }, nil }
func buildCmd(cmd Cmd) *Result { var execCmd *exec.Cmd switch len(cmd.Command) { case 1: execCmd = exec.Command(cmd.Command[0]) default: execCmd = exec.Command(cmd.Command[0], cmd.Command[1:]...) } outBuffer := new(lockedBuffer) errBuffer := new(lockedBuffer) execCmd.Stdin = cmd.Stdin execCmd.Dir = cmd.Dir execCmd.Env = cmd.Env if cmd.Stdout != nil { execCmd.Stdout = io.MultiWriter(outBuffer, cmd.Stdout) } else { execCmd.Stdout = outBuffer } execCmd.Stderr = errBuffer return &Result{ Cmd: execCmd, outBuffer: outBuffer, errBuffer: errBuffer, } }
func (w *World) CmdWithEnv(binary string, env []string, args ...string) *exec.Cmd { hasVerbose := func() bool { for _, v := range args { if v == "-verbose" || v == "--verbose" { return true } } return false } var cmd *exec.Cmd switch binary { case "camget", "camput", "camtool", "cammount": // TODO(mpl): lift the camput restriction when we have a unified logging mechanism if binary == "camput" && !hasVerbose() { // camput and camtool are the only ones to have a -verbose flag through cmdmain // but camtool is never used. (and cammount does not even have a -verbose). args = append([]string{"-verbose"}, args...) } cmd = exec.Command(filepath.Join(w.camRoot, "bin", binary), args...) clientConfigDir := filepath.Join(w.camRoot, "config", "dev-client-dir") cmd.Env = append([]string{ "CAMLI_CONFIG_DIR=" + clientConfigDir, // Respected by env expansions in config/dev-client-dir/client-config.json: "CAMLI_SERVER=" + w.ServerBaseURL(), "CAMLI_SECRET_RING=" + w.SecretRingFile(), "CAMLI_KEYID=" + w.ClientIdentity(), "CAMLI_AUTH=userpass:testuser:passTestWorld", }, env...) default: panic("Unknown binary " + binary) } return cmd }
func (a *AutoInstOptions) install() { sfx := "" if a.InstallSuffix != "" { sfx = a.InstallSuffix } osArchSfx := osArch + sfx if a.Env == nil { a.Env = map[string]string{} } roots := []string{} if p := a.Env["GOROOT"]; p != "" { roots = append(roots, filepath.Join(p, "pkg", osArchSfx)) } for _, p := range pathList(a.Env["GOPATH"]) { roots = append(roots, filepath.Join(p, "pkg", osArchSfx)) } if len(roots) == 0 { return } archiveOk := func(fn string) bool { for _, root := range roots { _, err := os.Stat(filepath.Join(root, fn)) if err == nil { return true } } return false } el := envSlice(a.Env) installed := []string{} for path, fn := range a.imports() { if !archiveOk(fn) { var cmd *exec.Cmd if sfx == "" { cmd = exec.Command("go", "install", path) } else { cmd = exec.Command("go", "install", "-installsuffix", sfx, path) } cmd.Env = el cmd.Stderr = ioutil.Discard cmd.Stdout = ioutil.Discard cmd.Run() if archiveOk(fn) { installed = append(installed, path) } } } if len(installed) > 0 { postMessage("auto-installed: %v", strings.Join(installed, ", ")) } }
// startContainer starts the container. Returns the exit status or -1 and an // error. // // Signals sent to the current process will be forwarded to container. func startContainer(container *libcontainer.Config, term namespaces.Terminal, dataPath string, args []string) (int, error) { var ( cmd *exec.Cmd sigc = make(chan os.Signal, 10) ) signal.Notify(sigc) createCommand := func(container *libcontainer.Config, console, rootfs, dataPath, init string, pipe *os.File, args []string) *exec.Cmd { cmd = namespaces.DefaultCreateCommand(container, console, rootfs, dataPath, init, pipe, args) if logPath != "" { cmd.Env = append(cmd.Env, fmt.Sprintf("log=%s", logPath)) } return cmd } startCallback := func() { go func() { for sig := range sigc { cmd.Process.Signal(sig) } }() } return namespaces.Exec(container, term, "", dataPath, args, createCommand, startCallback) }
// RunCommandWithStdoutStderr execs a command and returns its output. func RunCommandWithStdoutStderr(cmd *exec.Cmd) (bytes.Buffer, bytes.Buffer, error) { var stdout, stderr bytes.Buffer stderrPipe, err := cmd.StderrPipe() stdoutPipe, err := cmd.StdoutPipe() cmd.Env = os.Environ() if err != nil { fmt.Println("error at io pipes") } err = cmd.Start() if err != nil { fmt.Println("error at command start") } go func() { io.Copy(&stdout, stdoutPipe) fmt.Println(stdout.String()) }() go func() { io.Copy(&stderr, stderrPipe) fmt.Println(stderr.String()) }() time.Sleep(2000 * time.Millisecond) err = cmd.Wait() if err != nil { fmt.Println("error at command wait") } return stdout, stderr, err }
func writeGitRepositoryArchive(w io.Writer, path string, ref GitCommitRef) error { var cmd *exec.Cmd // TODO: Stream as tar with gzip if ref == EmptyGitCommitRef { cmd = exec.Command("/usr/bin/git", "archive", "--format", "zip", "master") } else { cmd = exec.Command("/usr/bin/git", "archive", "--format", "zip", string(ref)) } cmd.Env = []string{} cmd.Dir = path var stderr bytes.Buffer cmd.Stderr = utils.LimitWriter(&stderr, 20*1024) stdout, err := cmd.StdoutPipe() if err != nil { return err } if err := cmd.Start(); err != nil { return err } io.Copy(w, stdout) if err := cmd.Wait(); err != nil { return errors.New(fmt.Sprintf("Failed to archive repository: %s\n", err.Error()) + stderr.String()) } return nil }
func (c *linuxContainer) newInitProcess(p *Process, cmd *exec.Cmd, parentPipe, childPipe *os.File) (*initProcess, error) { cmd.Env = append(cmd.Env, "_LIBCONTAINER_INITTYPE="+string(initStandard)) nsMaps := make(map[configs.NamespaceType]string) for _, ns := range c.config.Namespaces { if ns.Path != "" { nsMaps[ns.Type] = ns.Path } } _, sharePidns := nsMaps[configs.NEWPID] data, err := c.bootstrapData(c.config.Namespaces.CloneFlags(), nsMaps, "") if err != nil { return nil, err } return &initProcess{ cmd: cmd, childPipe: childPipe, parentPipe: parentPipe, manager: c.cgroupManager, config: c.newInitConfig(p), container: c, process: p, bootstrapData: data, sharePidns: sharePidns, }, nil }
func (c *linuxContainer) newSetnsProcess(p *Process, cmd *exec.Cmd, parentPipe, childPipe, rootDir *os.File) (*setnsProcess, error) { cmd.Env = append(cmd.Env, "_LIBCONTAINER_INITTYPE="+string(initSetns)) state, err := c.currentState() if err != nil { return nil, newSystemErrorWithCause(err, "getting container's current state") } // for setns process, we don't have to set cloneflags as the process namespaces // will only be set via setns syscall data, err := c.bootstrapData(0, state.NamespacePaths) if err != nil { return nil, err } // TODO: set on container for process management p.consoleChan = make(chan *os.File, 1) return &setnsProcess{ cmd: cmd, cgroupPaths: c.cgroupManager.GetPaths(), childPipe: childPipe, parentPipe: parentPipe, config: c.newInitConfig(p), process: p, bootstrapData: data, rootDir: rootDir, }, nil }
func pluginInfo(name string) (ver, short, long string) { if os.Getenv("HKPLUGINMODE") == "info" { return "", "[plugin exec loop]", "[plugin exec loop]\n" } var cmd exec.Cmd cmd.Args = []string{name} cmd.Path = lookupPlugin(name) cmd.Env = append([]string{"HKPLUGINMODE=info"}, os.Environ()...) buf, err := cmd.Output() if err != nil { fmt.Fprintln(os.Stderr, err) return "", "[unknown description]", "[unknown description]\n" } info := string(buf) if !strings.HasPrefix(info, name+" ") { return "", "[unknown description]", "[unknown description]\n" } info = info[len(name)+1:] i := strings.Index(info, ": ") ver, info = info[:i], info[i+2:] i = strings.Index(info, "\n\n") short, long = info[:i], info[i+2:] if len(short) > 50 || strings.Contains(short, "\n") { return "", "[unknown description]", "[unknown description]\n" } return ver, short, long }
// RunCommandWithStdoutStderr execs a command and returns its output. func RunCommandWithStdoutStderr(cmd *exec.Cmd) (bytes.Buffer, bytes.Buffer, error) { var stdout, stderr bytes.Buffer stderrPipe, err := cmd.StderrPipe() stdoutPipe, err := cmd.StdoutPipe() cmd.Env = os.Environ() if err != nil { fmt.Println("error at io pipes") } err = cmd.Start() if err != nil { fmt.Println("error at command start") } go func() { streamOutput(stdoutPipe, &stdout, os.Stdout) }() go func() { streamOutput(stderrPipe, &stderr, os.Stderr) }() err = cmd.Wait() if err != nil { fmt.Println("error at command wait") } return stdout, stderr, err }
func RunWithEnvAndWd(command string, args []string, env []string, wd string) (proc *exec.Cmd, err error) { //log.Println(command, args) //hho := exec.PassThrough args = prepend(args, command) env = mergeEnv(os.Environ(), env) binpath, err := findCmd(findEnv(env, "PATH"), command) if err != nil { return nil, err } cmd := new(exec.Cmd) cmd.Path = binpath cmd.Args = args cmd.Env = env cmd.Dir = wd cmd.Stderr = os.Stderr cmd.Stdout = os.Stdout err = cmd.Start() if err != nil { log.Print("Error running command ", command, ": ", err, "\n") return nil, err } return cmd, nil }