go - 使用以编程方式编写并连接到os.stdin的stdin执行命令

标签 go

我正在从Go程序中执行docker-compose可执行文件。要配置它,我将docker-compose配置直接通过管道传递到docker-compose的stdin。在大多数情况下,这都可以正常工作,代码大致如下所示(为简单起见,我删除了代码段中的所有错误处理):

args = append([]string{"-f", "-"}, args...)
cmd := exec.Command("docker-compose", args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Stdin = strings.NewReader(input)
cmd.Run()
args是传递给docker-compose的参数,input是作为YAML字符串的docker-compose配置。

尽管这在大多数情况下都有效,但对于交互式命令而言却失败了。 Stdin未连接到os.stdin,命令失败。我可以使用以下代码获取交互式命令:
cmd := exec.Command("docker-compose", args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Stdin = os.Stdin
cmd.Run()

但这并没有传递配置的内容,最后我需要这样做。我试图以某种方式组合这些版本,但无法正常工作:
input, _ := getDockerComposeAsYaml(config)
args = append([]string{"-f", "-"}, args...)
cmd := exec.Command("docker-compose", args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr

stdin, _ := cmd.StdinPipe()

go func() {
    //defer stdin.Close()
    io.WriteString(stdin, input)
}()
cmd.Run()

我尝试了上面的代码,无论是否显式关闭stdin,但所需的行为应该是不关闭stdin,因为我想保持stdin打开以进行交互使用。如果不关闭程序,则该程序将永远挂起,而关闭stdin则无法按预期进行交互。

将已执行程序的stdin连接到os.stdin,同时仍然能够在开始时通过管道传输一些正确的方法是什么?

最佳答案

写入stdin(使用cmd.StdinPipe创建的管道)的goroutine应该:

  • 编写input字符串
  • 然后循环到真正的os.Stdin,将获取的所有内容写入stdin
  • os.Stdin上遇到EOF时,请明确关闭stdin

  • 但是,子进程可能在os.Stdin关闭之前退出。在这种情况下,管道(stdin将由exec.Command关闭)。您的循环应检查是否有闭合的stdin,如果发生则退出goroutine。

    关于go - 使用以编程方式编写并连接到os.stdin的stdin执行命令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61247109/

    相关文章:

    linux - Go通知macOS

    go - go中“无法分配给取消引用”是什么意思?

    go - 如何将记录器中间件输出数据传递到golang中的mysql表中?

    golang 时区夏令时不起作用

    ruby - Rust 数学错误

    html - 去使用下拉值

    go - 如何使用 GORM 初始化具有外键约束的结构并将其插入数据库

    networking - 使用 ResponseWriter.Write 在 Go 中连接 250 次后出现 "localhost: no such host"

    http - 如何让 Go 的 net/http 包停止删除双斜杠?

    go - 如何在 golang ssh 中使用加密的私钥