@marcel91200 / caddy Mirror · read-only / commits / 4df56c77
Fork 0

Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS

Mirrored from https://github.com/Slazee/caddy.git

Synced Nov 14, 05:15 UTC

cmd: Add pidfile support (closes #3235)

Matthew Holt committed May 13, 2020 at 11:28 UTC 4df56c77e380cdfec5e23862f7faa8bd843022e6
4 files changed +38 -9
admin.go
+16 -7
@@ -21,6 +21,7 @@ import (
21 "expvar"
22 "fmt"
23 "io"
24 + "io/ioutil"
25 "net"
26 "net/http"
27 "net/http/pprof"
@@ -546,13 +547,6 @@ func handleUnload(w http.ResponseWriter, r *http.Request) error {
547 Err: fmt.Errorf("method not allowed"),
548 }
549 }
549 - currentCfgMu.RLock()
550 - hasCfg := currentCfg != nil
551 - currentCfgMu.RUnlock()
552 - if !hasCfg {
553 - Log().Named("admin.api").Info("nothing to unload")
554 - return nil
555 - }
550 Log().Named("admin.api").Info("unloading")
551 if err := stopAndCleanup(); err != nil {
552 Log().Named("admin.api").Error("error unloading", zap.Error(err))
@@ -801,12 +795,27 @@ var (
795 }
796 )
797
798 +// PIDFile writes a pidfile to the file at filename. It
799 +// will get deleted before the process gracefully exits.
800 +func PIDFile(filename string) error {
801 + pid := []byte(strconv.Itoa(os.Getpid()) + "\n")
802 + err := ioutil.WriteFile(filename, pid, 0644)
803 + if err != nil {
804 + return err
805 + }
806 + pidfile = filename
807 + return nil
808 +}
809 +
810 // idRegexp is used to match ID fields and their associated values
811 // in the config. It also matches adjacent commas so that syntax
812 // can be preserved no matter where in the object the field appears.
813 // It supports string and most numeric values.
814 var idRegexp = regexp.MustCompile(`(?m),?\s*"` + idKey + `"\s*:\s*(-?[0-9]+(\.[0-9]+)?|(?U)".*")\s*,?`)
815
816 +// pidfile is the name of the pidfile, if any.
817 +var pidfile string
818 +
819 const (
820 rawConfigKey = "config"
821 idKey = "@id"
caddy.go
+3
@@ -470,6 +470,9 @@ func stopAndCleanup() error {
470 return err
471 }
472 certmagic.CleanUpOwnLocks()
473 + if pidfile != "" {
474 + os.Remove(pidfile)
475 + }
476 return nil
477 }
478
cmd/commandfuncs.go
+15
@@ -41,6 +41,7 @@ import (
41 func cmdStart(fl Flags) (int, error) {
42 startCmdConfigFlag := fl.String("config")
43 startCmdConfigAdapterFlag := fl.String("adapter")
44 + startCmdPidfileFlag := fl.String("pidfile")
45 startCmdWatchFlag := fl.Bool("watch")
46
47 // open a listener to which the child process will connect when
@@ -71,6 +72,9 @@ func cmdStart(fl Flags) (int, error) {
72 if startCmdWatchFlag {
73 cmd.Args = append(cmd.Args, "--watch")
74 }
75 + if startCmdPidfileFlag != "" {
76 + cmd.Args = append(cmd.Args, "--pidfile", startCmdPidfileFlag)
77 + }
78 stdinpipe, err := cmd.StdinPipe()
79 if err != nil {
80 return caddy.ExitCodeFailedStartup,
@@ -149,6 +153,7 @@ func cmdRun(fl Flags) (int, error) {
153 runCmdResumeFlag := fl.Bool("resume")
154 runCmdPrintEnvFlag := fl.Bool("environ")
155 runCmdWatchFlag := fl.Bool("watch")
156 + runCmdPidfileFlag := fl.String("pidfile")
157 runCmdPingbackFlag := fl.String("pingback")
158
159 // if we are supposed to print the environment, do that first
@@ -225,6 +230,16 @@ func cmdRun(fl Flags) (int, error) {
230 go watchConfigFile(configFile, runCmdConfigAdapterFlag)
231 }
232
233 + // create pidfile
234 + if runCmdPidfileFlag != "" {
235 + err := caddy.PIDFile(runCmdPidfileFlag)
236 + if err != nil {
237 + caddy.Log().Error("unable to write PID file",
238 + zap.String("pidfile", runCmdPidfileFlag),
239 + zap.Error(err))
240 + }
241 + }
242 +
243 // warn if the environment does not provide enough information about the disk
244 hasXDG := os.Getenv("XDG_DATA_HOME") != "" &&
245 os.Getenv("XDG_CONFIG_HOME") != "" &&
cmd/commands.go
+4 -2
@@ -74,7 +74,7 @@ func init() {
74 RegisterCommand(Command{
75 Name: "start",
76 Func: cmdStart,
77 - Usage: "[--config <path> [--adapter <name>]] [--watch]",
77 + Usage: "[--config <path> [--adapter <name>]] [--watch] [--pidfile <file>]",
78 Short: "Starts the Caddy process in the background and then returns",
79 Long: `
80 Starts the Caddy process, optionally bootstrapped with an initial config file.
@@ -87,6 +87,7 @@ using 'caddy run' instead to keep it in the foreground.`,
87 fs := flag.NewFlagSet("start", flag.ExitOnError)
88 fs.String("config", "", "Configuration file")
89 fs.String("adapter", "", "Name of config adapter to apply")
90 + fs.String("pidfile", "", "Path of file to which to write process ID")
91 fs.Bool("watch", false, "Reload changed config file automatically")
92 return fs
93 }(),
@@ -95,7 +96,7 @@ using 'caddy run' instead to keep it in the foreground.`,
96 RegisterCommand(Command{
97 Name: "run",
98 Func: cmdRun,
98 - Usage: "[--config <path> [--adapter <name>]] [--environ] [--watch]",
99 + Usage: "[--config <path> [--adapter <name>]] [--environ] [--resume] [--watch] [--pidfile <fil>]",
100 Short: `Starts the Caddy process and blocks indefinitely`,
101 Long: `
102 Starts the Caddy process, optionally bootstrapped with an initial config file,
@@ -132,6 +133,7 @@ development environment.`,
133 fs.Bool("environ", false, "Print environment")
134 fs.Bool("resume", false, "Use saved config, if any (and prefer over --config file)")
135 fs.Bool("watch", false, "Watch config file for changes and reload it automatically")
136 + fs.String("pidfile", "", "Path of file to which to write process ID")
137 fs.String("pingback", "", "Echo confirmation bytes to this address on success")
138 return fs
139 }(),