Start detached command with redirect to file

…衆ロ難τιáo~ 提交于 2020-08-19 08:36:26

问题


I'm trying to start a command in a detached process so that it can continue after go program exits. I need to redirect the output of the command to a file.

What I need is something like this:

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

Obviously such redirect doesn't work. As I immediately exit from the program after starting the long running command, I cannot open a file and bind it to the Stdout.

Is there any way to achieve such a redirect?


回答1:


Maybe you can try to use this: https://stackoverflow.com/a/28918814/2728768

Opening a file (and os.File implements io.Writer), and then passing it as the command.Stdout could do the trick:

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

Not sure this could be a viable solution for your case. I've tried it locally and it seems working... remember that your user should be able to create/update the file.




回答2:


You may start a shell which executes your command / app, and you may redirect its output to a file. The shell will continue to run and execute your script / app even if your Go app exits.

Example:

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)

Test it with this simple Go app (replace /tmp/test.sh with the name of the executable binary you compile this into):

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

This app simply prints a line to the standard output once every second. You can see how the output file is being written e.g. with tail -f /tmp/out.

Note that you may use other shells to execute your scripts to your liking (and to what the test.sh script dictates).

For example to use bash:

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

Note that the command to be executed by the shell is passed as a single string argument, and it is not broken down into multiple as you would do it if you were to execute it directly in the command prompt.



来源:https://stackoverflow.com/questions/40243197/start-detached-command-with-redirect-to-file

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!