2013-08-07 10 views
9

Voglio implementare un "wrapper di processo" in Go. Fondamentalmente quello che farà, è avviare un processo (diciamo un server nodo) e monitorarlo (prendere segnali come SIGKILL, SIGTERM ...)Segnali di cattura Golang

Penso che il modo per fare sia lanciare il server nodo in un go di routine utilizzando syscall.Exec:

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

Poi mi piacerebbe cogliere ogni possibile segnali generati dal comando eseguito da syscall. Sono abbastanza nuovo per andare, ogni aiuto sarebbe apprezzato.

+0

[vedi anche] (http://stackoverflow.com/q/11268943/720999). – kostix

risposta

30

ci sono tre modi di esecuzione di un programma in Go:

  1. syscall pacchetto con syscall.Exec, syscall.ForkExec, syscall.StartProcess
  2. os pacchetto con os.StartProcess
  3. os/exec pacchetto con exec.Command

syscall.StartProcess è di basso livello. Restituisce un uintptr come handle.

os.StartProcess fornisce una bella struttura os.Process che è possibile chiamare Signal su. os/exec ti dà io.ReaderWriter da utilizzare su una pipe. Entrambi usano internamente syscall.

I segnali di lettura inviati da un processo diverso dal proprio sembra un po 'complicato. Se fosse possibile, syscall sarebbe in grado di farlo. Non vedo nulla di ovvio nei pacchetti di livello superiore.

per ricevere un segnale è possibile utilizzare signal.Notify come questo:

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

Hai solo bisogno di cambiare i segnali che ti interessa ascoltare. Se non si specifica un segnale, catturerà tutti i segnali che possono essere catturati.

È possibile utilizzare syscall.Kill o Process.Signal per mappare il segnale. È possibile ottenere il pid da Process.Pid o come risultato da syscall.StartProcess.

+0

Thx ci proverò. L'idea è di avere questo wrapper monitorato da upstart, sarà solo usato per tenere traccia di quello che è successo – rmonjo

+0

Ok, posso catturare i segnali che vengono inseriti nel programma (se faccio^C per esempio) ma non posso ottenere i segnali generati dal mio programma eseguito da syscall. Qualche pensiero? – rmonjo

+0

@rmonjo Stai cercando di catturare un segnale inviato * da * il tuo programma o * a *? – Luke

16

È possibile utilizzare 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 
     } 
    }() 
    // ... 
}