Version 3.0.0. Throwed out everything not used but for whatever reason added previously.
This commit is contained in:
parent
3de964388a
commit
df3714d071
4
.gitignore
vendored
4
.gitignore
vendored
@ -1,4 +1,4 @@
|
|||||||
.vscode
|
.vscode
|
||||||
*.conf
|
*.json
|
||||||
!config.example.conf
|
!config.example.json
|
||||||
httpprocprobed
|
httpprocprobed
|
15
Makefile
15
Makefile
@ -2,26 +2,29 @@ TARGET=httpprocprobed
|
|||||||
|
|
||||||
SYSDDIR_=${shell pkg-config systemd --variable=systemdsystemunitdir}
|
SYSDDIR_=${shell pkg-config systemd --variable=systemdsystemunitdir}
|
||||||
SYSDDIR=${SYSDDIR_:/%=%}
|
SYSDDIR=${SYSDDIR_:/%=%}
|
||||||
DESTDIR=/
|
DESTDIR:=
|
||||||
|
|
||||||
LDFLAGS=-ldflags "-s -w" -tags netgo
|
VERSION:=3.0.0
|
||||||
|
|
||||||
|
FLAGS:=-buildmode=pie -modcacherw -mod=readonly -trimpath
|
||||||
|
LDFLAGS=-ldflags "-s -w -X main.version=${VERSION}" -tags netgo
|
||||||
|
|
||||||
SOURCES := ${wildcard *.go}
|
SOURCES := ${wildcard *.go}
|
||||||
|
|
||||||
all: ${TARGET}
|
.PHONY: install uninstall clean
|
||||||
|
|
||||||
${TARGET}: ${SOURCES}
|
${TARGET}: ${SOURCES}
|
||||||
go build ${LDFLAGS}
|
go build ${LDFLAGS} ${FLAGS}
|
||||||
|
|
||||||
install:
|
install:
|
||||||
install -Dm 0755 ${TARGET} ${DESTDIR}usr/bin/${TARGET}
|
install -Dm 0755 ${TARGET} ${DESTDIR}usr/bin/${TARGET}
|
||||||
install -Dm 0644 configs/config.example.conf ${DESTDIR}etc/${TARGET}.conf
|
install -Dm 0644 configs/config.example.json ${DESTDIR}etc/${TARGET}.json
|
||||||
install -Dm 0644 LICENSE ${DESTDIR}usr/share/licenses/${TARGET}/LICENSE
|
install -Dm 0644 LICENSE ${DESTDIR}usr/share/licenses/${TARGET}/LICENSE
|
||||||
install -Dm 0644 init/systemd.service ${DESTDIR}${SYSDDIR}/${TARGET}.service
|
install -Dm 0644 init/systemd.service ${DESTDIR}${SYSDDIR}/${TARGET}.service
|
||||||
|
|
||||||
uninstall:
|
uninstall:
|
||||||
rm ${DESTDIR}usr/bin/${TARGET}
|
rm ${DESTDIR}usr/bin/${TARGET}
|
||||||
rm ${DESTDIR}usr/share/licenses/${TARGET}/LICENSE
|
rm ${DESTDIR}usr/share/licenses/${TARGET}
|
||||||
rm ${DESTDIR}${SYSDDIR}/${TARGET}.service
|
rm ${DESTDIR}${SYSDDIR}/${TARGET}.service
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
|
46
README.md
46
README.md
@ -1,46 +0,0 @@
|
|||||||
# httpprocprobed Ver 2.0.1
|
|
||||||
|
|
||||||
License: MIT+NIGGER.
|
|
||||||
|
|
||||||
This utility provides a HTTP `/processes` GET endpoint that returns a list of
|
|
||||||
processes, and if they are currently running or not.
|
|
||||||
|
|
||||||
There are currently three output formats available: JSON, XML, and plain text.
|
|
||||||
|
|
||||||
JSON is a default format if `Accept` header didn't provided, or did with
|
|
||||||
value `application/json`. Its form is `{"process":true|false, ...}`.
|
|
||||||
|
|
||||||
XML is provided if `Accept: application/xml` header was given. Its form is
|
|
||||||
`<ProcessList><Process name="process">true|false</Process>...</ProcessList>`.
|
|
||||||
|
|
||||||
Plain text is provided if `Accept: text/plain` header was given. Its form is a
|
|
||||||
comma separated list of ONLY running process' names.
|
|
||||||
|
|
||||||
Configuration file is a simple `key = value` storage consisting of
|
|
||||||
`listen_address` string field in form `"[<ip|host>]:<port>"`. `indented_output`
|
|
||||||
boolean in form `true|false`, to enable indentation of JSON and XML output.
|
|
||||||
And `processes` is a space separated array of process names.
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
### Manually
|
|
||||||
|
|
||||||
Run these commands one after the other.
|
|
||||||
|
|
||||||
```console
|
|
||||||
$ make
|
|
||||||
$ make install
|
|
||||||
```
|
|
||||||
|
|
||||||
In order to uninstall run these commands:
|
|
||||||
|
|
||||||
```console
|
|
||||||
# systemctl stop httpprocprobed
|
|
||||||
# systemctl disable httpprocprobed
|
|
||||||
$ make uninstall
|
|
||||||
# systemctl daemon-reload
|
|
||||||
```
|
|
||||||
|
|
||||||
### For ArchLinux
|
|
||||||
|
|
||||||
You can take a [PKGBUILD](/Arav/httpprocprobed/raw/branch/master/build/archlinux/PKGBUILD) file and in a directory with it run `makepkg -i`.
|
|
@ -1,21 +1,14 @@
|
|||||||
# Maintainer: Alexander "Arav" Andreev <me@arav.top>
|
# Maintainer: Alexander "Arav" Andreev <me@arav.su>
|
||||||
pkgname=httpprocprobed
|
pkgname=httpprocprobed
|
||||||
pkgver=2.0.1
|
pkgver=3.0.0
|
||||||
pkgrel=1
|
pkgrel=1
|
||||||
pkgdesc="HTTPProcProbeD hands out an HTTP endpoint to get if processes are running."
|
pkgdesc="HTTPProcProbeD hands out an HTTP endpoint to get if processes are running."
|
||||||
arch=('i686' 'x86_64' 'arm' 'armv6h' 'armv7h' 'aarch64')
|
arch=('i686' 'x86_64' 'arm' 'armv6h' 'armv7h' 'aarch64')
|
||||||
url="https://git.arav.top/Arav/httpprocprobed"
|
url="https://git.arav.su/Arav/httpprocprobed"
|
||||||
license=('MIT')
|
license=('MIT')
|
||||||
groups=()
|
makedepends=('go>=1.17')
|
||||||
depends=()
|
backup=('etc/httpprocprobed.json')
|
||||||
makedepends=('go')
|
source=("https://git.arav.su/Arav/httpprocprobed/archive/$pkgver.tar.gz")
|
||||||
provides=('httpprocprobed')
|
|
||||||
conflicts=('httpprocprobed')
|
|
||||||
replaces=()
|
|
||||||
backup=('etc/httpprocprobed.conf')
|
|
||||||
options=()
|
|
||||||
install=
|
|
||||||
source=('https://git.arav.top/Arav/httpprocprobed/archive/2.0.1.tar.gz')
|
|
||||||
noextract=()
|
noextract=()
|
||||||
md5sums=('SKIP')
|
md5sums=('SKIP')
|
||||||
|
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
listen_address = :28010
|
|
||||||
indented_output = false
|
|
||||||
processes =
|
|
6
configs/config.example.json
Normal file
6
configs/config.example.json
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"listen-address": ":28010",
|
||||||
|
"processes": [
|
||||||
|
{"alias": "minecraft", "process": "fabric-server-mc"}
|
||||||
|
]
|
||||||
|
}
|
@ -1,98 +1,27 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"log"
|
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Configuration holds a configuration for the service.
|
|
||||||
type Configuration struct {
|
type Configuration struct {
|
||||||
ListenAddress string
|
ListenAddress string `json:"listen-address"`
|
||||||
IndentedOutput bool
|
Processes []Process `json:"processes"`
|
||||||
Processes []string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadConfiguration loads configuration from a file.
|
|
||||||
func LoadConfiguration(path string) (conf *Configuration, err error) {
|
func LoadConfiguration(path string) (conf *Configuration, err error) {
|
||||||
conf = &Configuration{}
|
f, err := os.Open(path)
|
||||||
|
|
||||||
file, err := os.Open(path)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer file.Close()
|
defer f.Close()
|
||||||
|
|
||||||
s := bufio.NewScanner(file)
|
conf = &Configuration{}
|
||||||
s.Split(bufio.ScanLines)
|
|
||||||
|
|
||||||
for s.Scan() {
|
if err := json.NewDecoder(f).Decode(conf); err != nil {
|
||||||
kv := strings.Split(s.Text(), " = ")
|
return nil, err
|
||||||
switch kv[0] {
|
|
||||||
case "listen_address":
|
|
||||||
conf.ListenAddress = kv[1]
|
|
||||||
case "indented_output":
|
|
||||||
v, err := strconv.ParseBool(kv[1])
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("[WARN] could not parse \"indented_output\", valid values are true or false. Defaulted to false.\n")
|
|
||||||
}
|
|
||||||
conf.IndentedOutput = v
|
|
||||||
case "processes":
|
|
||||||
if kv[1] != "" {
|
|
||||||
conf.Processes = append(conf.Processes, strings.Split(kv[1], " ")...)
|
|
||||||
} else {
|
|
||||||
log.Printf("[WARN] \"processes\" list is empty.\n")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return conf, nil
|
return conf, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// StoreConfiguration writes configuration into a file.
|
|
||||||
func (conf *Configuration) StoreConfiguration(path string) (err error) {
|
|
||||||
var config strings.Builder
|
|
||||||
|
|
||||||
config.WriteString("listen_address = ")
|
|
||||||
config.WriteString(conf.ListenAddress)
|
|
||||||
config.WriteByte('\n')
|
|
||||||
config.WriteString("indented_output = ")
|
|
||||||
config.WriteString(strconv.FormatBool(conf.IndentedOutput))
|
|
||||||
config.WriteByte('\n')
|
|
||||||
config.WriteString("processes = ")
|
|
||||||
config.WriteString(strings.Join(conf.Processes, " "))
|
|
||||||
if err := os.WriteFile(path, []byte(config.String()), 0644); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddProcess appends a new given process into a configuration file.
|
|
||||||
func (conf *Configuration) AddProcess(process string, configPath string) error {
|
|
||||||
for _, v := range conf.Processes {
|
|
||||||
if v == process {
|
|
||||||
return errors.New("process is already on list")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
conf.Processes = append(conf.Processes, process)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// RemoveProcess removes a given process from a configuration file.
|
|
||||||
func (conf *Configuration) RemoveProcess(process string, configPath string) error {
|
|
||||||
for k, v := range conf.Processes {
|
|
||||||
if v == process {
|
|
||||||
newlist := make([]string, len(conf.Processes)-1)
|
|
||||||
newlist = append(conf.Processes[:k], conf.Processes[k+1:]...)
|
|
||||||
conf.Processes = newlist
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return errors.New("process is not on list")
|
|
||||||
}
|
|
||||||
|
24
http.go
Normal file
24
http.go
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AreProcessesUp sends back status of watched processes.
|
||||||
|
func AreProcessesUp(processes *[]Process) func(http.ResponseWriter, *http.Request) {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if r.Method != http.MethodGet {
|
||||||
|
w.WriteHeader(http.StatusMethodNotAllowed)
|
||||||
|
w.Header().Add("Allow", "GET")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
w.Header().Add("Content-Type", "application/json")
|
||||||
|
if err := json.NewEncoder(w).Encode(GetProcessesState(processes)); err != nil {
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
log.Printf("Failed to encode a process list: %s\n", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,86 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"encoding/json"
|
|
||||||
"encoding/xml"
|
|
||||||
"log"
|
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func CreateAndStartHTTPServer(conf *Configuration) *http.Server {
|
|
||||||
router := http.NewServeMux()
|
|
||||||
router.HandleFunc("/processes", AreProcessesUp(&conf.Processes, conf.IndentedOutput))
|
|
||||||
|
|
||||||
srv := &http.Server{
|
|
||||||
Addr: conf.ListenAddress,
|
|
||||||
Handler: router,
|
|
||||||
ReadTimeout: 5 * time.Second,
|
|
||||||
WriteTimeout: 5 * time.Second,
|
|
||||||
IdleTimeout: 10 * time.Second,
|
|
||||||
}
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
|
||||||
log.Fatalf("ListenAndServe: %s\n", err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
return srv
|
|
||||||
}
|
|
||||||
|
|
||||||
func ShutdownHTTPServer(srv *http.Server) {
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
srv.SetKeepAlivesEnabled(false)
|
|
||||||
if err := srv.Shutdown(ctx); err != nil {
|
|
||||||
log.Fatalf("%s\n", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AreProcessesUp handles a GET /processes request and sends back status of given
|
|
||||||
// processes.
|
|
||||||
func AreProcessesUp(processes *[]string, indented bool) func(http.ResponseWriter, *http.Request) {
|
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if r.Method == http.MethodGet {
|
|
||||||
proclist := make(ProcessList)
|
|
||||||
|
|
||||||
for _, proc := range *processes {
|
|
||||||
pids, err := GetProcessPIDs(proc)
|
|
||||||
proclist[proc] = err == nil && len(pids) > 0
|
|
||||||
}
|
|
||||||
|
|
||||||
switch r.Header.Get("Accept") {
|
|
||||||
case "application/xml":
|
|
||||||
w.Header().Add("Content-Type", "application/xml")
|
|
||||||
enc := xml.NewEncoder(w)
|
|
||||||
if indented {
|
|
||||||
enc.Indent("", "\t")
|
|
||||||
}
|
|
||||||
enc.Encode(proclist)
|
|
||||||
case "text/plain":
|
|
||||||
w.Header().Add("Content-Type", "text/plain")
|
|
||||||
var s []string
|
|
||||||
for k, v := range proclist {
|
|
||||||
if v {
|
|
||||||
s = append(s, k)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
w.Write([]byte(strings.Join(s, ",")))
|
|
||||||
default:
|
|
||||||
w.Header().Add("Content-Type", "application/json")
|
|
||||||
enc := json.NewEncoder(w)
|
|
||||||
if indented {
|
|
||||||
enc.SetIndent("", "\t")
|
|
||||||
}
|
|
||||||
enc.Encode(proclist)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
w.WriteHeader(http.StatusMethodNotAllowed)
|
|
||||||
w.Header().Add("Allow", "GET")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
78
main.go
78
main.go
@ -1,85 +1,52 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var configPath *string = flag.String("c", "config.conf", "path to configuration file")
|
var configPath *string = flag.String("c", "config.json", "path to configuration file")
|
||||||
var showVersion *bool = flag.Bool("v", false, "show version")
|
var showVersion *bool = flag.Bool("v", false, "show version")
|
||||||
var listProcesses *bool = flag.Bool("l", false, "list watched processes")
|
|
||||||
|
|
||||||
var addProcess *string = flag.String("a", "", "add process to list")
|
var version string
|
||||||
var removeProcess *string = flag.String("r", "", "remove process from list")
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
log.SetFlags(0)
|
log.SetFlags(0)
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
if *showVersion {
|
if *showVersion {
|
||||||
fmt.Println("httpprocprobed ver. 2.0.1")
|
fmt.Println("httpprocprobed ver.", version, "Copyright (c) 2021-2023 Alexander \"Arav\" Andreev <me@arav.su>")
|
||||||
fmt.Println("Copyright (c) 2021-2023 Alexander \"Arav\" Andreev <me@arav.top>")
|
|
||||||
fmt.Println("This program is licensed under terms of MIT+NIGGER license.")
|
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
conf, err := LoadConfiguration(*configPath)
|
conf, err := LoadConfiguration(*configPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("[ERR] Cannot load configuration file: %s\n", err)
|
log.Fatalf("Cannot load configuration file: %s\n", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if *listProcesses {
|
router := http.NewServeMux()
|
||||||
for _, v := range conf.Processes {
|
router.HandleFunc("/processes", AreProcessesUp(&conf.Processes))
|
||||||
fmt.Printf("%s, ", v)
|
|
||||||
}
|
srv := &http.Server{
|
||||||
fmt.Println()
|
Addr: conf.ListenAddress,
|
||||||
os.Exit(0)
|
Handler: router,
|
||||||
|
ReadTimeout: 5 * time.Second,
|
||||||
|
WriteTimeout: 5 * time.Second,
|
||||||
|
IdleTimeout: 10 * time.Second,
|
||||||
}
|
}
|
||||||
|
|
||||||
if *addProcess != "" {
|
go func() {
|
||||||
err := conf.AddProcess(*addProcess, *configPath)
|
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
||||||
if err != nil {
|
log.Fatalf("ListenAndServe: %s\n", err)
|
||||||
log.Fatalf("[ERR] Cannot add process: %s\n", err)
|
|
||||||
}
|
}
|
||||||
}
|
}()
|
||||||
|
|
||||||
if *removeProcess != "" {
|
|
||||||
err := conf.RemoveProcess(*removeProcess, *configPath)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("[ERR] Cannot remove process: %s\n", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we modified a list then let's look for a running program and
|
|
||||||
// send SIGHUP to it to reload a list. Here we assume that there
|
|
||||||
// is only one process running, so we just filter our PID.
|
|
||||||
if *addProcess != "" || *removeProcess != "" {
|
|
||||||
if err := conf.StoreConfiguration(*configPath); err != nil {
|
|
||||||
log.Fatalf("[ERR] Cannot write configuration. Error: %s\n", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
pids, _ := GetProcessPIDs("httpprocprobed")
|
|
||||||
if len(pids) > 1 {
|
|
||||||
var trgt_pid int
|
|
||||||
if pids[0] == os.Getpid() {
|
|
||||||
trgt_pid = pids[1]
|
|
||||||
} else {
|
|
||||||
trgt_pid = pids[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
if proc, err := os.FindProcess(trgt_pid); err == nil {
|
|
||||||
proc.Signal(syscall.SIGHUP)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
os.Exit(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
srv := CreateAndStartHTTPServer(conf)
|
|
||||||
|
|
||||||
syssignal := make(chan os.Signal, 1)
|
syssignal := make(chan os.Signal, 1)
|
||||||
signal.Notify(syssignal, os.Interrupt, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP)
|
signal.Notify(syssignal, os.Interrupt, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP)
|
||||||
@ -91,7 +58,10 @@ func main() {
|
|||||||
case os.Interrupt:
|
case os.Interrupt:
|
||||||
fallthrough
|
fallthrough
|
||||||
case syscall.SIGINT | syscall.SIGTERM:
|
case syscall.SIGINT | syscall.SIGTERM:
|
||||||
ShutdownHTTPServer(srv)
|
srv.SetKeepAlivesEnabled(false)
|
||||||
|
if err := srv.Shutdown(context.Background()); err != nil {
|
||||||
|
log.Fatalf("%s\n", err)
|
||||||
|
}
|
||||||
log.Println("Server shutted down.")
|
log.Println("Server shutted down.")
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
case syscall.SIGHUP:
|
case syscall.SIGHUP:
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd
|
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -8,6 +6,27 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Process contains an alias that will be returned when queries, and a process
|
||||||
|
// name to look for.
|
||||||
|
type Process struct {
|
||||||
|
Alias string `json:"alias"`
|
||||||
|
Process string `json:"process"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProcessesState is a map of processes' aliases and its statuses.
|
||||||
|
type ProcessesState map[string]bool
|
||||||
|
|
||||||
|
func GetProcessesState(procs *[]Process) (ps ProcessesState) {
|
||||||
|
ps = make(ProcessesState)
|
||||||
|
|
||||||
|
for _, proc := range *procs {
|
||||||
|
pids, err := GetProcessPIDs(proc.Process)
|
||||||
|
ps[proc.Alias] = err == nil && len(pids) > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// GetProcessPIDs returns a list of PIDs found for a process.
|
// GetProcessPIDs returns a list of PIDs found for a process.
|
||||||
func GetProcessPIDs(name string) (pids []int, err error) {
|
func GetProcessPIDs(name string) (pids []int, err error) {
|
||||||
dir, err := os.ReadDir("/proc/")
|
dir, err := os.ReadDir("/proc/")
|
@ -1,32 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/xml"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ProcessList is a map of processes' names and its statuses.
|
|
||||||
type ProcessList map[string]bool
|
|
||||||
|
|
||||||
// MarshalXML implements XML Marshaler interface for a ProcessList.
|
|
||||||
func (l *ProcessList) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
|
|
||||||
if len(*l) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := e.EncodeToken(start); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
for key, val := range *l {
|
|
||||||
e.Encode(struct {
|
|
||||||
XMLName xml.Name
|
|
||||||
Name string `xml:"name,attr"`
|
|
||||||
IsUp bool `xml:",chardata"`
|
|
||||||
}{
|
|
||||||
XMLName: xml.Name{Local: "Process"},
|
|
||||||
Name: key,
|
|
||||||
IsUp: val})
|
|
||||||
}
|
|
||||||
|
|
||||||
return e.EncodeToken(start.End())
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user