Ich versuche, Prozesse mit meinem Daemon verzweigen und versuchen, sie im Falle meiner Daemon-Abstürze zu verleugnen. Regelmäßige os/exec
ist auf hohem Niveau, deshalb ging ich für syscall.ForkExec
und produzierte den folgenden Code:Golang Exec-Prozess und es zu verleugnen
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)
}
Ich habe auch eine einfache Anwendung aus, die schläft und druckt Hallo Welt und legte es auf Weg.
#include <stdio.h>
int main(){
while(1){
printf("hello world");
fflush(stdout);
usleep(300000);
}
}
Es funktioniert, aber der Prozess wird nicht an den Hintergrund gesendet, wie ich erwartet habe, mein Go-Prozess besitzt noch das Kind. Die SysProcAttr
hat folgende Werte in 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
Ctty int // Controlling TTY fd
Foreground bool // Place child's process group in foreground. (Implies Setpgid. Uses Ctty as fd of controlling TTY)
Pgid int // Child's process group ID if Setpgid.
Pdeathsig Signal // Signal that the process will get when its parent dies (Linux only)
Cloneflags uintptr // Flags for clone calls (Linux only)
UidMappings []SysProcIDMap // User ID mappings for user namespaces.
GidMappings []SysProcIDMap // Group ID mappings for user namespaces.
// GidMappingsEnableSetgroups enabling setgroups syscall.
// If false, then setgroups syscall will be disabled for the child process.
// This parameter is no-op if GidMappings == nil. Otherwise for unprivileged
// users this should be set to false for mappings work.
GidMappingsEnableSetgroups bool
}
Ich habe versucht, auch die folgenden, aber es einen Fehler verursacht:
Sys: &syscall.SysProcAttr{
Setsid: true,
Setctty: true,
Foreground: false,
},
Spawned proc 0 inappropriate ioctl for device
Auch die folgenden:
Sys: &syscall.SysProcAttr{
Setsid: true,
Setctty: true,
Foreground: false,
Noctty: true,
Setpgid: true,
},
Spawned proc 0 operation not permitted (with root privilleges)
Was mache ich/falsch annehmen? Hinweis: Trotz der Aussage, os/exec ist High-Level, habe ich auch Folgendes versucht, aber es produzierte die gleichen Ergebnisse.
cs := exec.Command(binary)
cs.SysProcAttr = &syscall.SysProcAttr{
Setctty: true,
}
err := cs.Run()
fmt.Println(err)
Warum denken Sie 'exec.Cmd' zu hoch Ebene? Sie haben von dort aus auch Zugriff auf SysProcAttr. Was meinst du mit deinem Prozess? Liegt es in derselben Prozessgruppe? Wird es nicht zu PID 1 neu zugewiesen, wenn das Elternteil beendet wird? – JimB