correct stdin handling. stderr might still be broken
Signed-off-by: Jeff Carr <jcarr@wit.com>
This commit is contained in:
parent
8a5c9922e4
commit
954470c34c
|
@ -0,0 +1,3 @@
|
|||
all:
|
||||
go build
|
||||
./example1
|
Binary file not shown.
|
@ -0,0 +1,27 @@
|
|||
package main
|
||||
|
||||
/*
|
||||
import "log"
|
||||
import "reflect"
|
||||
import "os"
|
||||
*/
|
||||
|
||||
// import "github.com/davecgh/go-spew/spew"
|
||||
|
||||
import "git.wit.com/jcarr/shell"
|
||||
|
||||
func main() {
|
||||
shell.SpewOn()
|
||||
|
||||
shell.Run("ls /tmp")
|
||||
|
||||
shell.Run("ping -c 4 localhost")
|
||||
|
||||
// slow down the polling to every 2 seconds
|
||||
shell.SetDelayInMsec(2000)
|
||||
shell.Run("ping -c 4 localhost")
|
||||
|
||||
// TODO: this might not be working
|
||||
// check error handling
|
||||
shell.Run("ls /tmpthisisnothere")
|
||||
}
|
96
shell.go
96
shell.go
|
@ -16,6 +16,7 @@ var shellStdout *os.File
|
|||
var shellStderr *os.File
|
||||
|
||||
var spewOn bool = false
|
||||
var msecDelay int = 20 // number of milliseconds to delay between reads with no data
|
||||
|
||||
func Script(cmds string) int {
|
||||
// split on new lines (while we are at it, handle stupid windows text files
|
||||
|
@ -40,6 +41,10 @@ func SpewOn() {
|
|||
spewOn = true
|
||||
}
|
||||
|
||||
func SetDelayInMsec(msecs int) {
|
||||
msecDelay = msecs
|
||||
}
|
||||
|
||||
func SetStdout(newout *os.File) {
|
||||
shellStdout = newout
|
||||
}
|
||||
|
@ -85,74 +90,45 @@ func Run(cmdline string) int {
|
|||
newreader := bufio.NewReader(pstdout)
|
||||
nbr := nbreader.NewNBReader(newreader, 1024)
|
||||
|
||||
newerrreader := bufio.NewReader(pstderr)
|
||||
nbrerr := nbreader.NewNBReader(newerrreader, 1024)
|
||||
// nbrerr := nbreader.NewNBReader(newerrreader, 1024)
|
||||
|
||||
tmp := bufio.NewReader(pstderr)
|
||||
go NonBlockingReader(tmp, shellStderr)
|
||||
|
||||
totalCount := 0
|
||||
|
||||
for {
|
||||
time.Sleep(2 * time.Millisecond) // only check the buffer 500 times a second
|
||||
var dead bool = false
|
||||
for (dead == false) {
|
||||
time.Sleep(time.Duration(msecDelay) * time.Millisecond) // only check the buffer 500 times a second
|
||||
// log.Println("sleep done")
|
||||
|
||||
var empty bool = false
|
||||
// tight loop that reads 1K at a time until buffer is empty
|
||||
for {
|
||||
for (empty == false) {
|
||||
oneByte := make([]byte, 1024)
|
||||
count, err := nbr.Read(oneByte)
|
||||
totalCount += count
|
||||
|
||||
if (err != nil) {
|
||||
// log.Println("Read() count = ", count, "err = ", err)
|
||||
log.Println("Read() count = ", count, "err = ", err)
|
||||
oneByte = make([]byte, 1024)
|
||||
count, err = nbr.Read(oneByte)
|
||||
f.Write([]byte(string(oneByte)))
|
||||
f.Flush()
|
||||
empty = true
|
||||
dead = true
|
||||
}
|
||||
f.Write([]byte(string(oneByte)))
|
||||
f.Flush()
|
||||
if (count == 0) {
|
||||
break
|
||||
empty = true
|
||||
}
|
||||
}
|
||||
|
||||
if (totalCount != 0) {
|
||||
log.Println("totalCount = ", totalCount)
|
||||
log.Println("STDOUT: totalCount = ", totalCount)
|
||||
totalCount = 0
|
||||
}
|
||||
|
||||
//
|
||||
// HANDLE STDERR
|
||||
// HANDLE STDERR
|
||||
//
|
||||
oneByte := make([]byte, 1024)
|
||||
count, err := nbrerr.Read(oneByte)
|
||||
|
||||
if (err != nil) {
|
||||
oneByte = make([]byte, 1024)
|
||||
count, err = nbrerr.Read(oneByte)
|
||||
f.Write([]byte(string(oneByte)))
|
||||
f.Flush()
|
||||
|
||||
log.Println("Read() count = ", count, "err = ", err)
|
||||
// spew.Dump(process.Process)
|
||||
// spew.Dump(process.ProcessState)
|
||||
err := process.Wait()
|
||||
if err != nil {
|
||||
if (spewOn) {
|
||||
spew.Dump(err.(*exec.ExitError))
|
||||
spew.Dump(process.ProcessState)
|
||||
}
|
||||
stuff := err.(*exec.ExitError)
|
||||
log.Println("ERROR ", stuff)
|
||||
log.Println("END ", cmdline)
|
||||
return -1
|
||||
}
|
||||
log.Println("END ", cmdline)
|
||||
return 0
|
||||
} else {
|
||||
f.Write([]byte(string(oneByte)))
|
||||
f.Flush()
|
||||
}
|
||||
|
||||
// spew.Dump(reflect.ValueOf(cmd.Process).Elem())
|
||||
}
|
||||
|
||||
err := process.Wait()
|
||||
|
@ -177,3 +153,35 @@ func Daemon(cmdline string, timeout time.Duration) int {
|
|||
time.Sleep(timeout)
|
||||
}
|
||||
}
|
||||
|
||||
// pass in two file handles (1 read, 1 write)
|
||||
func NonBlockingReader(buffReader *bufio.Reader, writeFileHandle *os.File) {
|
||||
// newreader := bufio.NewReader(readFileHandle)
|
||||
|
||||
// create a nonblocking GO reader
|
||||
nbr := nbreader.NewNBReader(buffReader, 1024)
|
||||
|
||||
for {
|
||||
// defer buffReader.Close()
|
||||
// defer writeFileHandle.Flush()
|
||||
defer writeFileHandle.Close()
|
||||
totalCount := 0
|
||||
for {
|
||||
oneByte := make([]byte, 1024)
|
||||
count, err := nbr.Read(oneByte)
|
||||
if (err != nil) {
|
||||
log.Println("count, err =", count, err)
|
||||
return
|
||||
}
|
||||
totalCount += count
|
||||
if (count == 0) {
|
||||
time.Sleep(time.Duration(msecDelay) * time.Millisecond) // without this delay this will peg the CPU
|
||||
if (totalCount != 0) {
|
||||
log.Println("STDERR: totalCount = ", totalCount)
|
||||
totalCount = 0
|
||||
}
|
||||
}
|
||||
writeFileHandle.Write([]byte(string(oneByte)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue