Go 使用重定向到文件启动分离的命令

Go 使用重定向到文件启动分离的命令,go,process,io,Go,Process,Io,我正在尝试在分离的进程中启动一个命令,以便在go程序退出后继续。我需要将命令的输出重定向到一个文件 我需要的是这样的东西: func main() { command := exec.Command("/tmp/test.sh", ">", "/tmp/out") if err := command.Start(); err != nil { fmt.Fprintln(os.Stderr, "Command failed.", err) o

我正在尝试在分离的进程中启动一个命令,以便在go程序退出后继续。我需要将命令的输出重定向到一个文件

我需要的是这样的东西:

func main() {
    command := exec.Command("/tmp/test.sh", ">", "/tmp/out")

    if err := command.Start(); err != nil {
        fmt.Fprintln(os.Stderr, "Command failed.", err)
        os.Exit(1)
    }

    fmt.Println("Process ID:", command.Process.Pid)
}
显然,这样的重定向不起作用。由于启动长时间运行的命令后立即退出程序,因此无法打开文件并将其绑定到Stdout


有没有办法实现这样的重定向?

也许您可以尝试使用以下方法:

打开一个文件(和
os.file
实现
io.Writer
),然后将其作为
命令传递。Stdout
可以实现以下功能:

func main() {
    command := exec.Command("./tmp/test.sh")
    f, err := os.OpenFile("/tmp/out", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
    if err != nil {
        fmt.Printf("error opening file: %v", err)
    }
    defer f.Close()
    // On this line you're going to redirect the output to a file
    command.Stdout = f
    if err := command.Start(); err != nil {
        fmt.Fprintln(os.Stderr, "Command failed.", err)
        os.Exit(1)
    }

    fmt.Println("Process ID:", command.Process.Pid)
}

我不确定这对你的情况来说是否是一个可行的解决方案。我在当地试过,似乎很管用。。。请记住,您的用户应该能够创建/更新该文件。

您可以启动一个shell来执行您的命令/应用程序,并且可以将其输出重定向到一个文件。即使Go应用程序退出,shell也将继续运行并执行您的脚本/应用程序

例如:

cmd := exec.Command("sh", "-c", "/tmp/test.sh > /tmp/out")
if err := cmd.Start(); err != nil {
    panic(err)
}
fmt.Println("Process ID:", cmd.Process.Pid)
用这个简单的Go应用程序测试它(用编译成的可执行二进制文件的名称替换
/tmp/Test.sh
):


请注意,shell要执行的命令是作为单个
字符串
参数传递的,它不会像在命令提示符下直接执行命令那样分解为多个参数。

这是可行的,但我不理解为什么。进程关闭后如何写入文件?如果这不重要,我们为什么要打开它呢?我没想过。所以,我会调查并返回给您,但我正在阅读文档,exec.Cmd和我们重定向的stdout是由一个writer描述符管理的,我相信,它会负责关闭它(看起来也会打开它…):谢谢您的回答。虽然你的答案没有错,但我还是同意@thoeni的答案,因为它是windows和linux的单一解决方案,对我来说更方便。如果我们需要使用操作系统提供的标准输出和文件重定向,触发后不需要在实际进程之上运行另一个go进程,这是很好的。谢谢
package main
import ("fmt"; "time")
func main() {
    for i := 0; i < 10; i++ {
        fmt.Printf("%d.: %v\n", i, time.Now())
        time.Sleep(time.Second)
    }
}
cmd := exec.Command("/bin/bash", "-c", "/tmp/test.sh > /tmp/out")
// rest is unchanged