Compare commits
No commits in common. "fb4f0c5a69924c74954888d14dc3d71ab755001e" and "1e9f95295d82441d71bcd391cf738ed7f3b80b47" have entirely different histories.
fb4f0c5a69
...
1e9f95295d
|
@ -1,4 +1,6 @@
|
||||||
/cmd/watchdog/installer/static
|
installer
|
||||||
|
watchdog.service
|
||||||
|
/cmd/install/static
|
||||||
/watchdog
|
/watchdog
|
||||||
/cmd/watchdog/watchdog
|
/cmd/watchdog/watchdog
|
||||||
xversion.go
|
xversion.go
|
||||||
|
|
|
@ -1,24 +1,18 @@
|
||||||
# Pre-req
|
# Pre-req
|
||||||
# sudo mkdir -p {{ .Local }}/opt/{{ .Name }}/ {{ .Local }}/var/log/{{ .Name }}
|
# sudo adduser {{ .Exec }} --home /opt/{{ .Exec }}
|
||||||
{{ if not .Local -}}
|
# sudo mkdir -p /opt/{{ .Exec }}/ /var/log/{{ .Exec }}
|
||||||
{{ if .User -}}
|
# sudo chown -R {{ .Exec }}:{{ .Exec }} /opt/{{ .Exec }}/ /var/log/{{ .Exec }}
|
||||||
# sudo adduser {{ .User }} --home /opt/{{ .Name }}
|
|
||||||
# sudo chown -R {{ .User }}:{{ .Group }} /opt/{{ .Name }}/ /var/log/{{ .Name }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
# Post-install
|
# Post-install
|
||||||
# sudo systemctl {{ if .Local -}} --user {{- end }} daemon-reload
|
# sudo systemctl daemon-reload
|
||||||
# sudo systemctl {{ if .Local -}} --user {{- end }} restart {{ .Name }}.service
|
# sudo systemctl restart {{ .Exec }}.service
|
||||||
# sudo journalctl {{ if .Local -}} --user {{- end }} -xefu {{ .Name }}
|
# sudo journalctl -xefu {{ .Exec }}
|
||||||
|
|
||||||
[Unit]
|
[Unit]
|
||||||
Description={{ .Title }} - {{ .Desc }}
|
Description={{ .Name }} - {{ .Desc }}
|
||||||
Documentation={{ .URL }}
|
Documentation={{ .URL }}
|
||||||
{{ if not .Local -}}
|
|
||||||
After=network-online.target
|
After=network-online.target
|
||||||
Wants=network-online.target systemd-networkd-wait-online.service
|
Wants=network-online.target systemd-networkd-wait-online.service
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
# Restart on crash (bad signal), but not on 'clean' failure (error exit code)
|
# Restart on crash (bad signal), but not on 'clean' failure (error exit code)
|
||||||
|
@ -34,8 +28,8 @@ User={{ .User }}
|
||||||
Group={{ .Group }}
|
Group={{ .Group }}
|
||||||
|
|
||||||
{{ end -}}
|
{{ end -}}
|
||||||
WorkingDirectory={{ .Local }}/opt/{{ .Name }}
|
WorkingDirectory=/opt/{{ .Exec }}
|
||||||
ExecStart={{if .Interpreter }}{{ .Interpreter }} {{ end }}{{ .Local }}/opt/{{ .Name }}/{{ .Name }} {{ .Args }}
|
ExecStart=/opt/{{ .Exec }}/{{ .Exec }} {{ .Args }}
|
||||||
ExecReload=/bin/kill -USR1 $MAINPID
|
ExecReload=/bin/kill -USR1 $MAINPID
|
||||||
|
|
||||||
{{if .Production -}}
|
{{if .Production -}}
|
||||||
|
@ -55,14 +49,14 @@ PrivateDevices=true
|
||||||
ProtectHome=true
|
ProtectHome=true
|
||||||
# Make /usr, /boot, /etc and possibly some more folders read-only.
|
# Make /usr, /boot, /etc and possibly some more folders read-only.
|
||||||
ProtectSystem=full
|
ProtectSystem=full
|
||||||
# ... except /opt/{{ .Name }} because we want a place for the database
|
# ... except /opt/{{ .Exec }} because we want a place for the database
|
||||||
# and /var/log/{{ .Name }} because we want a place where logs can go.
|
# and /var/log/{{ .Exec }} because we want a place where logs can go.
|
||||||
# This merely retains r/w access rights, it does not add any new.
|
# This merely retains r/w access rights, it does not add any new.
|
||||||
# Must still be writable on the host!
|
# Must still be writable on the host!
|
||||||
ReadWriteDirectories=/opt/{{ .Name }} /var/log/{{ .Name }}
|
ReadWriteDirectories=/opt/{{ .Exec }} /var/log/{{ .Exec }}
|
||||||
|
|
||||||
# Note: in v231 and above ReadWritePaths has been renamed to ReadWriteDirectories
|
# Note: in v231 and above ReadWritePaths has been renamed to ReadWriteDirectories
|
||||||
; ReadWritePaths=/opt/{{ .Name }} /var/log/{{ .Name }}
|
; ReadWritePaths=/opt/{{ .Exec }} /var/log/{{ .Exec }}
|
||||||
|
|
||||||
{{ end -}}
|
{{ end -}}
|
||||||
{{if .PrivilegedPorts -}}
|
{{if .PrivilegedPorts -}}
|
||||||
|
@ -81,8 +75,4 @@ NoNewPrivileges=true
|
||||||
|
|
||||||
{{ end -}}
|
{{ end -}}
|
||||||
[Install]
|
[Install]
|
||||||
{{ if not .Local -}}
|
|
||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
{{- else -}}
|
|
||||||
WantedBy=default.target
|
|
||||||
{{- end }}
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
//go:generate go run -mod=vendor github.com/UnnoTed/fileb0x b0x.toml
|
||||||
|
|
||||||
|
// I'm prototyping this out to be useful for more than just watchdog
|
||||||
|
// hence there are a few unnecessary things for the sake of the trying it out
|
||||||
|
package main
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Desc string `json:"desc"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
Exec string `json:"exec"`
|
||||||
|
Args string `json:"args"`
|
||||||
|
User string `json:"user"`
|
||||||
|
Group string `json:"group"`
|
||||||
|
Production bool `json:"production"`
|
||||||
|
PrivilegedPorts bool `json:"privileged_ports"`
|
||||||
|
MultiuserProtection bool `json:"multiuser_protection"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
|
||||||
|
install()
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "log"
|
||||||
|
|
||||||
|
func install() {
|
||||||
|
log.Fatal("not yet implemented")
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
// +build !windows !darwin
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"text/template"
|
||||||
|
|
||||||
|
"git.rootprojects.org/root/watchdog.go/cmd/install/static"
|
||||||
|
)
|
||||||
|
|
||||||
|
func install() {
|
||||||
|
b, err := static.ReadFile("dist/etc/systemd/system/watchdog.service.tmpl")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s := string(b)
|
||||||
|
|
||||||
|
j, err := static.ReadFile("dist/etc/systemd/system/watchdog.service.json")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//conf := map[string]string{}
|
||||||
|
conf := &Config{}
|
||||||
|
err = json.Unmarshal(j, &conf)
|
||||||
|
if nil != err {
|
||||||
|
log.Fatal(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if "" == conf.Group {
|
||||||
|
conf.Group = conf.User
|
||||||
|
}
|
||||||
|
|
||||||
|
serviceFile := conf.Exec + ".service"
|
||||||
|
|
||||||
|
rw := &bytes.Buffer{}
|
||||||
|
// not sure what the template name does, but whatever
|
||||||
|
tmpl, err := template.New("service").Parse(s)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = tmpl.Execute(rw, conf)
|
||||||
|
if nil != err {
|
||||||
|
log.Fatal(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ioutil.WriteFile(serviceFile, rw.Bytes(), 0644); err != nil {
|
||||||
|
log.Fatalf("ioutil.WriteFile error: %v", err)
|
||||||
|
}
|
||||||
|
fmt.Printf("Wrote %q\n", serviceFile)
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
package installer
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"log"
|
||||||
//"golang.org/x/sys/windows"
|
//"golang.org/x/sys/windows"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ import (
|
||||||
// https://stackoverflow.com/questions/27366298/check-if-application-is-running-as-administrator-in-golang
|
// https://stackoverflow.com/questions/27366298/check-if-application-is-running-as-administrator-in-golang
|
||||||
// https://www.reddit.com/r/golang/comments/53dthc/way_to_detect_if_the_programs_running_with/
|
// https://www.reddit.com/r/golang/comments/53dthc/way_to_detect_if_the_programs_running_with/
|
||||||
// https://play.golang.org/p/bBtRZrk4_p
|
// https://play.golang.org/p/bBtRZrk4_p
|
||||||
func install(c *Config) error {
|
func install() {
|
||||||
//token := windows.Token(0)
|
//token := windows.Token(0)
|
||||||
return fmt.Errorf("not yet implemented")
|
log.Fatal("not yet implemented")
|
||||||
}
|
}
|
|
@ -1,63 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"git.rootprojects.org/root/watchdog.go/cmd/watchdog/installer"
|
|
||||||
)
|
|
||||||
|
|
||||||
func install(binpath string, args []string) {
|
|
||||||
system := true
|
|
||||||
production := false
|
|
||||||
config := "./config.json"
|
|
||||||
for i := range os.Args {
|
|
||||||
switch {
|
|
||||||
case strings.HasSuffix(os.Args[i], "userspace"):
|
|
||||||
system = false
|
|
||||||
case strings.HasSuffix(os.Args[i], "production"):
|
|
||||||
fmt.Println("Warning: production options don't work on all systems. If you have trouble, drop this first.")
|
|
||||||
production = false
|
|
||||||
case "-c" == os.Args[i]:
|
|
||||||
if len(os.Args) <= i+1 {
|
|
||||||
fmt.Println("-c requires a string path to the config file")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
config = os.Args[i+1]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
j, err := static.ReadFile("dist/etc/systemd/system/watchdog.service.json")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//conf := map[string]string{}
|
|
||||||
conf := &Config{}
|
|
||||||
err = json.Unmarshal(j, &conf)
|
|
||||||
if nil != err {
|
|
||||||
log.Fatal(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
err := installer.Install(&installer.Config{
|
|
||||||
Title: "Watchdog",
|
|
||||||
Desc: "Get notified when sites go down",
|
|
||||||
URL: "https://git.rootprojects.org/root/watchdog.go",
|
|
||||||
Name: "watchdog",
|
|
||||||
Exec: "watchdog",
|
|
||||||
Local: "",
|
|
||||||
System: system,
|
|
||||||
Restart: true,
|
|
||||||
Argv: []string{"-c", config},
|
|
||||||
PrivilegedPorts: false,
|
|
||||||
MultiuserProtection: false,
|
|
||||||
Production: production,
|
|
||||||
})
|
|
||||||
if nil != err {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,71 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
||||||
<plist version="1.0">
|
|
||||||
<dict>
|
|
||||||
<key>Label</key>
|
|
||||||
<string>{{ .Title }}</string>
|
|
||||||
<key>ProgramArguments</key>
|
|
||||||
<array>
|
|
||||||
{{- if .Interpreter }}
|
|
||||||
<string>{{ .Interpreter }}</string>
|
|
||||||
{{- end }}
|
|
||||||
<string>{{ .Local }}/opt/{{ .Name }}/{{ .Exec }}</string>
|
|
||||||
{{- if .Argv }}
|
|
||||||
{{- range $arg := .Argv }}
|
|
||||||
<string>{{ $arg }}</string>
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
</array>
|
|
||||||
{{- if .Envs }}
|
|
||||||
<key>EnvironmentVariables</key>
|
|
||||||
<dict>
|
|
||||||
{{- range $key, $value := .Envs }}
|
|
||||||
<key>{{ $key }}</key>
|
|
||||||
<string>{{ $value }}</string>
|
|
||||||
{{- end }}
|
|
||||||
</dict>
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{if .User -}}
|
|
||||||
<key>UserName</key>
|
|
||||||
<string>{{ .User }}</string>
|
|
||||||
<key>GroupName</key>
|
|
||||||
<string>{{ .Group }}</string>
|
|
||||||
<key>InitGroups</key>
|
|
||||||
<true/>
|
|
||||||
|
|
||||||
{{end -}}
|
|
||||||
<key>RunAtLoad</key>
|
|
||||||
<true/>
|
|
||||||
{{ if .Restart -}}
|
|
||||||
<key>KeepAlive</key>
|
|
||||||
<true/>
|
|
||||||
<!--dict>
|
|
||||||
<key>Crashed</key>
|
|
||||||
<true/>
|
|
||||||
<key>NetworkState</key>
|
|
||||||
<true/>
|
|
||||||
<key>SuccessfulExit</key>
|
|
||||||
<false/>
|
|
||||||
</dict-->
|
|
||||||
|
|
||||||
{{ end -}}
|
|
||||||
{{ if .Production -}}
|
|
||||||
<key>SoftResourceLimits</key>
|
|
||||||
<dict>
|
|
||||||
<key>NumberOfFiles</key>
|
|
||||||
<integer>8192</integer>
|
|
||||||
</dict>
|
|
||||||
<key>HardResourceLimits</key>
|
|
||||||
<dict/>
|
|
||||||
|
|
||||||
{{ end -}}
|
|
||||||
<key>WorkingDirectory</key>
|
|
||||||
<string>{{ .Local }}/opt/{{ .Name }}</string>
|
|
||||||
|
|
||||||
<key>StandardErrorPath</key>
|
|
||||||
<string>{{ .LogDir }}/{{ .Name }}.log</string>
|
|
||||||
<key>StandardOutPath</key>
|
|
||||||
<string>{{ .LogDir }}/{{ .Name }}.log</string>
|
|
||||||
</dict>
|
|
||||||
</plist>
|
|
|
@ -1,23 +0,0 @@
|
||||||
package installer
|
|
||||||
|
|
||||||
// "A little copying is better than a little dependency"
|
|
||||||
// These are here so that we don't need a dependency on http.FileSystem and http.File
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Same as http.FileSystem
|
|
||||||
type FileSystem interface {
|
|
||||||
Open(name string) (File, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Same as http.File
|
|
||||||
type File interface {
|
|
||||||
io.Closer
|
|
||||||
io.Reader
|
|
||||||
io.Seeker
|
|
||||||
Readdir(count int) ([]os.FileInfo, error)
|
|
||||||
Stat() (os.FileInfo, error)
|
|
||||||
}
|
|
|
@ -1,68 +0,0 @@
|
||||||
//go:generate go run -mod=vendor github.com/UnnoTed/fileb0x b0x.toml
|
|
||||||
|
|
||||||
// I'm prototyping this out to be useful for more than just watchdog
|
|
||||||
// hence there are a few unnecessary things for the sake of the trying it out
|
|
||||||
package installer
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Config struct {
|
|
||||||
Title string `json:"title"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
Desc string `json:"desc"`
|
|
||||||
URL string `json:"url"`
|
|
||||||
Interpreter string `json:"interpreter"` // i.e. node, python
|
|
||||||
Exec string `json:"exec"`
|
|
||||||
Argv []string `json:"argv"`
|
|
||||||
Args string `json:"-"`
|
|
||||||
Envs map[string]string `json:"envs"`
|
|
||||||
User string `json:"user"`
|
|
||||||
Group string `json:"group"`
|
|
||||||
home string `json:"-"`
|
|
||||||
Local string `json:"local"`
|
|
||||||
LogDir string `json:"-"`
|
|
||||||
System bool `json:"system"`
|
|
||||||
Restart bool `json:"restart"`
|
|
||||||
Production bool `json:"production"`
|
|
||||||
PrivilegedPorts bool `json:"privileged_ports"`
|
|
||||||
MultiuserProtection bool `json:"multiuser_protection"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func Install(c *Config) error {
|
|
||||||
if "" == c.Exec {
|
|
||||||
c.Exec = c.Name
|
|
||||||
}
|
|
||||||
c.Args = strings.Join(c.Argv, " ")
|
|
||||||
|
|
||||||
// TODO handle non-system installs
|
|
||||||
// * ~/.local/opt/watchdog/watchdog
|
|
||||||
// * ~/.local/share/watchdog/var/log/
|
|
||||||
// * ~/.config/watchdog/watchdog.json
|
|
||||||
if !c.System {
|
|
||||||
home, err := os.UserHomeDir()
|
|
||||||
if nil != err {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
c.home = home
|
|
||||||
c.Local = filepath.Join(c.home, ".local")
|
|
||||||
c.LogDir = filepath.Join(c.home, ".local", "share", c.Name, "var", "log")
|
|
||||||
} else {
|
|
||||||
c.LogDir = "/var/log/" + c.Name
|
|
||||||
}
|
|
||||||
|
|
||||||
err := install(c)
|
|
||||||
if nil != err {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = os.MkdirAll(c.LogDir, 0750)
|
|
||||||
if nil != err {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
|
@ -1,64 +0,0 @@
|
||||||
package installer
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
"text/template"
|
|
||||||
|
|
||||||
"git.rootprojects.org/root/watchdog.go/cmd/watchdog/installer/static"
|
|
||||||
)
|
|
||||||
|
|
||||||
func install(c *Config) error {
|
|
||||||
// Darwin-specific config options
|
|
||||||
if c.PrivilegedPorts {
|
|
||||||
if !c.System {
|
|
||||||
return fmt.Errorf("You must use root-owned LaunchDaemons (not user-owned LaunchAgents) to use priveleged ports on OS X")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
plistDir := "/Library/LaunchDaemons/"
|
|
||||||
if !c.System {
|
|
||||||
plistDir = filepath.Join(c.home, "Library/LaunchAgents")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check paths first
|
|
||||||
err := os.MkdirAll(filepath.Dir(plistDir), 0750)
|
|
||||||
if nil != err {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create service file from template
|
|
||||||
b, err := static.ReadFile("dist/Library/LaunchDaemons/_rdns_.plist.tmpl")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
s := string(b)
|
|
||||||
rw := &bytes.Buffer{}
|
|
||||||
// not sure what the template name does, but whatever
|
|
||||||
tmpl, err := template.New("service").Parse(s)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = tmpl.Execute(rw, c)
|
|
||||||
if nil != err {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write the file out
|
|
||||||
// TODO rdns
|
|
||||||
plistName := c.Name + ".plist"
|
|
||||||
plistPath := filepath.Join(plistDir, plistName)
|
|
||||||
if err := ioutil.WriteFile(plistPath, rw.Bytes(), 0644); err != nil {
|
|
||||||
fmt.Println("Use 'sudo' to install as a privileged system service.")
|
|
||||||
fmt.Println("Use '--userspace' to install as an user service.")
|
|
||||||
return fmt.Errorf("ioutil.WriteFile error: %v", err)
|
|
||||||
}
|
|
||||||
fmt.Printf("Installed. To start '%s' run the following:\n", c.Name)
|
|
||||||
// TODO template config file
|
|
||||||
fmt.Printf("\tlaunchctl load -w %s\n", strings.Replace(plistPath, c.home, "~", 1))
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
|
@ -1,65 +0,0 @@
|
||||||
package installer
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"text/template"
|
|
||||||
|
|
||||||
"git.rootprojects.org/root/watchdog.go/cmd/watchdog/installer/static"
|
|
||||||
)
|
|
||||||
|
|
||||||
func install(c *Config) error {
|
|
||||||
// Linux-specific config options
|
|
||||||
if c.System {
|
|
||||||
if "" == c.User {
|
|
||||||
c.User = "root"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if "" == c.Group {
|
|
||||||
c.Group = c.User
|
|
||||||
}
|
|
||||||
serviceDir := "/etc/systemd/system/"
|
|
||||||
|
|
||||||
// Check paths first
|
|
||||||
serviceName := c.Name + ".service"
|
|
||||||
if !c.System {
|
|
||||||
// Not sure which of these it's supposed to be...
|
|
||||||
// * ~/.local/share/systemd/user/watchdog.service
|
|
||||||
// * ~/.config/systemd/user/watchdog.service
|
|
||||||
// https://wiki.archlinux.org/index.php/Systemd/User
|
|
||||||
serviceDir = filepath.Join(c.home, ".local/share/systemd/user")
|
|
||||||
}
|
|
||||||
err = os.MkdirAll(filepath.Dir(serviceDir), 0750)
|
|
||||||
if nil != err {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create service file from template
|
|
||||||
b, err := static.ReadFile("dist/etc/systemd/system/_name_.service.tmpl")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
s := string(b)
|
|
||||||
rw := &bytes.Buffer{}
|
|
||||||
// not sure what the template name does, but whatever
|
|
||||||
tmpl, err := template.New("service").Parse(s)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = tmpl.Execute(rw, c)
|
|
||||||
if nil != err {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write the file out
|
|
||||||
servicePath := filepath.Join(serviceDir, serviceName)
|
|
||||||
if err := ioutil.WriteFile(servicePath, rw.Bytes(), 0644); err != nil {
|
|
||||||
return fmt.Errorf("ioutil.WriteFile error: %v", err)
|
|
||||||
}
|
|
||||||
fmt.Printf("Wrote %q\n", servicePath)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
// +build !windows,!linux,!darwin
|
|
||||||
|
|
||||||
package installer
|
|
||||||
|
|
||||||
func install(c *Config) error {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
# Pre-req
|
|
||||||
# sudo adduser watchdog --home /opt/watchdog
|
|
||||||
# sudo mkdir -p /opt/watchdog/ /var/log/watchdog
|
|
||||||
# sudo chown -R watchdog:watchdog /opt/watchdog/ /var/log/watchdog
|
|
||||||
|
|
||||||
[Unit]
|
|
||||||
Description=Watchdog - Get notified when sites go down
|
|
||||||
Documentation=https://git.rootprojects.org/root/watchdog.go
|
|
||||||
After=network-online.target
|
|
||||||
Wants=network-online.target systemd-networkd-wait-online.service
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
# Restart on crash (bad signal), but not on 'clean' failure (error exit code)
|
|
||||||
# Allow up to 3 restarts within 10 seconds
|
|
||||||
# (it's unlikely that a user or properly-running script will do this)
|
|
||||||
Restart=on-abnormal
|
|
||||||
StartLimitInterval=10
|
|
||||||
StartLimitBurst=3
|
|
||||||
|
|
||||||
# User and group the process will run as
|
|
||||||
User=root
|
|
||||||
Group=root
|
|
||||||
|
|
||||||
WorkingDirectory=/opt/watchdog
|
|
||||||
ExecStart=/opt/watchdog -c ./config.json
|
|
||||||
ExecReload=/bin/kill -USR1 $MAINPID
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
|
@ -1,15 +0,0 @@
|
||||||
// +build !windows
|
|
||||||
|
|
||||||
package installer
|
|
||||||
|
|
||||||
import "os/user"
|
|
||||||
|
|
||||||
func IsAdmin() bool {
|
|
||||||
u, err := user.Current()
|
|
||||||
if nil != err {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// not quite, but close enough for now
|
|
||||||
return "0" == u.Uid
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
package installer
|
|
||||||
|
|
||||||
import "os/user"
|
|
||||||
|
|
||||||
func IsAdmin() {
|
|
||||||
u, err := user.Current()
|
|
||||||
if nil != err {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://support.microsoft.com/en-us/help/243330/well-known-security-identifiers-in-windows-operating-systems
|
|
||||||
// not quite, but close enough for now
|
|
||||||
// BUILTIN\ADMINISTRATORS
|
|
||||||
if "S-1-5-32-544" == u.Uid || "S-1-5-32-544" == u.Gid {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
ids := u.GroupIds()
|
|
||||||
for i := range ids {
|
|
||||||
if "S-1-5-32-544" == ids[i] {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
|
@ -11,7 +11,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.rootprojects.org/root/watchdog.go"
|
watchdog "git.rootprojects.org/root/watchdog.go"
|
||||||
)
|
)
|
||||||
|
|
||||||
var GitRev, GitVersion, GitTimestamp string
|
var GitRev, GitVersion, GitTimestamp string
|
||||||
|
@ -21,7 +21,6 @@ func usage() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
fmt.Println("Watchdog " + GitVersion)
|
|
||||||
for i := range os.Args {
|
for i := range os.Args {
|
||||||
switch {
|
switch {
|
||||||
case strings.HasSuffix(os.Args[i], "version"):
|
case strings.HasSuffix(os.Args[i], "version"):
|
||||||
|
@ -32,13 +31,6 @@ func main() {
|
||||||
case strings.HasSuffix(os.Args[i], "help"):
|
case strings.HasSuffix(os.Args[i], "help"):
|
||||||
usage()
|
usage()
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
case os.Args[i] == "install":
|
|
||||||
args := []string{}
|
|
||||||
if len(os.Args) > i+1 {
|
|
||||||
args = os.Args[i+1:]
|
|
||||||
}
|
|
||||||
install(os.Args[0], args)
|
|
||||||
os.Exit(0)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
{
|
|
||||||
"name": "Watchdog",
|
|
||||||
"desc": "Get notified when sites go down",
|
|
||||||
"url": "https://git.rootprojects.org/root/watchdog.go",
|
|
||||||
"exec": "watchdog",
|
|
||||||
"args": "-c ./config.json",
|
|
||||||
"user": "root",
|
|
||||||
"privileged_ports": false,
|
|
||||||
"multiuser_protection": false
|
|
||||||
}
|
|
Loading…
Reference in New Issue