package shell import ( "io/ioutil" "os" "os/exec" "strings" "time" "go.wit.com/log" ) // TODO: look at https://github.com/go-cmd/cmd/issues/20 // use go-cmd instead here? var callback func(interface{}, int) var shellStdout *os.File var shellStderr *os.File var spewOn bool = false var quiet bool = false // var msecDelay int = 20 // number of milliseconds to delay between reads with no data // var bytesBuffer bytes.Buffer // var bytesSplice []byte func handleError(c interface{}, ret int) { log.Log(INFO, "shell.Run() Returned", ret) if callback != nil { callback(c, ret) } } func init() { callback = nil } func InitCallback(f func(interface{}, int)) { callback = f } // this means it won't copy all the output to STDOUT func Quiet(q bool) { quiet = q } func Script(cmds string) int { // split on new lines (while we are at it, handle stupid windows text files lines := strings.Split(strings.Replace(cmds, "\r\n", "\n", -1), "\n") for _, line := range lines { line = Chomp(line) // this is like 'chomp' in perl log.Log(INFO, "LINE:", line) time.Sleep(1) RunString(line) } return 0 } func SpewOn() { spewOn = true } func SetDelayInMsec(msecs int) { msecDelay = msecs } func SetStdout(newout *os.File) { shellStdout = newout } func SetStderr(newerr *os.File) { shellStderr = newerr } func Unlink(filename string) bool { if err := os.Remove(filename); err != nil { return Exists(filename) } else { return Exists(filename) } } func RM(filename string) { os.Remove(Path(filename)) } func Daemon(cmdline string, timeout time.Duration) int { for { RunString(cmdline) time.Sleep(timeout) } } // run something and never return from it // TODO: pass STDOUT, STDERR, STDIN correctly // TODO: figure out how to nohup the process and exit func Exec(cmdline string) { log.Log(INFO, "shell.Run() START "+cmdline) cmd := Chomp(cmdline) // this is like 'chomp' in perl cmdArgs := strings.Fields(cmd) process := exec.Command(cmdArgs[0], cmdArgs[1:len(cmdArgs)]...) process.Stderr = os.Stderr process.Stdin = os.Stdin process.Stdout = os.Stdout process.Start() err := process.Wait() log.Log(INFO, "shell.Exec() err =", err) os.Exit(0) } // run interactively. output from the cmd is in real time func NewRun(workingpath string, cmd []string) error { log.Log(INFO, "NewRun() ", cmd) process := exec.Command(cmd[0], cmd[1:len(cmd)]...) // Set the working directory process.Dir = workingpath process.Stderr = os.Stderr process.Stdin = os.Stdin process.Stdout = os.Stdout process.Start() err := process.Wait() log.Log(INFO, "shell.Exec() err =", err) return err } // return true if the filename exists (cross-platform) func Exists(filename string) bool { _, err := os.Stat(Path(filename)) if os.IsNotExist(err) { return false } return true } // makes the directory func Mkdir(dir string) bool { if Dir(dir) { // already a dir return true } if Exists(dir) { // something else is there return false } Run([]string{"mkdir", "-p", dir}) return true } func IsDir(dirname string) bool { return Dir(dirname) } // return true if the filename exists (cross-platform) func Dir(dirname string) bool { info, err := os.Stat(Path(dirname)) if os.IsNotExist(err) { return false } return info.IsDir() } // Cat a file into a string func Cat(filename string) string { buffer, err := ioutil.ReadFile(Path(filename)) // log.Log(INFO, "buffer =", string(buffer)) if err != nil { return "" } return Chomp(buffer) }