Compare commits
2 Commits
1e9f95295d
...
fb4f0c5a69
Author | SHA1 | Date |
---|---|---|
AJ ONeal | fb4f0c5a69 | |
AJ ONeal | ae809d5d5e |
|
@ -1,6 +1,4 @@
|
||||||
installer
|
/cmd/watchdog/installer/static
|
||||||
watchdog.service
|
|
||||||
/cmd/install/static
|
|
||||||
/watchdog
|
/watchdog
|
||||||
/cmd/watchdog/watchdog
|
/cmd/watchdog/watchdog
|
||||||
xversion.go
|
xversion.go
|
||||||
|
|
|
@ -1,23 +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 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()
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import "log"
|
|
||||||
|
|
||||||
func install() {
|
|
||||||
log.Fatal("not yet implemented")
|
|
||||||
}
|
|
|
@ -1,60 +0,0 @@
|
||||||
// +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)
|
|
||||||
}
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
<?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,18 +1,24 @@
|
||||||
# Pre-req
|
# Pre-req
|
||||||
# sudo adduser {{ .Exec }} --home /opt/{{ .Exec }}
|
# sudo mkdir -p {{ .Local }}/opt/{{ .Name }}/ {{ .Local }}/var/log/{{ .Name }}
|
||||||
# sudo mkdir -p /opt/{{ .Exec }}/ /var/log/{{ .Exec }}
|
{{ if not .Local -}}
|
||||||
# sudo chown -R {{ .Exec }}:{{ .Exec }} /opt/{{ .Exec }}/ /var/log/{{ .Exec }}
|
{{ if .User -}}
|
||||||
|
# sudo adduser {{ .User }} --home /opt/{{ .Name }}
|
||||||
|
# sudo chown -R {{ .User }}:{{ .Group }} /opt/{{ .Name }}/ /var/log/{{ .Name }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
# Post-install
|
# Post-install
|
||||||
# sudo systemctl daemon-reload
|
# sudo systemctl {{ if .Local -}} --user {{- end }} daemon-reload
|
||||||
# sudo systemctl restart {{ .Exec }}.service
|
# sudo systemctl {{ if .Local -}} --user {{- end }} restart {{ .Name }}.service
|
||||||
# sudo journalctl -xefu {{ .Exec }}
|
# sudo journalctl {{ if .Local -}} --user {{- end }} -xefu {{ .Name }}
|
||||||
|
|
||||||
[Unit]
|
[Unit]
|
||||||
Description={{ .Name }} - {{ .Desc }}
|
Description={{ .Title }} - {{ .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)
|
||||||
|
@ -28,8 +34,8 @@ User={{ .User }}
|
||||||
Group={{ .Group }}
|
Group={{ .Group }}
|
||||||
|
|
||||||
{{ end -}}
|
{{ end -}}
|
||||||
WorkingDirectory=/opt/{{ .Exec }}
|
WorkingDirectory={{ .Local }}/opt/{{ .Name }}
|
||||||
ExecStart=/opt/{{ .Exec }}/{{ .Exec }} {{ .Args }}
|
ExecStart={{if .Interpreter }}{{ .Interpreter }} {{ end }}{{ .Local }}/opt/{{ .Name }}/{{ .Name }} {{ .Args }}
|
||||||
ExecReload=/bin/kill -USR1 $MAINPID
|
ExecReload=/bin/kill -USR1 $MAINPID
|
||||||
|
|
||||||
{{if .Production -}}
|
{{if .Production -}}
|
||||||
|
@ -49,14 +55,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/{{ .Exec }} because we want a place for the database
|
# ... except /opt/{{ .Name }} because we want a place for the database
|
||||||
# and /var/log/{{ .Exec }} because we want a place where logs can go.
|
# and /var/log/{{ .Name }} 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/{{ .Exec }} /var/log/{{ .Exec }}
|
ReadWriteDirectories=/opt/{{ .Name }} /var/log/{{ .Name }}
|
||||||
|
|
||||||
# Note: in v231 and above ReadWritePaths has been renamed to ReadWriteDirectories
|
# Note: in v231 and above ReadWritePaths has been renamed to ReadWriteDirectories
|
||||||
; ReadWritePaths=/opt/{{ .Exec }} /var/log/{{ .Exec }}
|
; ReadWritePaths=/opt/{{ .Name }} /var/log/{{ .Name }}
|
||||||
|
|
||||||
{{ end -}}
|
{{ end -}}
|
||||||
{{if .PrivilegedPorts -}}
|
{{if .PrivilegedPorts -}}
|
||||||
|
@ -75,4 +81,8 @@ 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 @@
|
||||||
|
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)
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
//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
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
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
|
||||||
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
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 +1,7 @@
|
||||||
package main
|
package installer
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
"fmt"
|
||||||
//"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() {
|
func install(c *Config) error {
|
||||||
//token := windows.Token(0)
|
//token := windows.Token(0)
|
||||||
log.Fatal("not yet implemented")
|
return fmt.Errorf("not yet implemented")
|
||||||
}
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
// +build !windows,!linux,!darwin
|
||||||
|
|
||||||
|
package installer
|
||||||
|
|
||||||
|
func install(c *Config) error {
|
||||||
|
return nil, nil
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
# 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
|
|
@ -0,0 +1,15 @@
|
||||||
|
// +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
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
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"
|
||||||
|
|
||||||
watchdog "git.rootprojects.org/root/watchdog.go"
|
"git.rootprojects.org/root/watchdog.go"
|
||||||
)
|
)
|
||||||
|
|
||||||
var GitRev, GitVersion, GitTimestamp string
|
var GitRev, GitVersion, GitTimestamp string
|
||||||
|
@ -21,6 +21,7 @@ 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"):
|
||||||
|
@ -31,6 +32,13 @@ 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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"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