Reputation: 335
I want to run an interactive shell script in golang program, such as wrap a "ping 8.8.8.8", "python", "bc", "mysql -H -P -u -p". The golang program should exit when itself finish calling an interactive command,or shell, and leaving spawned interactive with user.
I have tried the "exec.Command("python").Run()", but the golang program just finish and leave nothing to me.
func (h ConnectHandler)ConnectMySQL() {
logrus.Debug("ConnectMySQL, script:",common.CONF.FilePath.MySQLConnectScriptPath)
err :=exec.Command("bash",common.CONF.FilePath.MySQLConnectScriptPath).Run()
if err != nil{
logrus.Errorf("ConnectMySQL failed, exit 1,%s",err)
os.Exit(1)
}
}
Upvotes: 10
Views: 8961
Reputation: 2126
Connect the Command's stdin, stdout, and stderr to those of the parent process. Also, supply -c
in exec.Command
to bash
, else bash
will try to run your program as if it's a shell script.
For example launching the interactive Python console:
func main() {
fmt.Println("Before Python shell:")
cmd := exec.Command("bash", "-c", "/usr/bin/python3")
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
_ = cmd.Run() // add error checking
fmt.Println("After Python shell")
}
Upvotes: 26
Reputation: 158758
It sounds like you want to replace the current process with the command you're trying to launch. After you launch the other command, your Go program is gone, and the caller interacts with the launched program as if it were the thing that was initially started.
You need the low-level syscall.Exec function for this. You shouldn't normally expect it to return. Note that you need to provide a number of details like the actual binary to run and the environment that the higher-level wrappers don't need. (A very quick Google search finds this detailed writeup.)
import "os"
import "syscall"
err := syscall.Exec("/bin/ls", []string{"ls", "-l", "/"}, os.Environ())
// We don't expect this to ever return; if it does something is really wrong
os.panic(err)
In terms of the underlying Unix system calls, the higher-level interfaces like os.StartProcess
and the exec.Cmd
all fork(2) a child process first before execve(2) in that child. When your Go process exits, that child process becomes orphaned, and the system init process becomes its new parent. The shell just sees that the Go process has exited and will produce a new shell prompt.
Upvotes: 7