golang exec background process and get its pid

huangapple go评论92阅读模式
英文:

golang exec background process and get its pid

问题

情况:

我想运行一个将自己放入后台的命令。如果可能的话,我会在前台运行该命令,并自己将其放入后台。

问题:

当进程在后台运行时,我如何使用Go获取它的pid

我尝试了以下方法:

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

这会立即返回,并在后台运行ssh。但它的pid不是正在运行的ssh进程的pid。而且,它是在ssh进程分叉并将自己放入后台之前的父ssh进程的pid

英文:

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.

答案1

得分: 38

你不需要任何特殊的东西,只需不要告诉ssh将自己放到后台,并且不要使用Wait()等待它。以下是一个示例:

$ 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

希望对你有所帮助!

英文:

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

答案2

得分: 5

@Mostafa Hussein,可以使用goroutine进行等待和管理进程。

func main() {
    cmd := exec.Command("shell.sh")
    err := cmd.Start()
    if err != nil {
        return err
    }
    pid := cmd.Process.Pid
    // 使用goroutine进行等待和管理进程
    // 这很重要,否则进程会变为S模式
    go func() {
        err = cmd.Wait()
        fmt.Printf("命令执行完毕,错误信息:%v", err)
    }()
    return nil
}
英文:

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

huangapple
  • 本文由 发表于 2016年9月15日 17:53:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/39508086.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定