【问题标题】:Run interactive shell script in golang program在 golang 程序中运行交互式 shell 脚本
【发布时间】:2020-11-12 08:13:27
【问题描述】:

我想在 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)
    }
}

【问题讨论】:

    标签: go


    【解决方案1】:

    将命令的标准输入、标准输出和标准错误连接到父进程的标准输入。此外,将exec.Command 中的-c 提供给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")
    }
    

    【讨论】:

    • 这种方法效果很好。我不明白,为什么它没有收到任何赞成票。
    【解决方案2】:

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

    为此,您需要低级 syscall.Exec 函数。您通常不应该期望它返回。请注意,您需要提供许多详细信息,例如要运行的实际二进制文件以及高级包装器不需要的环境。 (一个非常快速的谷歌搜索找到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) 在 execve之前先有一个子进程>(2) 在那个孩子身上。当您的 Go 进程退出时,该子进程将变为孤立,系统 init 进程将成为其新的父进程。 shell 只是看到 Go 进程已经退出,并会产生一个新的 shell 提示符。

    【讨论】:

    • 下面使用Connect命令的stdin、stdout和stderr与父进程的答案有什么区别?
    • 在我的回答中没有“父进程”; Go 程序将自身替换为 exec 程序,并且父进程 ID 与 Go 程序的相同。在@ShengjianDing's answer 中,Go 程序保留并成为子进程的父进程;它负责检查错误状态和其他任务。
    猜你喜欢
    • 2021-07-11
    • 1970-01-01
    • 2019-09-18
    • 2017-02-13
    • 2013-06-19
    • 1970-01-01
    • 2016-05-29
    • 2012-07-03
    相关资源
    最近更新 更多