【问题标题】:Execute command with stdin written programmatically and connected to os.stdin使用以编程方式编写并连接到 os.stdin 的标准输入执行命令
【发布时间】:2020-04-16 09:37:47
【问题描述】:

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

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 是 docker-compose 配置为 YAML 字符串。

虽然这适用于大多数情况,但对于交互式命令它会失败。标准输入未连接到 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()

我在明确关闭和不关闭标准输入的情况下尝试了上述代码,尽管所需的行为应该是不关闭它,因为我想保持标准输入打开以供交互使用。不关闭程序只会永远挂起,关闭标准输入它不会按预期交互工作。

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

【问题讨论】:

    标签: go


    【解决方案1】:

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

    1. input字符串
    2. 然后在真正的os.Stdin 上循环,将它得到的所有内容写入stdin
    3. 当在 os.Stdin 上遇到 EOF 时,明确关闭 stdin

    但是,子进程可能会在os.Stdin 关闭之前退出。在这种情况下,管道(stdin 将被exec.Command 关闭)。你的循环应该检查关闭的stdin 并在发生这种情况时退出 goroutine。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-03
      • 2013-05-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-28
      相关资源
      最近更新 更多