I am trying to get output of a interactive child process like python from the parent process. I have tried the following code to change the processes stdin to os.Stdin and stdout to os.Stdout but it isn't working. I can't see the output from the child process on the parent's terminal. Am I missing something or doing it wrong?
func main(){
cmd := exec.Command("python")
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err := cmd.Run()
if err != nil{
fmt.Println("Cannot Execute cmd.")
}
}
Run exec.Command("python", "-i").
By default when running python not in a shell it won't enter interactive mode and won't print anything out.
Related
This question already has an answer here:
How can I redirect the stdout and stderr of a command to both the console and a log file while outputting in real time?
(1 answer)
Closed 5 years ago.
I have a small Go tool which basically allows the user to define an command that than will be run using os/exec.
My problem is that I want to show the user the output (stdout/stderr) of the command.
An example could look like this:
The user defines a command that in the end is sh test.sh.
Content of test.sh:
echo "Start"
sleep 7s
echo "Done"
With my current implementation the user can only see the output once the complete command finished. In the example above the user wouldn't see the output Start until the sleep command and the second echo finish.
I currently retrieve the output of the command like this:
cmd := exec.Command(command, args...)
cmd.Dir = dir
// Attach to the standard out to read what the command might print
stdout, err := cmd.StdoutPipe()
if err != nil {
log.Panic(err)
}
// Execute the command
if err := cmd.Start(); err != nil {
log.Panic(err)
}
buf := new(bytes.Buffer)
buf.ReadFrom(stdout)
log.Print(buf.String())
Is it somehow possible to read the stdout/stderr in real-time. Meaning that as soon as the user defined command creates and output it is printed?
Thank you mh-cbon. That pushed me in the right direction.
The code now looks like this and does exactly what I want it to do. I also found that when I use Run() instead of Start() the execution of the program only continues after the command has finished.
cmd := exec.Command(command, args...)
cmd.Dir = dir
var stdBuffer bytes.Buffer
mw := io.MultiWriter(os.Stdout, &stdBuffer)
cmd.Stdout = mw
cmd.Stderr = mw
// Execute the command
if err := cmd.Run(); err != nil {
log.Panic(err)
}
log.Println(stdBuffer.String())
I have a method that can spawn an interactive process, now how do I log everything (including stdin and stdout) after spawning ?
e.g.,
func execute(cmd1 string, slice []string) {
cmd := exec.Command(cmd1, slice...)
// redirect the output to terminal
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Stdin = os.Stdin
cmd.Run()
}
..
The interactive program could be :
execute(ftp)
I think I have to dup stdin, stdout and read write in separate thread.
Rather than redirecting it's output to the terminal read it and then you can log/print do whatever you want with it.
stdout, err := cmd.StdoutPipe()
b, _ := ioutil.ReadAll(stdout)
fmt.Println(string(b))
Something like the code above would work though there are many options. I think you'll want to remove all that code you have to redirect to the terminal.
you could store the output in a temporary buffer and write it to several places
outBuf := bytes.Buffer{}
cmd := exec.Command(cmd1, slice...)
cmd.Stdout = &outBuf
cmd.Run()
if outBuf.Len() > 0 {
log.Printf("%s", outBuf.String())
fmt.Fprintf(os.Stdout, "%s", outBuf.String())
}
Im trying the following, to use go to bundle a folder of html files using the CMD web2exe.
cmd := exec.Command("web2exe-win.exe", "html-folder --main index.html --export- to windows-x32 --output-dir")
var out bytes.Buffer
cmd.Stdout = &out
err := cmd.Run()
if err != nil {
fmt.Println(err)
}
fmt.Println(out)
When a program exits non-zero it means that it could not run successfully and typically it has written an error message to STDERR (or STDOUT). You should somehow capture or print the output streams so you can inspect them for error messages. For example:
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
Note also that your command line arguments should be separate array elements (instead of space separated elements in a single string as they are now):
cmd := exec.Command("web2exe-win.exe", "html-folder", "--main", "index.html", "--export-to", "windows-x32", "--output-dir")
I want to execute a tmux session using Golang. I'm able to compile and get an exit status 1.
cmd := exec.Command("tmux", "new", "-s", "foo")
err := cmd.Run()
if err != nil {
log.Fatal(err)
}
I want to start a session. At the very least, I want to get a more tangible error. Any docs to refer me to? I couldn't find much on the Tmux manual pages. I think I'm missing a command.
You need to connect tmux to your terminal. Try to add these lines after cmd initialization:
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
UPDATE: link to the playground
I want to execute perforce command line "p4" from Go to do the login job. "p4 login" require user to input password.
How can I run a program that requires user's input in Go?
The following code doesn't work.
err = exec.Command(p4cmd, "login").Run()
if err != nil {
log.Fatal(err)
}
// To run any system commands. EX: Cloud Foundry CLI commands: `CF login`
cmd := exec.Command("cf", "login")
// Sets standard output to cmd.stdout writer
cmd.Stdout = os.Stdout
// Sets standard input to cmd.stdin reader
cmd.Stdin = os.Stdin
cmd.Run()
From the os/exec.Command docs:
// Stdin specifies the process's standard input. If Stdin is
// nil, the process reads from the null device (os.DevNull).
Stdin io.Reader
Set the command's Stdin field before executing it.