Skip to content
This repository has been archived by the owner on Sep 21, 2020. It is now read-only.

Commit

Permalink
First working version
Browse files Browse the repository at this point in the history
  • Loading branch information
dasavick committed Mar 2, 2019
1 parent d63a7f7 commit 7d5ff5c
Show file tree
Hide file tree
Showing 4 changed files with 231 additions and 0 deletions.
39 changes: 39 additions & 0 deletions daemon.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package main

import (
"github.com/go-ini/ini"
)

type ScreenInfo struct {
Name string `ini:"name"`
}

type ExecutionInfo struct {
Command string `ini:"command"`
}

type DaemonInfo struct {
Enabled bool `ini:"enabled"`
}

type DaemonConfig struct {
ScreenInfo `ini:"Screen"`
ExecutionInfo `ini:"Execution"`
DaemonInfo `ini:"Daemon"`
}

func loadDaemon(cfgPath string) (*DaemonConfig, error) {

cfg, err := ini.LoadSources(ini.LoadOptions{
IgnoreInlineComment: true,
UnescapeValueCommentSymbols: true,
}, cfgPath)

daemonConfig := new(DaemonConfig)
err = cfg.MapTo(daemonConfig)
if err != nil {
return daemonConfig, err
}

return daemonConfig, nil
}
8 changes: 8 additions & 0 deletions daemons/test.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[Screen]
name = testgit

[Execution]
command = bash

[Daemon]
enabled = true
75 changes: 75 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package main

import (
"log"
"os/exec"
"path/filepath"
"strconv"
"time"
)

func executeCommand(args ...string) (string, error) {

baseCmd := args[0]
cmdArgs := args[1:]

cmd := exec.Command(baseCmd, cmdArgs...)
out, err := cmd.Output()
if err != nil {
return string(out), err
}

return string(out), nil
}

func main() {

files, err := filepath.Glob("daemons/*.ini")
if err != nil {
log.Fatal("Failed to find daemons: ", err)
return
}

var daemons []DaemonConfig
for _, cfgPath := range files {

cfg, err := loadDaemon(cfgPath)
if err != nil {
log.Fatal("Failed load ", cfgPath, err)
continue
}

daemons = append(daemons, *cfg)
}

firstRun := true

for {
for _, daemon := range daemons {

if !daemon.Enabled {
continue
}

command := daemon.Command
name := daemon.Name

screen, err := runScreen(name, command)
if err != nil {
if err.Error() == "SCREEN_ALREADY_EXISTS" {
if firstRun {
log.Print("(", name, ") WARNING: skipped, screen already exists")
}
} else {
log.Fatal("(", name, ") FAILED: ", command, " [", err, "]")
}
continue
}

log.Print("(" + strconv.Itoa(screen.id) + ", " + screen.name + ") STARTED: " + command)
}

firstRun = false
time.Sleep(5 * time.Second)
}
}
109 changes: 109 additions & 0 deletions screen.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package main

import (
"github.com/pkg/errors"
"strconv"
"strings"
)

type Screen struct {
id int
name string
}

func runScreen(screenName string, command string) (Screen, error) {

exists, err := doesScreenExists(screenName)
if err != nil {
return Screen{}, err
}

if exists {
return Screen{}, errors.New("SCREEN_ALREADY_EXISTS")
}

args := []string{"screen", "-dmS", screenName}
args = append(args, strings.Split(command, " ")...)

_, err = executeCommand(args...)
if err != nil {
if err.Error() == "exit status 1" {
return Screen{}, errors.New("exit status 1: check command")
}
return Screen{}, err
}

screen, err := getScreenByName(screenName)
if err != nil {
if err.Error() == "SCREEN_NOT_FOUND" {
return Screen{}, errors.New("Screen " + screenName + " not present after creation")
}
return Screen{}, err
}

return screen, nil
}

func getRunningScreens() ([]Screen, error) {

output, err := executeCommand("screen", "-ls")
if err != nil {
if !strings.HasPrefix(output, "No Sockets found in") {
return []Screen{}, err
}
return []Screen{}, nil
}

var screens []Screen
lines := strings.Split(output, "\n")
for _, line := range lines {

if !strings.HasPrefix(line, "\t") {
continue
}

lineParts := strings.Split(line, "\t")
fullScreenName := lineParts[1]
fullNameParts := strings.Split(fullScreenName, ".")

name := strings.Join(fullNameParts[1:], ".")
id, err := strconv.Atoi(fullNameParts[0])
if err != nil {
return []Screen{}, err
}

screens = append(screens, Screen{id, name})
}

return screens, nil
}

func doesScreenExists(screenName string) (bool, error) {

_, err := getScreenByName(screenName)
if err != nil {
if err.Error() == "SCREEN_NOT_FOUND" {
return false, nil
}
return false, err
}

return true, nil
}

func getScreenByName(screenName string) (Screen, error) {

screens, err := getRunningScreens()
if err != nil {
return Screen{}, err
}

for _, screen := range screens {
if screen.name != screenName {
continue
}
return screen, nil
}

return Screen{}, errors.New("SCREEN_NOT_FOUND")
}

0 comments on commit 7d5ff5c

Please sign in to comment.