go - Interact with external application from within code (Golang) -
i need able run external application , interact though manually running command-line. examples find deal running program , capturing output.
below simple example hope illustrates trying accomplish.
package main import ( "fmt" "log" "os/exec" ) func main() { cmd := exec.command("rm", "-i", "somefile.txt") out, err := cmd.combinedoutput() if err != nil { log.fatal(err) } if string(out) == "remove file 'somefile.txt'?" { // send response 'y' rm process } // program completes normally... }
i've tried tweak various examples i've found accomplish 0 success. seems though 'rm' waiting response, go closes process.
any examples, articles, or advice can provide appreciated. many in advance.
you have 2 possibilities. first use readline() works if application output full lines, , can wait \n. not case rm, have develop custom splitfunction scanner. both versions can found below.
please note can not use combinedoutput, can not scanned. have use pipes.
package main import ( "bufio" //"fmt" "log" "os/exec" ) func main() { cmd := exec.command("rm", "-i", "somefile.txt") // stdout + stderr out, err := cmd.stderrpipe() // rm writes prompt err if err != nil { log.fatal(err) } r := bufio.newreader(out) // stdin in, err := cmd.stdinpipe() if err != nil { log.fatal(err) } defer in.close() // start command! err = cmd.start() if err != nil { log.fatal(err) } line, _, err := r.readline() err != nil { if string(line) == "remove file 'somefile.txt'?" { in.write([]byte("y\n")) } line, _, err = r.readline() } // program completes normally...s }
this second version scanner, , uses both \n , ? line delimiters:
package main import ( "bufio" "bytes" "fmt" "log" "os/exec" ) // ugly hack, bufio.scanlines ? added other delimiter :d func new_scanner(data []byte, ateof bool) (advance int, token []byte, err error) { if ateof && len(data) == 0 { return 0, nil, nil } if := bytes.indexbyte(data, '\n'); >= 0 { // have full newline-terminated line. fmt.printf("nn\n") return + 1, data[0:i], nil } if := bytes.indexbyte(data, '?'); >= 0 { // have full ?-terminated line. return + 1, data[0:i], nil } // if we're @ eof, have final, non-terminated line. return it. if ateof { return len(data), data, nil } // request more data. return 0, nil, nil } func main() { cmd := exec.command("rm", "-i", "somefile.txt") // stdout + stderr out, err := cmd.stderrpipe() // again, rm writes prompts stderr if err != nil { log.fatal(err) } scanner := bufio.newscanner(out) scanner.split(new_scanner) // stdin in, err := cmd.stdinpipe() if err != nil { log.fatal(err) } defer in.close() // start command! err = cmd.start() if err != nil { log.fatal(err) } // start scanning scanner.scan() { line := scanner.text() if line == "rm: remove regular empty file ‘somefile.txt’" { in.write([]byte("y\n")) } } // report scanner's errors if err := scanner.err(); err != nil { log.fatal(err) } // program completes normally...s }
Comments
Post a Comment