Search code examples
gonohup

nohup return to back to program in golang


We are trying to excute a nohup script from the golang and here is the command we excute

cmd := exec.Command("nohup","sh",destinationDirPath + "/pf_file_monitor.sh","&>",destinationDirPath + "/nohup.out","&")
_,err = cmd.Output();

The problem is after excuting this command the control is not returing back to the program.

Can anyone please assist me in this ?


Solution

  • So it seems that there are a few things that are tripping out up. I've rewritten the code below, but let me first address each one explicitly so I can explain what I think the confusion is and explain my changes:

    • destinationDirPath + "/pf_file_monitor.sh" - this isn't technically wrong, but it's much more idiomatic (and more reliable) to use filepath.Join; as a general rule, you should never be doing manual string concatenation of paths unless you have a good reason
    • $> - I assume what you're trying to do here is redirect the output of the command to the log file. The issue here is that the symbol $> is only meaningful when you're in a shell (like sh or bash). Go, on the other hand, just sees it as another command line argument, and passes it as an argument to the program. Thus, you're going to have to do this manually. In the example I give below, what I do is open the file up and then set cmd's stdout and stderr pipes (these are io.Writers that control where stdout and stderr go) to the file handle.
    • It won't run in the background. The problem here is that you're using the Run method, which will run the command and block until it finishes. You instead want the Start method, which only starts the command and then immediately returns so your program can keep running.

    Hope this helps! Here's the updated implementation:

    script := filepath.Join(destinationDirPath, "pf_file_monitor.sh")
    log := filepath.Join(destinationDirPath, "nohup.out")
    cmd := exec.Command("nohup", "sh", script)
    
    f, err := os.Create(log)
    if err != nil {
        // handle error
    }
    
    // redirect both stdout and stderr to the log file
    cmd.Stdout = f
    cmd.Stderr = f
    
    // start command (and let it run in the background)
    err = cmd.Start()
    if err != nil {
        // handle error
    }