func start(c *exec.Cmd) (io.ReadCloser, io.WriteCloser, error) { c.SysProcAttr = &syscall.SysProcAttr{} //c.SysProcAttr.CreationFlags = 16 // CREATE_NEW_CONSOLE stdin, err := c.StdinPipe() if err != nil { return nil, nil, err } stdout, err := c.StdoutPipe() if err != nil { return nil, nil, err } stderr, err := c.StderrPipe() if err != nil { return nil, nil, err } t := &term{} t.cmd = c t.stderr = stderr t.stdout = stdout t.stdin = stdin err = t.start() if err != nil { return nil, nil, err } return t, t, nil }
func Example() { var cmd *exec.Cmd memd := func(t *tcptest.TCPTest) { cmd = exec.Command("memcached", "-p", fmt.Sprintf("%d", t.Port())) cmd.SysProcAttr = &syscall.SysProcAttr{ Setpgid: true, } go cmd.Run() for loop := true; loop; { select { case <-t.Done(): cmd.Process.Kill() loop = false } } } server, err := tcptest.Start2(memd, 30*time.Second) if err != nil { log.Fatalf("Failed to start memcached: %s", err) } log.Printf("memcached started on port %d", server.Port()) defer func() { if cmd != nil && cmd.Process != nil { cmd.Process.Signal(syscall.SIGTERM) } }() server.Stop() server.Wait() }
func (r *RealCommandRunner) Start(cmd *exec.Cmd) error { if cmd.SysProcAttr == nil { cmd.SysProcAttr = &syscall.SysProcAttr{ Setpgid: true, } } else { cmd.SysProcAttr.Setpgid = true } if r.debug { log.Printf("\x1b[40;36mspawning: %s\x1b[0m\n", prettyCommand(cmd)) r.tee(cmd) } err := r.resolve(cmd).Start() if r.debug { if err != nil { log.Printf("\x1b[40;31mspawning failed: %s\x1b[0m\n", err) } else { log.Printf("\x1b[40;32mspawning succeeded\x1b[0m\n") } } return err }
// Configures the given Command to produce a hidden window, if possible. Must // be called before the Command is executed. func Hide(c *exec.Cmd) { if c.SysProcAttr == nil { c.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} } else { c.SysProcAttr.HideWindow = true } }
func start(c *exec.Cmd) (pty *os.File, err error) { pty, tty, err := open() if err != nil { return nil, err } defer tty.Close() err = setEcho(pty, false) if err != nil { return nil, err } err = setEcho(tty, false) if err != nil { return nil, err } c.Stdout = tty c.Stdin = tty c.Stderr = tty if c.SysProcAttr == nil { c.SysProcAttr = &syscall.SysProcAttr{} } c.SysProcAttr.Setctty = true c.SysProcAttr.Setsid = true err = c.Start() if err != nil { pty.Close() return nil, err } return pty, err }
// timedCommand executes the given command, terminating it forcefully // if it is still running after the given timeout elapses. func (e *executor) timedCommand(timeout time.Duration, opts opts, command *exec.Cmd) error { // Make the process of this command a new process group leader // to facilitate clean up of processes that time out. command.SysProcAttr = &syscall.SysProcAttr{Setpgid: true} // Kill this process group explicitly when receiving SIGTERM // or SIGINT signals. sigchan := make(chan os.Signal, 1) signal.Notify(sigchan, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGINT) go func() { <-sigchan e.terminateProcessGroup(opts, command) }() if err := command.Start(); err != nil { e.printf(e.verboseStdout(opts), "FAILED: %v", err) return err } done := make(chan error, 1) go func() { done <- command.Wait() }() select { case <-time.After(timeout): // The command has timed out. e.terminateProcessGroup(opts, command) // Allow goroutine to exit. <-done e.printf(e.verboseStdout(opts), "TIMED OUT") return commandTimedOutErr case err := <-done: e.printf(e.verboseStdout(opts), okOrFailed(err)) return err } }
func (pipe *Pipe) runPtyCmd(cmd *exec.Cmd) error { py, tty, err := pty.Open() if err != nil { return err } defer tty.Close() env := os.Environ() env = append(env, "TERM=xterm") cmd.Env = env cmd.Stdout = tty cmd.Stdin = tty cmd.Stderr = tty cmd.SysProcAttr = &syscall.SysProcAttr{Setctty: true, Setsid: true} ws := &Winsize{ Width: uint16(pipe.opts.Width), Height: uint16(pipe.opts.Height), } _, _, syserr := syscall.Syscall(syscall.SYS_IOCTL, py.Fd(), uintptr(syscall.TIOCSWINSZ), uintptr(unsafe.Pointer(ws))) if syserr != 0 { return syserr } pCmd := pipedCmd{ pipe: pipe, cmd: cmd, stdin: py, stdout: py, stderr: nil, } return pCmd.run() }
func (r *RealCommandRunner) Run(cmd *exec.Cmd) error { if cmd.SysProcAttr == nil { cmd.SysProcAttr = &syscall.SysProcAttr{ Setpgid: true, } } else { cmd.SysProcAttr.Setpgid = true } if r.debug { log.Printf("\x1b[40;36mexecuting: %s\x1b[0m\n", prettyCommand(cmd)) r.tee(cmd) } err := r.resolve(cmd).Run() if r.debug { if err != nil { log.Printf("\x1b[40;31mcommand failed (%s): %s\x1b[0m\n", prettyCommand(cmd), err) } else { log.Printf("\x1b[40;32mcommand succeeded (%s)\x1b[0m\n", prettyCommand(cmd)) } } return err }
// Launch creates and begins debugging a new process. First entry in // `cmd` is the program to run, and then rest are the arguments // to be supplied to that process. func Launch(cmd []string) (*Process, error) { var ( proc *exec.Cmd err error ) // check that the argument to Launch is an executable file if fi, staterr := os.Stat(cmd[0]); staterr == nil && (fi.Mode()&0111) == 0 { return nil, NotExecutableErr } dbp := New(0) dbp.execPtraceFunc(func() { proc = exec.Command(cmd[0]) proc.Args = cmd proc.Stdout = os.Stdout proc.Stderr = os.Stderr proc.SysProcAttr = &syscall.SysProcAttr{Ptrace: true, Setpgid: true} err = proc.Start() }) if err != nil { return nil, err } dbp.Pid = proc.Process.Pid _, _, err = dbp.wait(proc.Process.Pid, 0) if err != nil { return nil, fmt.Errorf("waiting for target execve failed: %s", err) } return initializeDebugProcess(dbp, proc.Path, false) }
func TestMemd(t *testing.T) { var cmd *exec.Cmd memd := func(t *tcptest.TCPTest) { cmd = exec.Command("memcached", "-p", fmt.Sprintf("%d", t.Port())) cmd.SysProcAttr = &syscall.SysProcAttr{ Setpgid: true, } cmd.Run() } server, err := tcptest.Start2(memd, 30*time.Second) if err != nil { log.Fatalf("Failed to start memcached: %s", err) } t.Logf("memcached started on port %d", server.Port()) defer func() { if cmd != nil && cmd.Process != nil { cmd.Process.Signal(syscall.SIGTERM) } }() argv := []string{"-p", fmt.Sprintf("%d", server.Port()), "-k", "test"} ckr := run(argv) if ckr.Status.String() != "OK" { t.Errorf("faild to check memcache:%s", ckr) } cmd.Process.Signal(syscall.SIGTERM) server.Wait() }
func (w *Spawn) spawnWithTty(cmd *exec.Cmd) ([]*os.File, error) { pty, tty, err := w.PTY.Open() if err != nil { return nil, fmt.Errorf("container_daemon: open pipe: %s", err) } cmd.Stdin = tty cmd.Stdout = tty cmd.Stderr = tty if cmd.SysProcAttr == nil { cmd.SysProcAttr = &syscall.SysProcAttr{} } cmd.SysProcAttr.Setctty = true cmd.SysProcAttr.Setsid = true exitFd, err := wireExit(cmd, w.Runner) if err != nil { pty.Close() tty.Close() return nil, err } return []*os.File{pty, exitFd}, err }
func PutInBackgroundIfLinux(cmd *exec.Cmd) { // To put this in the background, we have to change the process group // per: https://groups.google.com/forum/#!topic/golang-nuts/shST-SDqIp4. // But it doesn't work on Windows cmd.SysProcAttr = &syscall.SysProcAttr{ Setpgid: true, } }
//PtyRun assigns a psuedo terminal tty to the corresponding std.io set and returns an error indicating state func PtyRun(c *exec.Cmd, tty *os.File) (err error) { defer tty.Close() c.Stdout = tty c.Stdin = tty c.Stderr = tty c.SysProcAttr = &syscall.SysProcAttr{Setctty: true, Setsid: true} return c.Start() }
func (e *ExecScriptCheck) setChroot(cmd *exec.Cmd) { if e.FSIsolation { if cmd.SysProcAttr == nil { cmd.SysProcAttr = &syscall.SysProcAttr{} } cmd.SysProcAttr.Chroot = e.taskDir } cmd.Dir = "/" }
func (p *Pty) SetCmd(c *exec.Cmd) { c.Stdin = p.tty c.Stdout = p.tty c.Stderr = p.tty if c.SysProcAttr == nil { c.SysProcAttr = &syscall.SysProcAttr{} } c.SysProcAttr.Setctty = true c.SysProcAttr.Setsid = true }
func (r *RealCommandRunner) Background(cmd *exec.Cmd) error { if cmd.SysProcAttr == nil { cmd.SysProcAttr = &syscall.SysProcAttr{ Setpgid: true, } } else { cmd.SysProcAttr.Setpgid = true } return cmd.Start() }
// Set OS-specific SysProcAttrs if they exist func cleanupSubcmd(c *exec.Cmd) { // Send the subprocess a SIGTERM when we exit attr := new(syscall.SysProcAttr) r := reflect.ValueOf(attr) f := reflect.Indirect(r).FieldByName(`Pdeathsig`) if f.IsValid() { f.Set(reflect.ValueOf(syscall.SIGTERM)) c.SysProcAttr = attr } }
func serviceHandleUsersFor(service *Service, cmd *exec.Cmd) { config := (*service).config userName := config.User if !userName.IsTrimmedEmpty() { cmd.SysProcAttr = &syscall.SysProcAttr{} uid, gid, err := lookupUser(userName.String()) if err != nil { panics.New("Could not run as user '%v'.", userName).CausedBy(err).Throw() } cmd.SysProcAttr.Credential = &syscall.Credential{Uid: uint32(uid), Gid: uint32(gid)} } }
// --- functions func CmdDaemonWrapper(c *cli.Context) { args := os.Args args[1] = "_daemon" started := []time.Time{} sigTerm := make(chan os.Signal, 1) signal.Notify(sigTerm, os.Interrupt) signal.Notify(sigTerm, syscall.SIGTERM) var cmd *exec.Cmd go func() { <-sigTerm cmd.Process.Kill() os.Exit(1) }() sigHup := make(chan os.Signal, 1) signal.Notify(sigHup, syscall.SIGHUP) go func() { for { <-sigHup cmd.Process.Signal(syscall.SIGHUP) } }() for { cmd = exec.Command(args[0], args[1:]...) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr envHappoUserId := os.Getenv("HAPPO_USER_ID") if envHappoUserId != "" { uid, err := strconv.Atoi(envHappoUserId) if err != nil { log.Print("HAPPO_USER_ID ", envHappoUserId) log.Fatal(err) } cmd.SysProcAttr = &syscall.SysProcAttr{} cmd.SysProcAttr.Credential = &syscall.Credential{Uid: uint32(uid)} } started = append(started, time.Now()) cmd.Start() cmd.Wait() if len(started) > 10 && time.Now().Add(-30*time.Second).Before(started[len(started)-5]) { log.Fatal("Restarted too fast. Abort!") os.Exit(1) } } }
func SetNamespace(cmd *exec.Cmd) { // XXX: keep move with Go 1.4 and later's cmd.SysProcAttr = &syscall.SysProcAttr{} //cmd.SysProcAttr.Cloneflags = syscall.CLONE_NEWUSER | syscall.CLONE_NEWNS | syscall.CLONE_NEWUTS | syscall.CLONE_NEWPID | syscall.CLONE_NEWIPC | syscall.CLONE_NEWNET cmd.SysProcAttr.Cloneflags = syscall.CLONE_NEWUSER /*| syscall.CLONE_NEWNS*/ | syscall.CLONE_NEWUTS | syscall.CLONE_NEWPID | syscall.CLONE_NEWIPC /*| syscall.CLONE_NEWNET*/ cmd.SysProcAttr.Credential = &syscall.Credential{ Uid: 0, Gid: 0, } cmd.SysProcAttr.UidMappings = []syscall.SysProcIDMap{{ContainerID: 0, HostID: 1001, Size: 1}} cmd.SysProcAttr.GidMappings = []syscall.SysProcIDMap{{ContainerID: 0, HostID: 1001, Size: 1}} }
func (t *Terminal) Start(c *exec.Cmd) (err error) { if t == nil { return errors.New("terminal not assigned.") } //defer t.Tty.Close() c.Stdout = t.Tty c.Stdin = t.Tty c.Stderr = t.Tty c.SysProcAttr = &syscall.SysProcAttr{Setctty: true, Setsid: true} if err = c.Start(); err != nil { fmt.Println("error is ", err) t.Pty.Close() return } return }
// NewTty creates a pseudo-TTY for a command and modifies it appropriately so // the command thinks it's a real terminal func NewTty(cmd *exec.Cmd) *Tty { tty := &Tty{} tty.cmd = cmd // Assign pty/tty so git thinks it's a real terminal tty.outpty, tty.outtty, _ = pty.Open() cmd.Stdin = tty.outtty cmd.Stdout = tty.outtty tty.errpty, tty.errtty, _ = pty.Open() cmd.Stderr = tty.errtty if cmd.SysProcAttr == nil { cmd.SysProcAttr = &syscall.SysProcAttr{} } cmd.SysProcAttr.Setctty = true cmd.SysProcAttr.Setsid = true return tty }
func (exer *Executor) Prepare(cmd *exec.Cmd) (err error) { exer.path = cmd.Path if cmd.SysProcAttr == nil { cmd.SysProcAttr = &syscall.SysProcAttr{} } if exer.chroot != "" { if cmd.Dir == "" { cmd.Dir = "/" } cmd.SysProcAttr.Chroot = exer.chroot if err = exer.MkJail(); err != nil { return } } cmd.SysProcAttr.Credential = &syscall.Credential{Uid: uint32(exer.id), Gid: uint32(exer.id)} return }
func (s *server) Print(stream pb.ServerPrintService_PrintServer) error { var cmd *exec.Cmd = nil var out bytes.Buffer dataReader := newDataReader() for { content, err := stream.Recv() if err == io.EOF { close(dataReader.ch) stream.SendAndClose(&pb.PrintResponse{0}) fmt.Printf("%q\n", out.String()) } if err != nil { return err } if x, ok := content.GetPrintContentType().(*pb.PrintContent_PrintInfo); ok { dir, err := filepath.Abs(filepath.Dir(os.Args[0])) if err != nil { log.Fatal(err) } cmd = exec.Command(path.Join(dir, "gswin32c.exe"), "-dNOPAUSE", "-dBATCH", "-sDEVICE=mswinpr2", fmt.Sprintf("-dNumCopies=%d", x.PrintInfo.Copies), fmt.Sprintf("-dDEVICEWIDTHPOINTS=%d", x.PrintInfo.PageSizeWidth), fmt.Sprintf("-dDEVICEHEIGHTPOINTS=%d", x.PrintInfo.PageSizeHeight), "-sOutputFile=%printer%"+x.PrintInfo.PrinterName, "-") fmt.Printf("cmd.Args %v\n", cmd.Args) cmd.Stdin = dataReader cmd.Stdout = &out cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} go func(cmd *exec.Cmd) { err := cmd.Run() if err != nil { log.Fatal(err) } }(cmd) } if x, ok := content.GetPrintContentType().(*pb.PrintContent_Content); ok { if cmd != nil && cmd.Stdin != nil { dataReader.ch <- x.Content } } } return nil }
// Start assigns a pseudo-terminal tty os.File to c.Stdin, c.Stdout, // and c.Stderr, calls c.Start, and returns the File of the tty's // corresponding pty. func Start(c *exec.Cmd) (pty *os.File, err error) { pty, tty, err := Open() if err != nil { return nil, err } defer tty.Close() c.Stdout = tty c.Stdin = tty c.Stderr = tty c.SysProcAttr = &syscall.SysProcAttr{Setctty: true, Setsid: true} err = c.Start() if err != nil { pty.Close() return nil, err } return pty, err }
func (self *TestEnv) startMemcached() { var cmd *exec.Cmd var server *tcptest.TCPTest var err error for i := 0; i < 5; i++ { server, err = tcptest.Start(func(port int) { out, err := os.OpenFile("memcached.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644) cmd = exec.Command("memcached", "-vv", "-p", fmt.Sprintf("%d", port)) cmd.SysProcAttr = &syscall.SysProcAttr{ Setpgid: true, } stderrpipe, err := cmd.StderrPipe() if err != nil { self.FailNow("Failed to open pipe to stderr") } stdoutpipe, err := cmd.StdoutPipe() if err != nil { self.FailNow("Failed to open pipe to stdout") } go io.Copy(out, stderrpipe) go io.Copy(out, stdoutpipe) cmd.Run() }, time.Minute) if err == nil { break } self.Logf("Failed to start memcached: %s", err) } if server == nil { self.FailNow("Failed to start memcached") } self.MemdPort = server.Port() self.AddGuard(func() { if cmd != nil && cmd.Process != nil { self.Logf("Killing memcached") cmd.Process.Signal(syscall.SIGTERM) } server.Wait() }) }
func processLife(cmd *exec.Cmd, errc chan error) { // FIXME(nightlyone) This works neither in Windows nor Plan9. // Fix it, once we have users of this platform. // NOTE: Cannot setsid and and setpgid in one child. Would need double fork or exec, // which makes things very hard. cmd.SysProcAttr = &syscall.SysProcAttr{ Setpgid: true, } if err := cmd.Start(); err != nil { errc <- &NotAvailableError{ args: cmd.Args, err: err, } } else { errc <- cmd.Wait() } }
func (self *TestEnv) startQueue() { var cmd *exec.Cmd tt, err := tcptest.Start(func(port int) { path, err := exec.LookPath("redis-server") if err != nil { self.Test.Errorf("Failed to find redis-server: %s", err) self.Test.FailNow() } out, err := os.OpenFile("redis.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644) cmd = exec.Command(path, "--port", fmt.Sprintf("%d", port), "--loglevel", "verbose") cmd.SysProcAttr = &syscall.SysProcAttr{ Setpgid: true, } stderrpipe, err := cmd.StderrPipe() if err != nil { self.FailNow("Failed to open pipe to stderr") } stdoutpipe, err := cmd.StdoutPipe() if err != nil { self.FailNow("Failed to open pipe to stdout") } go io.Copy(out, stderrpipe) go io.Copy(out, stdoutpipe) err = cmd.Run() if err != nil { self.Test.Logf("Command %v exited: %s", cmd.Args, err) } }, 5*time.Second) if err != nil { self.Test.Fatalf("Failed to start redis-server: %s", err) } addr := fmt.Sprintf("127.0.0.1:%d", tt.Port()) self.QueueConfig = &config.QueueConfig{ Addr: addr, } self.AddGuard(func() { cmd.Process.Signal(syscall.SIGTERM) }) }
func finishRunning(cmd *exec.Cmd) error { stepName := strings.Join(cmd.Args, " ") if *verbose { cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr } log.Printf("Running: %v", stepName) defer func(start time.Time) { log.Printf("Step '%s' finished in %s", stepName, time.Since(start)) }(time.Now()) cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true} if err := cmd.Start(); err != nil { return fmt.Errorf("error starting %v: %v", stepName, err) } finished := make(chan error) go func() { finished <- cmd.Wait() }() for { select { case <-terminate.C: terminate.Reset(time.Duration(0)) // Kill subsequent processes immediately. syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL) cmd.Process.Kill() return fmt.Errorf("Terminate testing after 15m after %s timeout during %s", *timeout, stepName) case <-interrupt.C: log.Printf("Interrupt testing after %s timeout. Will terminate in another 15m", *timeout) terminate.Reset(15 * time.Minute) if err := syscall.Kill(-cmd.Process.Pid, syscall.SIGINT); err != nil { log.Printf("Failed to interrupt %v. Will terminate immediately: %v", stepName, err) syscall.Kill(-cmd.Process.Pid, syscall.SIGTERM) cmd.Process.Kill() } case err := <-finished: return err } } }
// Start assigns a pseudo-terminal tty os.File to c.Stdin, c.Stdout, // and c.Stderr, calls c.Start, and returns the File of the tty's // corresponding pty. func ptyStart(c *exec.Cmd) (p *os.File, err error) { p, tty, err := pty.Open() if err != nil { return nil, err } defer tty.Close() c.Stdout = tty c.Stdin = tty c.Stderr = tty c.SysProcAttr = &syscall.SysProcAttr{Setctty: true, Setsid: true} if daemon.user != nil { uid, e1 := strconv.Atoi(daemon.user.Uid) gid, e2 := strconv.Atoi(daemon.user.Gid) if e1 == nil && e2 == nil { c.SysProcAttr.Credential = &syscall.Credential{ Uid: uint32(uid), Gid: uint32(gid), Groups: daemon.ugroups, } c.Dir = daemon.user.HomeDir c.Env = make([]string, len(GlobalOpt.Env)+1) i := 0 for k, v := range GlobalOpt.Env { c.Env[i] = fmt.Sprintf("%s=%s", k, v) i += 1 } c.Env[i] = fmt.Sprintf("HOME=%s", c.Dir) glog.V(3).Infof("uid:%d gid:%d groups:%v env:\n%s\n", uid, gid, daemon.ugroups, strings.Join(c.Env, "\n")) } } err = c.Start() if err != nil { p.Close() return nil, err } return p, err }