├── .gitignore ├── chromium-app.run ├── static └── stylesheets │ └── main.css ├── templates ├── docker.html ├── man.html ├── command.html └── home.html ├── README.md ├── monitor.go ├── LICENSE └── web └── web.go /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | -------------------------------------------------------------------------------- /chromium-app.run: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #this is a script to start an instance of chromium with the --app flag in which the browser looks at the web page as 3 | #an app instead of a full address. allows for desktop like application building 4 | 5 | chromium --app=http://localhost:8080 6 | -------------------------------------------------------------------------------- /static/stylesheets/main.css: -------------------------------------------------------------------------------- 1 | body { 2 | /*background: green;*/ 3 | } 4 | 5 | .text-center { 6 | text-align: center; 7 | } 8 | 9 | .container { 10 | width: 900px; 11 | margin: auto; 12 | display: block; 13 | } 14 | 15 | .container.command { 16 | unicode-bidi: embed; 17 | font-family: monospace; 18 | white-space: pre; 19 | } -------------------------------------------------------------------------------- /templates/docker.html: -------------------------------------------------------------------------------- 1 | {{ define "docker"}} 2 | 3 | 4 | 5 | 6 | {{ .Title }} 7 | 8 | 9 | 10 |

11 | {{ .Data1}} 12 |

13 |

14 | {{ .Data2}} 15 |

16 |

17 | {{ .Data3}} 18 |

19 | {{end}} 20 | -------------------------------------------------------------------------------- /templates/man.html: -------------------------------------------------------------------------------- 1 | {{ define "man"}} 2 | 3 | 4 | 5 | 6 | {{ .Title }} 7 | 8 | 9 | 10 |

{{ .Title }}

11 |
12 | Type a command to receive the full manpage for the command 13 |
14 |
15 | 16 | 17 |
18 |
{{ .Body }}
19 | 20 | 21 | {{end}} 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### goMonitor 2 | Monitor Your Server from a webpage 3 | 4 | GoMonitor allows for any system command to easily be displayed in a webpage with a nicely designed web panel. 5 | The project is still in it's infacy, however soon i hope to finish the panel as well as add a secure login form. 6 | 7 | 8 | ##FAQ 9 | 1.Why don't you just take a query variable and execute it? Security Security Security. By hardcoding allowed commands 10 | it's literally impossible to run a non-supported command. 11 | 12 | ##FEATURES 13 | ls 14 | free 15 | top 16 | iostat 17 | vmstat 18 | dmesg 19 | ps 20 | Manpage Lookup 21 | ###Docker 22 | Stats 23 | PS 24 | 25 | -------------------------------------------------------------------------------- /templates/command.html: -------------------------------------------------------------------------------- 1 | {{define "command"}} 2 | 3 | 4 | 5 | 6 | {{ .Title }} 7 | 8 | 9 | 10 | 11 |

{{ .Title }}

12 | 13 | arg: 14 | 15 |
Home
16 |
17 | {{ .Body }} 18 |
19 | 20 | 21 | {{end}} 22 | -------------------------------------------------------------------------------- /monitor.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2016 Justyn Temme 3 | This program is free software: you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation, either version 3 of the License, or 6 | (at your option) any later version. 7 | 8 | This program is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with this program. If not, see . 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | */ 24 | package main 25 | 26 | import "github.com/justyntemme/gomonitor/web" 27 | 28 | func main() { 29 | web.StartServer() 30 | } 31 | -------------------------------------------------------------------------------- /templates/home.html: -------------------------------------------------------------------------------- 1 | {{define "home"}} 2 | 3 | 4 | 5 | 6 | {{ .Title }} 7 | 8 | 9 | 10 |

{{ .Title }}

