Golang exec 进程并否认它

我正在尝试使用我的守护进程来分叉进程,并试图在我的守护进程崩溃时不承认它们。常规os/exec是高级别的,因此我选择syscall.ForkExec并生成了以下代码:


package main


import (

    "fmt"

    "os"

    "os/exec"

    "syscall"

    "time"

)


func main() {


    cmd := "myproc"

    binary, lookErr := exec.LookPath(cmd)

    if lookErr != nil {

        panic(lookErr)

    }

    fmt.Println(binary)


    os.Remove("/tmp/stdin")

    os.Remove("/tmp/stdout")

    os.Remove("/tmp/stderr")


    fstdin, err1 := os.Create("/tmp/stdin")

    fstdout, err2 := os.Create("/tmp/stdout")

    fstderr, err3 := os.Create("/tmp/stderr")

    if err1 != nil || err2 != nil || err3 != nil {

        fmt.Println(err1, err2, err3)

        panic("WOW")

    }


    argv := []string{"hi"}

    procAttr := syscall.ProcAttr{

        Dir:   "/tmp",

        Files: []uintptr{fstdin.Fd(), fstdout.Fd(), fstderr.Fd()},

        Env:   []string{"VAR1=ABC123"},

        Sys: &syscall.SysProcAttr{

            Foreground: false,

        },

    }


    pid, err := syscall.ForkExec(binary, argv, &procAttr)

    fmt.Println("Spawned proc", pid, err)


    time.Sleep(time.Second * 100)

}

我还制作了一个简单的应用程序,它可以休眠并打印 hello world 并将其放入路径。


#include <stdio.h>


int main(){

    while(1){

        printf("hello world");

        fflush(stdout);

        usleep(300000);

        }

}

它可以工作,但是,该过程没有像我预期的那样发送到后台,我的 go 过程仍然拥有孩子。该SysProcAttr拥有的Linux以下值:


type SysProcAttr struct {

    Chroot      string         // Chroot.

    Credential  *Credential    // Credential.

    Ptrace      bool           // Enable tracing.

    Setsid      bool           // Create session.

    Setpgid     bool           // Set process group ID to Pgid, or, if Pgid == 0, to new pid.

    Setctty     bool           // Set controlling terminal to fd Ctty (only meaningful if Setsid is set)

    Noctty      bool           // Detach fd 0 from controlling terminal

}


叮当猫咪
浏览 154回答 3
3回答

aluckdog

Start()即使在其父进程死亡后,被分叉的进程仍将继续。func forker() {&nbsp; &nbsp; cmd := exec.Command("sleep", "3")&nbsp; &nbsp; cmd.Start()&nbsp; &nbsp; time.Sleep(2 * time.Second)&nbsp; &nbsp; os.Exit(1)}在这里,sleep即使父进程只存活 2 秒,该进程也会愉快地存活 3 秒:&nbsp; $ forker &; while true; do ps -f; sleep 1; done&nbsp; UID&nbsp; &nbsp;PID&nbsp; PPID&nbsp; &nbsp;C STIME&nbsp; &nbsp;TTY&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;TIME CMD&nbsp; 501 71423 69892&nbsp; &nbsp;0&nbsp; 3:01PM ttys003&nbsp; &nbsp; 0:00.07 forker&nbsp; 501 71433 71432&nbsp; &nbsp;0&nbsp; 3:01PM ttys003&nbsp; &nbsp; 0:00.00 sleep 3&nbsp; UID&nbsp; &nbsp;PID&nbsp; PPID&nbsp; &nbsp;C STIME&nbsp; &nbsp;TTY&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;TIME CMD&nbsp; 501 71423 69892&nbsp; &nbsp;0&nbsp; 3:01PM ttys003&nbsp; &nbsp; 0:00.07 forker&nbsp; 501 71433 71432&nbsp; &nbsp;0&nbsp; 3:01PM ttys003&nbsp; &nbsp; 0:00.00 sleep 3&nbsp; UID&nbsp; &nbsp;PID&nbsp; PPID&nbsp; &nbsp;C STIME&nbsp; &nbsp;TTY&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;TIME CMD&nbsp; 501 71433&nbsp; &nbsp; &nbsp;1&nbsp; &nbsp;0&nbsp; 3:01PM ttys003&nbsp; &nbsp; 0:00.00 sleep 3通知父进程ID(如何PPID)的的sleep过程变得1当父进程71432退出。这意味着该sleep进程已被孤立。

HUX布斯

似乎立即放弃的好策略是os.Argv[0]生成进程(自生成),然后生成目标进程(使用 Setsid:true),然后退出第一个生成的进程。这样 gradchild 进程立即获得 ppid 1。可选地,第一个衍生的进程可以在退出之前通过 stdout 将孙子的 pid 传递给父进程。

冉冉说

在Start()方法应该给你你在找什么。我的示例 Go 程序终止后附加一个简单文本文件的脚本继续运行:package mainimport (&nbsp; &nbsp; "os/exec")func main() {&nbsp; &nbsp; cmd := exec.Command("./appender.sh")&nbsp; &nbsp; cmd.Start()}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go