github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/misc/dashboard/builder/exec.go (about)

     1  // Copyright 2011 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package main
     6  
     7  import (
     8  	"bytes"
     9  	"fmt"
    10  	"io"
    11  	"log"
    12  	"os"
    13  	"os/exec"
    14  	"time"
    15  )
    16  
    17  // run is a simple wrapper for exec.Run/Close
    18  func run(timeout time.Duration, envv []string, dir string, argv ...string) error {
    19  	if *verbose {
    20  		log.Println("run", argv)
    21  	}
    22  	cmd := exec.Command(argv[0], argv[1:]...)
    23  	cmd.Dir = dir
    24  	cmd.Env = envv
    25  	cmd.Stderr = os.Stderr
    26  	if err := cmd.Start(); err != nil {
    27  		return err
    28  	}
    29  	return waitWithTimeout(timeout, cmd)
    30  }
    31  
    32  // runLog runs a process and returns the combined stdout/stderr. It returns
    33  // process combined stdout and stderr output, exit status and error. The
    34  // error returned is nil, if process is started successfully, even if exit
    35  // status is not successful.
    36  func runLog(timeout time.Duration, envv []string, dir string, argv ...string) (string, bool, error) {
    37  	var b bytes.Buffer
    38  	ok, err := runOutput(timeout, envv, &b, dir, argv...)
    39  	return b.String(), ok, err
    40  }
    41  
    42  // runOutput runs a process and directs any output to the supplied writer.
    43  // It returns exit status and error. The error returned is nil, if process
    44  // is started successfully, even if exit status is not successful.
    45  func runOutput(timeout time.Duration, envv []string, out io.Writer, dir string, argv ...string) (bool, error) {
    46  	if *verbose {
    47  		log.Println("runOutput", argv)
    48  	}
    49  
    50  	cmd := exec.Command(argv[0], argv[1:]...)
    51  	cmd.Dir = dir
    52  	cmd.Env = envv
    53  	cmd.Stdout = out
    54  	cmd.Stderr = out
    55  
    56  	startErr := cmd.Start()
    57  	if startErr != nil {
    58  		return false, startErr
    59  	}
    60  	if err := waitWithTimeout(timeout, cmd); err != nil {
    61  		return false, err
    62  	}
    63  	return true, nil
    64  }
    65  
    66  func waitWithTimeout(timeout time.Duration, cmd *exec.Cmd) error {
    67  	errc := make(chan error, 1)
    68  	go func() {
    69  		errc <- cmd.Wait()
    70  	}()
    71  	var err error
    72  	select {
    73  	case <-time.After(timeout):
    74  		cmd.Process.Kill()
    75  		err = fmt.Errorf("timed out after %v", timeout)
    76  	case err = <-errc:
    77  	}
    78  	return err
    79  }