11 |
Home
12 |
13 | To use a command include it in your url reques
14 | Example: http://localhost:8080/ls povides the output of the ls command
15 | Supported Commands: 16 | 26 |
27 | 28 | 29 | {{end}} 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, justyntemme 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | 25 | -------------------------------------------------------------------------------- /web/web.go: -------------------------------------------------------------------------------- 1 | package web 2 | 3 | import ( 4 | "fmt" 5 | "html/template" 6 | "log" 7 | "net/http" 8 | "os/exec" 9 | "strings" 10 | ) 11 | 12 | type Page struct { 13 | Title string 14 | Body string 15 | Type string 16 | Data1 string 17 | Data2 string 18 | Data3 string 19 | } 20 | 21 | func panicMyway(err error, d http.ResponseWriter) { 22 | 23 | log.Print(err) 24 | status := http.StatusInternalServerError 25 | http.Error(d, http.StatusText(status), status) 26 | return 27 | } 28 | 29 | //StartServer STarts Starts server 30 | func StartServer() { 31 | fs := http.FileServer(http.Dir("static")) 32 | http.Handle("/static/", http.StripPrefix("/static/", fs)) 33 | http.HandleFunc("/", serveHTTP) 34 | http.HandleFunc("/docker", docker) 35 | http.HandleFunc("/ls", cmdLS) 36 | http.HandleFunc("/ps", cmdPs) 37 | http.HandleFunc("/man", man) 38 | http.HandleFunc("/dmesg", cmdDmesg) 39 | http.HandleFunc("/vmstat", cmdVmstat) 40 | http.HandleFunc("/free", cmdFree) 41 | http.HandleFunc("/top", cmdTop) 42 | http.HandleFunc("/iostat", cmdIostat) 43 | http.ListenAndServe(":8080", nil) 44 | 45 | } 46 | 47 | func docker(d http.ResponseWriter, req *http.Request) { 48 | c1 := exec.Command("docker", "ps") //work on sudo shit 49 | ps, err := c1.Output() 50 | log.Print(string(ps)) 51 | if err != nil { 52 | panicMyway(err, d) 53 | } 54 | c2 := exec.Command("docker", "stats") 55 | stats, err := c2.Output() 56 | log.Print(string(stats)) 57 | if err != nil { 58 | panicMyway(err, d) 59 | } 60 | 61 | serveTemplate(d, &Page{Title: "Docker Containers", Data1: string(ps), Data2: string(stats), Type: "docker"}) 62 | } 63 | func man(d http.ResponseWriter, req *http.Request) { 64 | var arg string 65 | var args []string 66 | c1 := exec.Command("man", "man") 67 | out, err := c1.Output() 68 | if req.Method == "POST" { 69 | req.ParseForm() 70 | fmt.Println(req.Form["arg"]) 71 | if req.Form["arg"][0] != "" { 72 | arg = "" 73 | for i := 0; i < len(req.Form["arg"]); i++ { 74 | arg += (req.Form["arg"][i]) 75 | strings.Replace(arg, "[", "", -1) 76 | strings.Replace(arg, "]", "", -1) 77 | } 78 | } 79 | args = strings.Split(arg, " ") 80 | c1 = exec.Command("man", args...) 81 | out, err = c1.Output() 82 | } 83 | if err != nil { 84 | panicMyway(err, d) 85 | } 86 | serveTemplate(d, &Page{Title: "Manpages", Body: string(out), Type: "man"}) 87 | } 88 | 89 | func serveTemplate(d http.ResponseWriter, page *Page) { 90 | d.Header().Add("Content Type", "text/html") 91 | var file string 92 | if page.Type == "home" { 93 | file = "home" 94 | } else if page.Type == "command" { 95 | file = "command" 96 | } else if page.Type == "man" { 97 | file = "man" 98 | } else if page.Type == "docker" { 99 | file = "docker" 100 | } 101 | tmpl, _ := template.ParseFiles("templates/home.html", "templates/command.html", "templates/man.html", "templates/docker.html") 102 | tmpl.ExecuteTemplate(d, file, page) 103 | } 104 | 105 | func serveHTTP(d http.ResponseWriter, req *http.Request) { 106 | serveTemplate(d, &Page{Title: "Home", Body: "", Type: "home"}) 107 | } 108 | 109 | func cmdLS(d http.ResponseWriter, req *http.Request) { 110 | var arg string = "--help" 111 | var args []string 112 | if req.Method == "POST" { 113 | req.ParseForm() 114 | fmt.Println(req.Form["arg"]) 115 | if req.Form["arg"][0] != "" { 116 | arg = "" 117 | for i := 0; i < len(req.Form["arg"]); i++ { 118 | arg += (req.Form["arg"][i]) 119 | strings.Replace(arg, "[", "", -1) 120 | strings.Replace(arg, "]", "", -1) 121 | } 122 | } else { 123 | arg = "--help" 124 | } 125 | fmt.Println(req.Form["arg"][0]) 126 | } 127 | args = strings.Split(arg, " ") 128 | c1 := exec.Command("ls", args...) 129 | out, err := c1.Output() 130 | if err != nil { 131 | panicMyway(err, d) 132 | } 133 | serveTemplate(d, &Page{Title: "Command: ls", Body: string(out), Type: "command"}) 134 | } 135 | 136 | func cmdFree(d http.ResponseWriter, req *http.Request) { 137 | var arg string = "--help" 138 | var args []string 139 | if req.Method == "POST" { 140 | req.ParseForm() 141 | fmt.Println(req.Form["arg"]) 142 | if req.Form["arg"][0] != "" { 143 | arg = "" 144 | for i := 0; i < len(req.Form["arg"]); i++ { 145 | arg += (req.Form["arg"][i]) 146 | strings.Replace(arg, "[", "", -1) 147 | strings.Replace(arg, "]", "", -1) 148 | } 149 | } else { 150 | arg = "--help" 151 | } 152 | fmt.Println(arg) 153 | } 154 | args = strings.Split(arg, " ") 155 | c1 := exec.Command("free", args...) 156 | out, err := c1.Output() 157 | if err != nil { 158 | panicMyway(err, d) 159 | } 160 | serveTemplate(d, &Page{Title: "Command: free", Body: string(out), Type: "command"}) 161 | } 162 | 163 | func cmdTop(d http.ResponseWriter, req *http.Request) { 164 | c1 := exec.Command("top", "-b", "-n1") 165 | out, err := c1.Output() 166 | if err != nil { 167 | panicMyway(err, d) 168 | } 169 | serveTemplate(d, &Page{Title: "Command: top", Body: string(out), Type: "command"}) 170 | } 171 | 172 | func cmdPs(d http.ResponseWriter, req *http.Request) { 173 | c1 := exec.Command("ps") 174 | out, err := c1.Output() 175 | if err != nil { 176 | panicMyway(err, d) 177 | } 178 | serveTemplate(d, &Page{Title: "Command: ps", Body: string(out), Type: "command"}) 179 | } 180 | 181 | func cmdIostat(d http.ResponseWriter, req *http.Request) { 182 | c1 := exec.Command("iostat") 183 | out, err := c1.Output() 184 | if err != nil { 185 | out = []byte(`Command not available on this system`) 186 | } 187 | serveTemplate(d, &Page{Title: "Command: iostat", Body: string(out), Type: "command"}) 188 | } 189 | func cmdDmesg(d http.ResponseWriter, req *http.Request) { 190 | c1 := exec.Command("dmesg") 191 | out, err := c1.Output() 192 | if err != nil { 193 | panicMyway(err, d) 194 | } 195 | serveTemplate(d, &Page{Title: "Command: dmesg", Body: string(out), Type: "command"}) 196 | } 197 | func cmdVmstat(d http.ResponseWriter, req *http.Request) { 198 | c1 := exec.Command("vmstat") 199 | out, err := c1.Output() 200 | if err != nil { 201 | panicMyway(err, d) 202 | } 203 | serveTemplate(d, &Page{Title: "Command: vmstat", Body: string(out), Type: "command"}) 204 | } 205 | --------------------------------------------------------------------------------