Interactive bash inside GoLang

Team,

I have small helloworld go routine that calls the shell script hello.sh.
In hello.sh, I have made a code to prompt your response and simply prints that response.
In hello.go, go routine, I need to pass the control over the shell script (hello.sh) so that it directly ask for the user input as in the code. Below are the codes for your reference.

#### Hello.go

package main
import (
“fmt”
//“log”
“os/exec”
“bytes”
//“syscall”
//“bufio”
“os”
//“time”
//“strings”
)

func main() {
fmt.Printf(“hello, world\n”)
var out bytes.Buffer
var stderr bytes.Buffer
cmd := exec.Command("/bin/sh", “/Users/z003swb/go/nagy/src/hello.sh”)
cmd.Stdout = &out
cmd.Stderr = &stderr
cmd.Stdin = os.Stdin
cmd.Run()
fmt.Printf("%s\n", out.String())
}

#### Hello.sh

echo “”
echo "Calling Hello sh script at date"
echo "Hai at date"
echo “Do you want to say Yes|No?”
read name
echo “respone was : $name”
echo "Bye at date"

### My Question/Help needed?
+++++++++++++++++++++++++

I want the command in the shell echo “Do you want to say Yes|No?” to be displayed while execution and takes the input from the user.

Right now, by having cmd.Stdin = os.Stdin, I could able to pass the value to the shell, although I am not getting the call directly from the shell code.

#### Sample execution

$ ./hello
hello, world
yes

Calling Hello sh script at Thu May 6 11:32:07 IST 2021
Hai at Thu May 6 11:32:07 IST 2021
Do you want to say Yes|No?
respone was : yes
Bye at Thu May 6 11:32:10 IST 2021

But, how do I make the shell to ask for the input and display “Do you want to say Yes|No?” in the execution? Is there any way we can achieve that? Please help. I am a beginner and so needed expertise help here. Thank you.

You don’t need to use bytes.Buffer as an output.
you can just do cmd.Stdout = os.Stdout; cmd.Stderr = os.Stderr
You might also write your own implementation of io.Writer e.g.

type writer struct {
        w bytes.Buffer
}

func (w *writer) Write(b []byte) (n int, err error) {
        n1, err := os.Stdout.Write(b)
        if err != nil {
                return n1, err
        }

        n2, err := w.w.Write(b)
        if err != nil {
                return n2, err
        }

        return len(b), nil
}

func (w *writer) String() string { return w.w.String() }

*ofc, Write method should check each n1 and n2

@ gucio321

Hi, Thanks a lot for the response. But, how do I make it prompted for "echo “Do you want to say Yes|No?”, which is there in hello.sh ? That’s not happening. That’s the issue.

I need to call/prompted for input from the shell through go code and respond that back to shell from go.

Thanks much again for your post.

gucio321 said that if you want to see the prompt from hello.sh and be able to respond via the terminal, then set the command’s Stdout = os.Stdout and Stderr = os.Stderr. This will let hello.sh interact with the terminal the same way it would if it was run from your shell.

I’m not sure what you’re asking for here. Do you want a user to see and interact with hello.sh via the shell or do you want your Go program to intercept it and respond?

As others have noted, you can just assign Stdin/out/error to os:

cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr

I’d be willing to bet the reason you aren’t getting any prompt/output, though, is because cmd.Run is returning an error and you’re not doing anything with it. Change this line to check for errors:

// Change this...
cmd.Run()
// ... to this:
if err := cmd.Run(); err != nil {
	fmt.Println(err)
}

… and I bet you will get an error that tells you exactly what is going on.

EDIT: I didn’t realize I was so late to the party here. Oops. :slight_smile: