daemonize

master
Carlo Strub 7 years ago
parent cb45c57c4d
commit e5b59cafef

@ -0,0 +1,28 @@
package main
import (
"os"
"strconv"
)
// See
// https://www.socketloop.com/tutorials/golang-daemonizing-a-simple-web-server-process-example
// for the process we are using to daemonize
// savePID stores a pidfile
func savePID(pidfile string, p int) error {
file, err := os.Create(pidfile)
if err != nil {
return err
}
defer file.Close()
_, err = file.WriteString(strconv.Itoa(p))
if err != nil {
return err
}
file.Sync()
return nil
}

@ -60,9 +60,6 @@ func openDB(maildir string) (db *bolt.DB, err error) {
}
return nil
})
if err != nil {
return db, err
}
return db, nil
return db, err
}

@ -1,12 +0,0 @@
package main_test
import (
. "github.com/carlostrub/sisyphus"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var _ = Describe("Filter", func() {
})

@ -1,16 +1,22 @@
package main
import (
"errors"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
"os/exec"
"os/signal"
"strconv"
"syscall"
"github.com/urfave/cli"
)
var (
// Processed is a map of e-mail IDs and the value set to true if Junk
Processed map[string]bool
// Processed is a map of e-mail IDs and the value set to true if Junk
// Processed map[string]bool
)
func main() {
@ -20,13 +26,13 @@ func main() {
panic(err)
}
var maildir []string
// Define App
app := cli.NewApp()
app.Name = "Sisyphus"
app.Usage = "Intelligent Junk and Spam Mail Handler"
app.UsageText = `Sisyphus applies artificial intelligence to filter
app.UsageText = `sisyphus [global options] command [command options]
Sisyphus applies artificial intelligence to filter
Junk mail in an unobtrusive way. Both, classification and learning
operate directly on the Maildir of a user in a fully transparent mode,
without any need for configuration or active operation.`
@ -43,6 +49,10 @@ func main() {
maildirPaths := cli.StringSlice([]string{
wd + "/Maildir",
})
var pidfile *string
pidfile = new(string)
app.Flags = []cli.Flag{
cli.StringSliceFlag{
@ -51,33 +61,88 @@ func main() {
EnvVar: "SISYPHUS_DIRS",
Usage: "Comma separated list of paths to the Maildir directories",
},
cli.StringFlag{
Name: "pidfile, p",
Value: "/tmp/sisyphus.pid",
EnvVar: "SISYPHUS_PID",
Usage: "Location of PID file",
Destination: pidfile,
},
}
app.Commands = []cli.Command{
{
Name: "run",
Aliases: []string{"u"},
Usage: "run sisyphus",
Action: func(c *cli.Context) {
log.Print("App runs..........")
// Make arrangement to remove PID file upon receiving the SIGTERM from kill command
ch := make(chan os.Signal, 1)
signal.Notify(ch, os.Interrupt, os.Kill, syscall.SIGTERM)
go func() {
signalType := <-ch
signal.Stop(ch)
log.Println("Exit command received. Exiting sisyphus...")
// this is a good place to flush everything to disk
// before terminating.
log.Println("Received signal type: ", signalType)
// remove PID file
os.Remove(*pidfile)
os.Exit(0)
}()
// var maildir []string
// if maildir == nil {
// return errors.New("no maildir selected")
// }
//
// // Load the Maildir
// mails, err := Index(maildirPaths[0])
// if err != nil {
// return cli.NewExitError(err, 66)
// }
//
// fmt.Println(mails)
//
// // Open the database
// db, err := openDB(maildirPaths[0])
// if err != nil {
// return cli.NewExitError(err, 66)
// }
// defer db.Close()
mux := http.NewServeMux()
log.Fatalln(http.ListenAndServe(":8080", mux))
},
},
{
// See
// https://www.socketloop.com/tutorials/golang-daemonizing-a-simple-web-server-process-example
// for the process we are using to daemonize
Name: "start",
Aliases: []string{"s"},
Usage: "start sisyphus daemon",
Usage: "start sisyphus daemon in the background",
Action: func(c *cli.Context) error {
if maildir == nil {
return errors.New("no maildir selected")
// check if daemon already running.
if _, err := os.Stat(*pidfile); err == nil {
return cli.NewExitError("sisyphus running or "+*pidfile+" file exists.", 69)
}
// Load the Maildir
mails, err := Index(maildirPaths[0])
cmd := exec.Command(os.Args[0], "run")
cmd.Start()
log.Printf("starting sisyphus process ID [%v]\n", cmd.Process.Pid)
log.Println("sisyphus started")
err := savePID(*pidfile, cmd.Process.Pid)
if err != nil {
return cli.NewExitError(err, 66)
return cli.NewExitError(err, 73)
}
fmt.Println(mails)
// Open the database
db, err := openDB(maildirPaths[0])
if err != nil {
return cli.NewExitError(err, 66)
}
defer db.Close()
return nil
},
},
@ -86,6 +151,44 @@ func main() {
Aliases: []string{"e"},
Usage: "stop sisyphus daemon",
Action: func(c *cli.Context) error {
_, err := os.Stat(*pidfile)
if err != nil {
return cli.NewExitError("sisyphus is not running", 64)
}
processIDRaw, err := ioutil.ReadFile(*pidfile)
if err != nil {
return cli.NewExitError("sisyphus is not running", 64)
}
processID, err := strconv.Atoi(string(processIDRaw))
if err != nil {
return cli.NewExitError("unable to read and parse process id found in "+*pidfile, 74)
}
process, err := os.FindProcess(processID)
if err != nil {
e := fmt.Sprintf("Unable to find process ID [%v] with error %v \n", processID, err)
return cli.NewExitError(e, 71)
}
// remove PID file
os.Remove(*pidfile)
log.Printf("stopping sisyphus process ID [%v]\n", processID)
// kill process and exit immediately
err = process.Kill()
if err != nil {
e := fmt.Sprintf("Unable to kill process ID [%v] with error %v \n", processID, err)
return cli.NewExitError(e, 71)
}
log.Println("sisyphus stopped")
os.Exit(0)
return nil
},
},
@ -94,6 +197,31 @@ func main() {
Aliases: []string{"r"},
Usage: "restart sisyphus daemon",
Action: func(c *cli.Context) error {
_, err := os.Stat(*pidfile)
if err != nil {
return cli.NewExitError("sisyphus is not running", 64)
}
pid, err := ioutil.ReadFile(*pidfile)
if err != nil {
return cli.NewExitError("sisyphus is not running", 64)
}
cmd := exec.Command(os.Args[0], "stop")
err = cmd.Start()
if err != nil {
return cli.NewExitError(err, 64)
}
log.Printf("stopping sisyphus process ID [%v]\n", string(pid))
cmd = exec.Command(os.Args[0], "start")
err = cmd.Start()
if err != nil {
return cli.NewExitError(err, 64)
}
log.Println("sisyphus restarted")
return nil
},
},
@ -102,14 +230,7 @@ func main() {
Aliases: []string{"i"},
Usage: "status of sisyphus",
Action: func(c *cli.Context) error {
return nil
},
},
{
Name: "describe",
Aliases: []string{"d"},
Usage: "short description of sisyphus",
Action: func(c *cli.Context) error {
log.Println("here, we should get statistics from the db, TBD...")
return nil
},
},

Loading…
Cancel
Save