2017-05-29 3 views
1

Ich versuche, den notwendigen Code hinzuzufügen, um meine App wie ein Daemon auszuführen. Früher habe ich das nächste Projekt:Daemon führt nur einmal eine Goroutine aus

  • github.com/sevlyar/go-daemon

ich die Probe gehen Code neu geschrieben, dass es fertig ist: https://github.com/sevlyar/go-daemon/blob/master/sample/sample.go

package main 

import (
    "bufio" 
    "flag" 
    "fmt" 
    "io/ioutil" 
    "os" 
    "syscall" 
    "time" 

    "github.com/sevlyar/go-daemon" 
) 

var (
    signal = flag.String("s", "", `sdaemon -s ... 
     quit -- graceful shutdown`) 
) 

var (
    stop = make(chan struct{}) 
    done = make(chan struct{}) 
) 

func main() { 
    flag.Parse() 
    daemon.AddCommand(daemon.StringFlag(signal, "quit"), syscall.SIGQUIT, TermHandler) 

    cntxt := &daemon.Context{ 
     PidFileName: "/var/run/sdaemon.pid", 
     PidFilePerm: 0644, 
     WorkDir:  "./", 
     Umask:  027, 
     Args:  []string{"[sdaemon]"}, 
    } 
    if len(daemon.ActiveFlags()) > 0 { 
     d, _ := cntxt.Search() 
     daemon.SendCommands(d) 
     return 
    } 
    d, err := cntxt.Reborn() 
    if d != nil { 
     return 
    } 
    if err != nil { 
     os.Exit(1) 
    } 
    defer cntxt.Release() 

    // Start daemon 
    go Worker() 

    err = daemon.ServeSignals() 
    if err != nil { 
     fmt.Printf("STOPPED!\n") 
     return 
    } 
} 

func Worker() { 
    for { 
     go Writer() 
     if _, ok := <-stop; ok { 
      break 
     } 
    } 
    done <- struct{}{} 
} 

func TermHandler(sig os.Signal) error { 
    stop <- struct{}{} 
    if sig == syscall.SIGQUIT { 
     <-done 
    } 
    return daemon.ErrStop 
} 

ich hinzugefügt haben, ein Funktion Writer() lesen Sie eine Datei, behalten Sie den Text wie eine Zeichenfolge und erstellen Sie eine neue Datei mit dieser Zeichenfolge.

func Writer() error { 
    time.Sleep(time.Minute) 

    f, _ := ioutil.ReadFile("$HOME/test") 
    contents := string(f) 

    fileHandle, _ := os.Create("$HOME/stest") 
    writer := bufio.NewWriter(fileHandle) 
    defer fileHandle.Close() 
    fmt.Fprintln(writer, contents) 
    writer.Flush() 

    return nil 
} 

Ich behandle nicht so gut, um die Kanäle in golang und ich weiß nicht, warum die unendliche Schleife in Worker() Funktion nur einmal ausgeführt wird ...

Können Sie mir bitte helfen?

Antwort

1

Das Problem ist in der Worker-Funktion, wenn Sie versuchen, zu überprüfen, ob Sie Daten im done-Kanal haben. Der Anruf receive wird blockiert, bis ein Wert gelesen wird, so dass der Anruf blockiert wird, bis Sie ein Signal an den Prozess senden.

Der zweite Wert, der vom Empfangsoperator ok zurückgegeben wird, zeigt nicht an, ob ein Wert erfolgreich gelesen wurde oder nicht. Es zeigt nur an, ob der Kanal geschlossen wurde, als versucht wurde, einen Wert zu empfangen (wenn dies der Fall ist, wird zero value zurückgegeben, siehe).

Um zu überprüfen, ob es einen Wert im Kanal ist, dass Sie eine select Anweisung verwenden müssen, wie folgt aus:

select { 
     case v, ok <- stop: 
      // We could read a value from the channel 
     default: 
      // No value could be read, but we didn't block 
} 

So Ihre Worker Funktion etwas aussehen sollte:

func Worker() { 
    for { 
     time.Sleep(time.Minute) 
     select { 
     case <- stop: 
      // Got a stop signal, stopping 
      done <- struct{}{} 
      return 
     default: 
      // No stop signal, continuing loop 
     } 

     go Writer() 
    } 
} 

Beachten Sie, dass Ich habe die Sleep aus der Writer Funktion in die Worker verschoben, sonst würden Sie mit Tausenden von gleichzeitigen Writer Go-Routinen enden ...

+0

Nun funktioniert die Funktion 'Writer()', aber wenn ich 'sdaemon -s quit' einfüge, um ein ordnungsgemäßes Herunterfahren zu machen, funktioniert es nicht, bevor es funktioniert; Weißt du, was ist das Problem? Vielen Dank für Ihre erste anwser @ johlo – icarbajo

+0

Ich habe die Antwort, "sdaemon -s quit" funktioniert, aber wir müssen time.Sleep() warten, um das anmutige Herunterfahren zu bekommen. Ich muss das ändern. – icarbajo

+1

@icvallejo Sie möchten wahrscheinlich einen 'Ticker' verwenden, anstatt zu schlafen, siehe https://gobyexample.com/tickers. Sie können den Ticker stoppen, wenn das Signal SIGQUIT kommt. – johlo

Verwandte Themen