WIP generates osx file as well
This commit is contained in:
parent
1e9f95295d
commit
ae809d5d5e
|
@ -1,6 +1,4 @@
|
|||
installer
|
||||
watchdog.service
|
||||
/cmd/install/static
|
||||
/cmd/watchdog/installer/static
|
||||
/watchdog
|
||||
/cmd/watchdog/watchdog
|
||||
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>{{ .Exec }}</string>
|
||||
{{- if .Argv }}
|
||||
{{- range $arg := .Argv }}
|
||||
<string>{{ $arg }}</string>
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
</array>
|
||||
<key>EnvironmentVariables</key>
|
||||
{{- if .Envs }}
|
||||
<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
|
||||
# sudo adduser {{ .Exec }} --home /opt/{{ .Exec }}
|
||||
# sudo mkdir -p /opt/{{ .Exec }}/ /var/log/{{ .Exec }}
|
||||
# sudo chown -R {{ .Exec }}:{{ .Exec }} /opt/{{ .Exec }}/ /var/log/{{ .Exec }}
|
||||
# sudo mkdir -p {{ .Local }}/opt/{{ .Name }}/ {{ .Local }}/var/log/{{ .Name }}
|
||||
{{ if not .Local -}}
|
||||
{{ if .User -}}
|
||||
# sudo adduser {{ .User }} --home /opt/{{ .Name }}
|
||||
# sudo chown -R {{ .User }}:{{ .Group }} /opt/{{ .Name }}/ /var/log/{{ .Name }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
# Post-install
|
||||
# sudo systemctl daemon-reload
|
||||
# sudo systemctl restart {{ .Exec }}.service
|
||||
# sudo journalctl -xefu {{ .Exec }}
|
||||
# sudo systemctl {{ if .Local -}} --user {{- end }} daemon-reload
|
||||
# sudo systemctl {{ if .Local -}} --user {{- end }} restart {{ .Name }}.service
|
||||
# sudo journalctl {{ if .Local -}} --user {{- end }} -xefu {{ .Name }}
|
||||
|
||||
[Unit]
|
||||
Description={{ .Name }} - {{ .Desc }}
|
||||
Description={{ .Title }} - {{ .Desc }}
|
||||
Documentation={{ .URL }}
|
||||
{{ if not .Local -}}
|
||||
After=network-online.target
|
||||
Wants=network-online.target systemd-networkd-wait-online.service
|
||||
{{- end }}
|
||||
|
||||
[Service]
|
||||
# Restart on crash (bad signal), but not on 'clean' failure (error exit code)
|
||||
|
@ -28,8 +34,8 @@ User={{ .User }}
|
|||
Group={{ .Group }}
|
||||
|
||||
{{ end -}}
|
||||
WorkingDirectory=/opt/{{ .Exec }}
|
||||
ExecStart=/opt/{{ .Exec }}/{{ .Exec }} {{ .Args }}
|
||||
WorkingDirectory={{ .Local }}/opt/{{ .Name }}
|
||||
ExecStart={{if .Interpreter }}{{ .Interpreter }} {{ end }}{{ .Local }}/opt/{{ .Name }}/{{ .Name }} {{ .Args }}
|
||||
ExecReload=/bin/kill -USR1 $MAINPID
|
||||
|
||||
{{if .Production -}}
|
||||
|
@ -49,14 +55,14 @@ PrivateDevices=true
|
|||
ProtectHome=true
|
||||
# Make /usr, /boot, /etc and possibly some more folders read-only.
|
||||
ProtectSystem=full
|
||||
# ... except /opt/{{ .Exec }} because we want a place for the database
|
||||
# and /var/log/{{ .Exec }} because we want a place where logs can go.
|
||||
# ... except /opt/{{ .Name }} because we want a place for the database
|
||||
# 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.
|
||||
# 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
|
||||
; ReadWritePaths=/opt/{{ .Exec }} /var/log/{{ .Exec }}
|
||||
; ReadWritePaths=/opt/{{ .Name }} /var/log/{{ .Name }}
|
||||
|
||||
{{ end -}}
|
||||
{{if .PrivilegedPorts -}}
|
||||
|
@ -75,4 +81,8 @@ NoNewPrivileges=true
|
|||
|
||||
{{ end -}}
|
||||
[Install]
|
||||
{{ if not .Local -}}
|
||||
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,63 @@
|
|||
//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
|
||||
}
|
||||
|
||||
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 (
|
||||
"log"
|
||||
"fmt"
|
||||
//"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://www.reddit.com/r/golang/comments/53dthc/way_to_detect_if_the_programs_running_with/
|
||||
// https://play.golang.org/p/bBtRZrk4_p
|
||||
func install() {
|
||||
func install(c *Config) error {
|
||||
//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"
|
||||
"strings"
|
||||
|
||||
watchdog "git.rootprojects.org/root/watchdog.go"
|
||||
"git.rootprojects.org/root/watchdog.go"
|
||||
)
|
||||
|
||||
var GitRev, GitVersion, GitTimestamp string
|
||||
|
@ -31,6 +31,13 @@ func main() {
|
|||
case strings.HasSuffix(os.Args[i], "help"):
|
||||
usage()
|
||||
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