Situation:
I want to run a command that puts itself into the background. If it makes it more possible, then I'll run the command in foreground and bring it into the background by myself.
Question:
When the process runs in background: how can I get it's pid
using Go?
I tried the following:
cmd := exec.Command("ssh", "-i", keyFile, "-o", "ExitOnForwardFailure yes", "-fqnNTL", fmt.Sprintf("%d:127.0.0.1:%d", port, port), fmt.Sprintf("%s@%s", serverUser, serverIP)) cmd.Start() pid := cmd.Process.Pid cmd.Wait()
This returns instantly and leaves ssh
running in the background. But it's pid
is not the pid
of the running ssh
process. Moreover, it's the pid
of the parent ssh
process before it forked and backgrounded itself.
We can reconnect a background job to our terminal with the Linux command fg. This command will bring job 2 into the foreground. If no job ID is given, fg will assume we're referring to the current (suspended) job.
The exec package is defined under the OS package. It is simply a sub-package that allows you to execute external commands using Go. In this guide, we will explore how we can use the exec package in to run external commands.
You don't need anything special, just don't tell ssh to background itself and don't Wait()
for it. Example:
$ cat script.sh #!/bin/sh sleep 1 echo "I'm the script with pid $$" for i in 1 2 3; do sleep 1 echo "Still running $$" done $ cat proc.go package main import ( "log" "os" "os/exec" ) func main() { cmd := exec.Command("./script.sh") cmd.Stdout = os.Stdout err := cmd.Start() if err != nil { log.Fatal(err) } log.Printf("Just ran subprocess %d, exiting\n", cmd.Process.Pid) } $ go run proc.go 2016/09/15 17:01:03 Just ran subprocess 3794, exiting $ I'm the script with pid 3794 Still running 3794 Still running 3794 Still running 3794
@Mostafa Hussein, can use goroutine waiting, manage process
function main() cmd := exec.Command( "shell.sh" ) err := cmd.Start() if err != nil { return err } pid := cmd.Process.Pid // use goroutine waiting, manage process // this is important, otherwise the process becomes in S mode go func() { err = cmd.Wait() fmt.Printf("Command finished with error: %v", err) }() return nil }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With