2013-08-07 6 views
9

Chcę zaimplementować "opakowanie procesu" w Go. Zasadniczo, co to zrobi, uruchomi proces (powiedzmy serwer węzła) i go monitoruje (przechwytuje sygnały, takie jak SIGKILL, SIGTERM ...)Sygnały złapania Golanga

Myślę, że sposób na to, aby uruchomić serwer węzła za darmo rutynowego korzystania syscall.Exec:

func launchCmd(path string, args []string) { 
    err := syscall.Exec(path, args, os.Environ()) 
    if err != nil { 
    panic(err) 
    } 
} 

Następnie chciałbym złapać wszelkie możliwe sygnały generowane przez komendę wykonywanego przez syscall. Jestem całkiem nowy w Go, każda pomoc będzie doceniona.

+0

[Zobacz również] (http://stackoverflow.com/q/11268943/720999). – kostix

Odpowiedz

30

Istnieją trzy sposoby wykonania programu w Go:

  1. syscall pakiet z syscall.Exec, syscall.ForkExec, syscall.StartProcess
  2. os pakiet z os.StartProcess
  3. os/exec pakiet z exec.Command

syscall.StartProcess ma niski poziom. Zwraca ona uintptr jako uchwyt.

os.StartProcess daje ładne struktury os.Process, które można nazwać Signal na. os/exec daje Ci io.ReaderWriter do użycia na rurze. Oba używają wewnętrznie syscall.

Sygnały odczytowe wysłane z proces inny niż własny wydaje się nieco skomplikowany. Gdyby było to możliwe, mógłby to zrobić syscall. Nie widzę niczego oczywistego w pakietach wyższego poziomu.

Aby odbierać sygnał można użyć signal.Notify takiego:

sigc := make(chan os.Signal, 1) 
signal.Notify(sigc, 
    syscall.SIGHUP, 
    syscall.SIGINT, 
    syscall.SIGTERM, 
    syscall.SIGQUIT) 
go func() { 
    s := <-sigc 
    // ... do something ... 
}() 

wystarczy zmienić sygnały, które Cię interesują słuchania. Jeśli nie określisz sygnału, będzie on przechwytywał wszystkie sygnały, które można uchwycić.

Użytkownik użyłby syscall.Kill lub Process.Signal do odwzorowania sygnału. Możesz pobrać pid od Process.Pid lub w wyniku syscall.StartProcess.

+0

Thx spróbuję. Chodzi o to, żeby owijarz był monitorowany przez upsstart, po prostu będzie używany do śledzenia tego, co się stało – rmonjo

+0

Ok mogę przechwytywać sygnały, które są wprowadzane do programu (jeśli na przykład^C), ale nie mogę uzyskać generowanych sygnałów przez mój program wykonywany przez syscall. Jakiekolwiek myśli ? – rmonjo

+0

@rmonjo Próbujesz złapać sygnał wysłany * z * Twojego programu lub * do *? – Luke

16

Można użyć signal.Notify:

import (
"os" 
"os/signal" 
"syscall" 
) 

func main() { 
    signalChannel := make(chan os.Signal, 2) 
    signal.Notify(signalChannel, os.Interrupt, syscall.SIGTERM) 
    go func() { 
     sig := <-signalChannel 
     switch sig { 
     case os.Interrupt: 
      //handle SIGINT 
     case syscall.SIGTERM: 
      //handle SIGTERM 
     } 
    }() 
    // ... 
}