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
}(),