在golang程序中运行交互式shell脚本

时间:2020-02-29 13:14:54

标签: go

我想在golang程序中运行交互式shell脚本, 例如包装“ ping 8.8.8.8”,“ python”,“ bc”,“ mysql -H -P -u -p”。 当golang程序本身完成调用交互式命令或shell并与用户进行交互时,应退出该程序。

我尝试了“ exec.Command(“ python”)。Run()“,但是golang程序刚刚完成,什么也没给我。

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)
    }
}

2 个答案:

答案 0 :(得分:1)

将命令的stdin,stdout和stderr连接到父进程的stdin,stdout和stderr。另外,在-c中向exec.Command提供bash,否则bash会尝试像运行shell脚本一样运行程序。

例如,启动交互式Python控制台:

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")
}

答案 1 :(得分:0)

听起来您想用尝试启动的命令替换当前进程。启动另一个命令后,Go程序消失了,调用者与启动的程序进行交互,就好像它是最初启动的东西一样。

为此,您需要低级syscall.Exec函数。通常,您不应该期望它返回。请注意,您需要提供许多详细信息,例如要运行的实际二进制文件以及高级包装程序不需要的环境。 (非常快速的Google搜索找到了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)

就底层Unix系统调用而言,诸如os.StartProcessexec.Cmd之类的更高级别的接口都是 fork (2)先于在那个孩子中执行(2)。当您的Go进程退出时,该子进程将成为孤立的,并且系统初始化进程将成为其新的父进程。该外壳程序仅看到Go进程已退出,并会产生一个新的外壳程序提示。