Próbuję rozwidlić procesy za pomocą mojego demona i próbuję go odrzucić w przypadku awarii mojego demona. Regularne os/exec
jest na wysokim poziomie, dlatego poszedłem na syscall.ForkExec
i produkowane następujący kod:Proces wykonywania Golanga i jego wyrzucenie
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)
}
Mam również wykonany prosty wniosek, że śpi i drukuje Hello World i umieścić go na ścieżce.
#include <stdio.h>
int main(){
while(1){
printf("hello world");
fflush(stdout);
usleep(300000);
}
}
Działa, jednak proces nie jest wysyłany do tła, jak się spodziewałem, mój proces go nadal jest właścicielem dziecka. SysProcAttr
ma następujące wartości w systemie 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
}
Próbowałem również ale on spowodował błąd:
Sys: &syscall.SysProcAttr{
Setsid: true,
Setctty: true,
Foreground: false,
},
Spawned proc 0 inappropriate ioctl for device
również:
Sys: &syscall.SysProcAttr{
Setsid: true,
Setctty: true,
Foreground: false,
Noctty: true,
Setpgid: true,
},
Spawned proc 0 operation not permitted (with root privilleges)
Co robię/zakładając, że źle? Uwaga: Mimo że mówię, że os/exec jest na wysokim poziomie, próbowałem również następujących rzeczy, ale przyniosły one takie same wyniki.
cs := exec.Command(binary)
cs.SysProcAttr = &syscall.SysProcAttr{
Setctty: true,
}
err := cs.Run()
fmt.Println(err)
Dlaczego sądzisz 'exec.Cmd' jest zbyt wysoki poziom? Masz również dostęp do SysProcAttr. Co masz na myśli, mówiąc, że Twój proces wciąż jest właścicielem dziecka? Czy jest w tej samej grupie procesów? Czy nie zostanie ponownie przypisany do PID 1, jeśli rodzic wyjdzie? – JimB