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

Start detached command with redirect to file

我正在尝试在分离进程中启动一个命令,以便它可以在 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)
}

显然这样的重定向不起作用。因为我在启动 long 运行 命令后立即退出程序,所以我无法打开文件并将其绑定到 Stdout。

有什么方法可以实现这样的重定向吗?

也许你可以尝试使用这个:

打开文件(os.File 实现 io.Writer),然后将其作为 command.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)
}

不确定这是否是适合您的情况的可行解决方案。我已经在本地试过了,它似乎有效...请记住,您的用户应该能够 create/update 文件。

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

示例:

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 替换为您将其编译成的可执行二进制文件的名称):

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

这个应用只是每秒向标准输出打印一行。您可以看到输出文件是如何写入的,例如tail -f /tmp/out.

请注意,您可以根据自己的喜好(以及 test.sh 脚本的指示)使用其他 shell 来执行脚本。

例如使用bash:

cmd := exec.Command("/bin/bash", "-c", "/tmp/test.sh > /tmp/out")
// rest is unchanged

请注意,shell 执行的命令作为单个 string 参数传递,并且不会像执行它时那样分解为多个直接在命令提示符中。