Compare commits
4 Commits
74868ab2d3
...
b77147434e
Author | SHA1 | Date | |
---|---|---|---|
b77147434e | |||
fe33725c09 | |||
aec103063f | |||
b4847da839 |
@ -1,10 +1,12 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
"os"
|
"os"
|
||||||
"slices"
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
var flagsEquivalence = map[string]uintptr{
|
var flagsEquivalence = map[string]uintptr{
|
||||||
@ -111,6 +113,8 @@ func mountFstabEntries() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
swapPriority := -2
|
||||||
|
|
||||||
for _, line := range strings.Split(string(bytes), "\n") {
|
for _, line := range strings.Split(string(bytes), "\n") {
|
||||||
line = strings.TrimSpace(line)
|
line = strings.TrimSpace(line)
|
||||||
if strings.HasPrefix(line, "#") || line == "" {
|
if strings.HasPrefix(line, "#") || line == "" {
|
||||||
@ -128,6 +132,18 @@ func mountFstabEntries() error {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if fstype == "swap" {
|
||||||
|
b := append([]byte(source), 0)
|
||||||
|
const SwapFlagPrioShift = 0
|
||||||
|
const SwapFlagPrioMask = 0x7fff
|
||||||
|
_, _, err := unix.Syscall(unix.SYS_SWAPON, uintptr(unsafe.Pointer(&b[0])), uintptr((swapPriority<<SwapFlagPrioShift)&SwapFlagPrioMask), 0)
|
||||||
|
swapPriority--
|
||||||
|
if err != 0 {
|
||||||
|
return fmt.Errorf("swapon syscall returned none-zero error code: %d", err)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
if isMountpoint(target) && !slices.Contains(flags, unix.MS_REMOUNT) {
|
if isMountpoint(target) && !slices.Contains(flags, unix.MS_REMOUNT) {
|
||||||
flags = append(flags, unix.MS_REMOUNT)
|
flags = append(flags, unix.MS_REMOUNT)
|
||||||
}
|
}
|
||||||
|
@ -2,4 +2,4 @@ module esvm
|
|||||||
|
|
||||||
go 1.23.4
|
go 1.23.4
|
||||||
|
|
||||||
require gopkg.in/yaml.v3 v3.0.1 // indirect
|
require gopkg.in/yaml.v3 v3.0.1
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
112
cmd/esvm/main.go
112
cmd/esvm/main.go
@ -39,6 +39,7 @@ type EnitService struct {
|
|||||||
CrashOnSafeExit bool `yaml:"crash_on_safe_exit"`
|
CrashOnSafeExit bool `yaml:"crash_on_safe_exit"`
|
||||||
StopCmd string `yaml:"stop_cmd,omitempty"`
|
StopCmd string `yaml:"stop_cmd,omitempty"`
|
||||||
Restart string `yaml:"restart,omitempty"`
|
Restart string `yaml:"restart,omitempty"`
|
||||||
|
LogOutput bool `yaml:"log_output,omitempty"`
|
||||||
ServiceRunPath string
|
ServiceRunPath string
|
||||||
restartCount int
|
restartCount int
|
||||||
stopChannel chan bool
|
stopChannel chan bool
|
||||||
@ -57,13 +58,12 @@ var logger *log.Logger
|
|||||||
var socket net.Listener
|
var socket net.Listener
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
loggerFile, err := os.OpenFile("/var/log/esvm.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
|
// Setup main logger
|
||||||
|
err := setupESVMLogger()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error opening /var/log/esvm/esvm.log: %v", err)
|
log.Printf("Could not setup main ESVM logger! Error: %s\n", err)
|
||||||
|
logger = log.Default()
|
||||||
}
|
}
|
||||||
logger = log.New(loggerFile, "[ESVM] ", log.Lshortfile|log.LstdFlags)
|
|
||||||
// Print an empty line as separator
|
|
||||||
logger.Println()
|
|
||||||
|
|
||||||
// Parse flags
|
// Parse flags
|
||||||
printVersion := flag.Bool("version", false, "print version and exit")
|
printVersion := flag.Bool("version", false, "print version and exit")
|
||||||
@ -93,7 +93,6 @@ func main() {
|
|||||||
go func() {
|
go func() {
|
||||||
<-sigc
|
<-sigc
|
||||||
Destroy()
|
Destroy()
|
||||||
loggerFile.Close()
|
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@ -102,6 +101,22 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setupESVMLogger() error {
|
||||||
|
err := os.MkdirAll("/var/log/esvm", 0755)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
loggerFile, err := os.OpenFile("/var/log/esvm/esvm.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
logger = log.New(loggerFile, "[ESVM] ", log.Lshortfile|log.LstdFlags)
|
||||||
|
// Print an empty line as separator
|
||||||
|
_, err = loggerFile.WriteString("------ " + time.Now().Format(time.UnixDate) + " ------\n")
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func Init() {
|
func Init() {
|
||||||
logger.Println("Initializing ESVM...")
|
logger.Println("Initializing ESVM...")
|
||||||
|
|
||||||
@ -152,6 +167,7 @@ func Init() {
|
|||||||
ServiceRunPath: "",
|
ServiceRunPath: "",
|
||||||
restartCount: 0,
|
restartCount: 0,
|
||||||
stopChannel: make(chan bool),
|
stopChannel: make(chan bool),
|
||||||
|
LogOutput: true,
|
||||||
}
|
}
|
||||||
if err := yaml.Unmarshal(bytes, &service); err != nil {
|
if err := yaml.Unmarshal(bytes, &service); err != nil {
|
||||||
logger.Printf("Could not read service file at %s!\n", path.Join(serviceConfigDir, "services", entry.Name()))
|
logger.Printf("Could not read service file at %s!\n", path.Join(serviceConfigDir, "services", entry.Name()))
|
||||||
@ -232,9 +248,18 @@ func Init() {
|
|||||||
service := servicesWithMetDepends[i]
|
service := servicesWithMetDepends[i]
|
||||||
canStart := true
|
canStart := true
|
||||||
for _, dependency := range service.Dependencies {
|
for _, dependency := range service.Dependencies {
|
||||||
if GetServiceByName(dependency).GetCurrentState() != EnitServiceRunning && GetServiceByName(dependency).GetCurrentState() != EnitServiceCompleted {
|
if strings.HasPrefix(dependency, "/") {
|
||||||
canStart = false
|
// File dependency
|
||||||
break
|
if _, err := os.Stat(dependency); err != nil {
|
||||||
|
canStart = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Service dependency
|
||||||
|
if GetServiceByName(dependency).GetCurrentState() != EnitServiceRunning && GetServiceByName(dependency).GetCurrentState() != EnitServiceCompleted {
|
||||||
|
canStart = false
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if canStart {
|
if canStart {
|
||||||
@ -277,9 +302,17 @@ func GetServiceByName(name string) *EnitService {
|
|||||||
|
|
||||||
func (service *EnitService) GetUnmetDependencies() (missingDependencies []string) {
|
func (service *EnitService) GetUnmetDependencies() (missingDependencies []string) {
|
||||||
for _, dependency := range service.Dependencies {
|
for _, dependency := range service.Dependencies {
|
||||||
depService := GetServiceByName(dependency)
|
if strings.HasPrefix(dependency, "/") {
|
||||||
if depService == nil {
|
// File dependency
|
||||||
missingDependencies = append(missingDependencies, dependency)
|
if _, err := os.Stat(dependency); err != nil {
|
||||||
|
missingDependencies = append(missingDependencies, dependency)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Service dependency
|
||||||
|
depService := GetServiceByName(dependency)
|
||||||
|
if depService == nil {
|
||||||
|
missingDependencies = append(missingDependencies, dependency)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -332,6 +365,26 @@ func (service *EnitService) setCurrentState(state EnitServiceState) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (service *EnitService) GetLogFile() (file *os.File, err error) {
|
||||||
|
err = os.MkdirAll(path.Join("/var/log/esvm/"), 0755)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
file, err = os.OpenFile(path.Join("/var/log/esvm/", service.Name+".log"), os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0644)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = file.WriteString("------ " + time.Now().Format(time.UnixDate) + " ------\n")
|
||||||
|
if err != nil {
|
||||||
|
file.Close()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return file, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (service *EnitService) StartService() error {
|
func (service *EnitService) StartService() error {
|
||||||
if service == nil {
|
if service == nil {
|
||||||
return nil
|
return nil
|
||||||
@ -342,23 +395,58 @@ func (service *EnitService) StartService() error {
|
|||||||
|
|
||||||
logger.Printf("Starting service (%s)...\n", service.Name)
|
logger.Printf("Starting service (%s)...\n", service.Name)
|
||||||
|
|
||||||
|
// Get log file if service logs output
|
||||||
|
var logFile *os.File
|
||||||
|
if service.LogOutput {
|
||||||
|
var err error
|
||||||
|
logFile, err = service.GetLogFile()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cmd := exec.Command("/bin/sh", "-c", "exec "+service.StartCmd)
|
cmd := exec.Command("/bin/sh", "-c", "exec "+service.StartCmd)
|
||||||
|
if logFile != nil {
|
||||||
|
cmd.Stdout = logFile
|
||||||
|
cmd.Stderr = logFile
|
||||||
|
}
|
||||||
if err := cmd.Start(); err != nil {
|
if err := cmd.Start(); err != nil {
|
||||||
|
// Close log file if not nil
|
||||||
|
if logFile != nil {
|
||||||
|
logFile.Close()
|
||||||
|
}
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err := service.setProcessID(cmd.Process.Pid)
|
err := service.setProcessID(cmd.Process.Pid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// Close log file if not nil
|
||||||
|
if logFile != nil {
|
||||||
|
logFile.Close()
|
||||||
|
}
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = service.setCurrentState(EnitServiceRunning)
|
err = service.setCurrentState(EnitServiceRunning)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// Close log file if not nil
|
||||||
|
if logFile != nil {
|
||||||
|
logFile.Close()
|
||||||
|
}
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
err := cmd.Wait()
|
err := cmd.Wait()
|
||||||
|
|
||||||
|
// Close log file if not nil
|
||||||
|
if logFile != nil {
|
||||||
|
logFile.Close()
|
||||||
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case <-service.stopChannel:
|
case <-service.stopChannel:
|
||||||
service.restartCount = 0
|
service.restartCount = 0
|
||||||
|
7
services/lo-interface.esv
Normal file
7
services/lo-interface.esv
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
name: lo-interface
|
||||||
|
description: Enable loopback interface on boot
|
||||||
|
dependencies: ["/usr/sbin/ip"]
|
||||||
|
type: simple
|
||||||
|
start_cmd: ip link set lo up
|
||||||
|
exit_method: kill
|
||||||
|
restart: false
|
Loading…
x
Reference in New Issue
Block a user