mirror of
https://github.com/EnumeratedDev/enit.git
synced 2026-09-16 02:26:11 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eb424b0416
|
||
|
|
b64d6984be
|
||
|
|
a3403ca151
|
||
|
|
f263ec06cc
|
||
|
|
075b5a8bad
|
||
|
|
542f9987e1
|
||
|
|
48b9e3512a
|
||
|
|
f69ca4d02c
|
||
|
|
84de96ceca
|
||
|
|
2c97e87261
|
||
|
|
49541f6f76
|
||
|
|
fc738e6f4e
|
||
|
|
87ea28bfa3
|
@@ -1,12 +1,14 @@
|
|||||||
SHELL := /bin/bash
|
# Installation paths
|
||||||
|
|
||||||
PREFIX ?= /usr/local
|
PREFIX ?= /usr/local
|
||||||
SBINDIR ?= $(PREFIX)/sbin
|
SBINDIR ?= $(PREFIX)/sbin
|
||||||
SYSCONFDIR ?= $(PREFIX)/etc
|
SYSCONFDIR ?= $(PREFIX)/etc
|
||||||
LOCALSTATEDIR ?= $(PREFIX)/var
|
LOCALSTATEDIR ?= $(PREFIX)/var
|
||||||
RUNSTATEDIR ?= $(LOCALSTATEDIR)/run
|
RUNSTATEDIR ?= $(LOCALSTATEDIR)/run
|
||||||
|
|
||||||
|
# Compilers and tools
|
||||||
GO ?= $(shell type -a -P go | head -n 1)
|
GO ?= $(shell type -a -P go | head -n 1)
|
||||||
|
|
||||||
|
# Build-time variables
|
||||||
VERSION ?= $(shell git describe --tags --dirty)
|
VERSION ?= $(shell git describe --tags --dirty)
|
||||||
|
|
||||||
build:
|
build:
|
||||||
@@ -15,18 +17,23 @@ build:
|
|||||||
cd src/esvm; $(GO) build -ldflags "-w -X main.version=$(VERSION)" -o ../../build/esvm esvm
|
cd src/esvm; $(GO) build -ldflags "-w -X main.version=$(VERSION)" -o ../../build/esvm esvm
|
||||||
cd src/ectl; $(GO) build -ldflags "-w -X main.version=$(VERSION) -X main.sysconfdir=$(SYSCONFDIR) -X main.runstatedir=$(RUNSTATEDIR)" -o ../../build/ectl ectl
|
cd src/ectl; $(GO) build -ldflags "-w -X main.version=$(VERSION) -X main.sysconfdir=$(SYSCONFDIR) -X main.runstatedir=$(RUNSTATEDIR)" -o ../../build/ectl ectl
|
||||||
|
|
||||||
install: build/enit build/ectl
|
install: build/enit build/ectl build/esvm
|
||||||
mkdir -p $(DESTDIR)$(SBINDIR)
|
# Create directories
|
||||||
mkdir -p $(DESTDIR)$(SYSCONFDIR)/esvm/services
|
install -d $(DESTDIR)$(SBINDIR)
|
||||||
cp build/enit $(DESTDIR)$(SBINDIR)/enit
|
# Install binaries
|
||||||
cp build/esvm $(DESTDIR)$(SBINDIR)/esvm
|
install -m755 build/{enit,esvm,ectl} -t $(DESTDIR)$(SBINDIR)
|
||||||
cp build/ectl $(DESTDIR)$(SBINDIR)/ectl
|
|
||||||
|
|
||||||
install-services:
|
install-services:
|
||||||
mkdir -p $(DESTDIR)$(SYSCONFDIR)/esvm/services
|
# Create directory
|
||||||
cp services/* -t $(DESTDIR)$(SYSCONFDIR)/esvm/services
|
install -d $(DESTDIR)$(SYSCONFDIR)/esvm/services
|
||||||
|
# Install services
|
||||||
|
install -m644 services/*.esv -t $(DESTDIR)$(SYSCONFDIR)/esvm/services
|
||||||
|
|
||||||
|
uninstall:
|
||||||
|
-rm -f $(DESTDIR)$(SBINDIR)/{enit,esvm,ectl}
|
||||||
|
-rm -rf $(DESTDIR)$(SYSCONFDIR)/esvm
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -r build/
|
rm -r build/
|
||||||
|
|
||||||
.PHONY: build
|
.PHONY: build install install-services uninstall clean
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
# Enit
|
||||||
|
## The official init system for Tide Linux
|
||||||
|
|
||||||
|
### Project Information
|
||||||
|
Enit is an init system developed for the Tide Linux project. It features easy-to-use commands for power and service management and yaml-based service configuration
|
||||||
|
|
||||||
|
### Installation Guide
|
||||||
|
#### Using a package manager
|
||||||
|
- Tide Linux: Enit is pre-installed as the default init system through the `enit` package
|
||||||
|
#### Building from source
|
||||||
|
- Download `go` from your package manager or from the go website
|
||||||
|
- Download `make` from your package manager
|
||||||
|
- Run the following command to compile the project
|
||||||
|
```
|
||||||
|
make PREFIX=/usr SYSCONFDIR=/etc LOCALSTATEDIR=/var
|
||||||
|
```
|
||||||
|
- Run the following command to install Enit into your system. You may also append a DESTDIR variable at the end of this line if you wish to install in a different root directory
|
||||||
|
```
|
||||||
|
make install PREFIX=/usr
|
||||||
|
make install-config PREFIX=/usr SYSCONFDIR=/etc
|
||||||
|
```
|
||||||
|
### Post installation
|
||||||
|
- Set the default init system in your bootloader/boot-manager by appending `init=/usr/sbin/enit` to your kernel command-line parameters. Alternatively symlink `/usr/sbin/enit` to `/sbin/init`
|
||||||
|
- You may find additional service files in the [Tide Linux repositories](https://git.enumerated.dev/tide-linux). Some service files will likely need to be modified to run in your distribution
|
||||||
@@ -2,7 +2,6 @@ name: agetty-tty1
|
|||||||
description: Start virtual terminal on tty1
|
description: Start virtual terminal on tty1
|
||||||
type: background
|
type: background
|
||||||
start_cmd: /usr/bin/setsid /sbin/agetty --noclear tty1
|
start_cmd: /usr/bin/setsid /sbin/agetty --noclear tty1
|
||||||
exit_method: kill
|
|
||||||
crash_on_safe_exit: false
|
crash_on_safe_exit: false
|
||||||
restart: always
|
restart: always
|
||||||
setpgid: false
|
setpgid: false
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ name: agetty-tty2
|
|||||||
description: Start virtual terminal on tty2
|
description: Start virtual terminal on tty2
|
||||||
type: background
|
type: background
|
||||||
start_cmd: /usr/bin/setsid /sbin/agetty tty2
|
start_cmd: /usr/bin/setsid /sbin/agetty tty2
|
||||||
exit_method: kill
|
|
||||||
crash_on_safe_exit: false
|
crash_on_safe_exit: false
|
||||||
restart: always
|
restart: always
|
||||||
setpgid: false
|
setpgid: false
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ name: agetty-tty3
|
|||||||
description: Start virtual terminal on tty3
|
description: Start virtual terminal on tty3
|
||||||
type: background
|
type: background
|
||||||
start_cmd: /usr/bin/setsid /sbin/agetty tty3
|
start_cmd: /usr/bin/setsid /sbin/agetty tty3
|
||||||
exit_method: kill
|
|
||||||
crash_on_safe_exit: false
|
crash_on_safe_exit: false
|
||||||
restart: always
|
restart: always
|
||||||
setpgid: false
|
setpgid: false
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ name: agetty-tty4
|
|||||||
description: Start virtual terminal on tty4
|
description: Start virtual terminal on tty4
|
||||||
type: background
|
type: background
|
||||||
start_cmd: /usr/bin/setsid /sbin/agetty tty4
|
start_cmd: /usr/bin/setsid /sbin/agetty tty4
|
||||||
exit_method: kill
|
|
||||||
crash_on_safe_exit: false
|
crash_on_safe_exit: false
|
||||||
restart: always
|
restart: always
|
||||||
setpgid: false
|
setpgid: false
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ name: agetty-tty5
|
|||||||
description: Start virtual terminal on tty5
|
description: Start virtual terminal on tty5
|
||||||
type: background
|
type: background
|
||||||
start_cmd: /usr/bin/setsid /sbin/agetty tty5
|
start_cmd: /usr/bin/setsid /sbin/agetty tty5
|
||||||
exit_method: kill
|
|
||||||
crash_on_safe_exit: false
|
crash_on_safe_exit: false
|
||||||
restart: always
|
restart: always
|
||||||
setpgid: false
|
setpgid: false
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ name: agetty-tty6
|
|||||||
description: Start virtual terminal on tty6
|
description: Start virtual terminal on tty6
|
||||||
type: background
|
type: background
|
||||||
start_cmd: /usr/bin/setsid /sbin/agetty tty6
|
start_cmd: /usr/bin/setsid /sbin/agetty tty6
|
||||||
exit_method: kill
|
|
||||||
crash_on_safe_exit: false
|
crash_on_safe_exit: false
|
||||||
restart: always
|
restart: always
|
||||||
setpgid: false
|
setpgid: false
|
||||||
|
|||||||
@@ -2,5 +2,3 @@ name: lo-interface
|
|||||||
description: Enable loopback interface on boot
|
description: Enable loopback interface on boot
|
||||||
type: simple
|
type: simple
|
||||||
start_cmd: ip link set lo up
|
start_cmd: ip link set lo up
|
||||||
exit_method: kill
|
|
||||||
restart: false
|
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
name: rc-local
|
||||||
|
description: Run the /etc/rc.local script at boot
|
||||||
|
type: simple
|
||||||
|
start_cmd: /etc/rc.local
|
||||||
+53
-17
@@ -35,8 +35,12 @@ func handleServiceSubcommand() {
|
|||||||
setupFlagsAndHelp(currentFlagSet, fmt.Sprintf("ectl %s %s <options> <service>", os.Args[1], subcommand), fmt.Sprintf("%s the specified service", strings.Title(subcommand)), os.Args[3:])
|
setupFlagsAndHelp(currentFlagSet, fmt.Sprintf("ectl %s %s <options> <service>", os.Args[1], subcommand), fmt.Sprintf("%s the specified service", strings.Title(subcommand)), os.Args[3:])
|
||||||
|
|
||||||
// Dial esvm socket
|
// Dial esvm socket
|
||||||
dialSocket()
|
err := dialSocket()
|
||||||
|
if err == nil {
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
} else {
|
||||||
|
log.Fatalf("Error: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
startStopRestartService(subcommand)
|
startStopRestartService(subcommand)
|
||||||
case "enable", "disable":
|
case "enable", "disable":
|
||||||
@@ -53,8 +57,12 @@ func handleServiceSubcommand() {
|
|||||||
setupFlagsAndHelp(currentFlagSet, fmt.Sprintf("ectl %s status <options> <service>", os.Args[1]), "Show service status", os.Args[3:])
|
setupFlagsAndHelp(currentFlagSet, fmt.Sprintf("ectl %s status <options> <service>", os.Args[1]), "Show service status", os.Args[3:])
|
||||||
|
|
||||||
// Dial esvm socket
|
// Dial esvm socket
|
||||||
dialSocket()
|
err := dialSocket()
|
||||||
|
if err == nil {
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
} else {
|
||||||
|
log.Fatalf("Error: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
showServiceStatus()
|
showServiceStatus()
|
||||||
case "list":
|
case "list":
|
||||||
@@ -64,8 +72,12 @@ func handleServiceSubcommand() {
|
|||||||
setupFlagsAndHelp(currentFlagSet, fmt.Sprintf("ectl %s reload <options>", os.Args[1]), "List all services", os.Args[3:])
|
setupFlagsAndHelp(currentFlagSet, fmt.Sprintf("ectl %s reload <options>", os.Args[1]), "List all services", os.Args[3:])
|
||||||
|
|
||||||
// Dial esvm socket
|
// Dial esvm socket
|
||||||
dialSocket()
|
err := dialSocket()
|
||||||
|
if err == nil {
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
} else {
|
||||||
|
log.Fatalf("Error: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
listAllServices()
|
listAllServices()
|
||||||
case "reload":
|
case "reload":
|
||||||
@@ -75,8 +87,12 @@ func handleServiceSubcommand() {
|
|||||||
setupFlagsAndHelp(currentFlagSet, fmt.Sprintf("ectl %s reload <options>", os.Args[1]), "Reload all services", os.Args[3:])
|
setupFlagsAndHelp(currentFlagSet, fmt.Sprintf("ectl %s reload <options>", os.Args[1]), "Reload all services", os.Args[3:])
|
||||||
|
|
||||||
// Dial esvm socket
|
// Dial esvm socket
|
||||||
dialSocket()
|
err := dialSocket()
|
||||||
|
if err == nil {
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
} else {
|
||||||
|
log.Fatalf("Error: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
reloadAllServices()
|
reloadAllServices()
|
||||||
default:
|
default:
|
||||||
@@ -174,6 +190,18 @@ func enableDisableService(subcommand string) {
|
|||||||
verb = "disabled"
|
verb = "disabled"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure service exists
|
||||||
|
if stage != 0 {
|
||||||
|
if !serviceExists(service) {
|
||||||
|
if printJson {
|
||||||
|
fmt.Printf("{\"error\":\"Service (%s) does not exist\"}\n", verb)
|
||||||
|
} else {
|
||||||
|
fmt.Printf("Service (%s) does not exist\n", verb)
|
||||||
|
}
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Return if service is already enabled
|
// Return if service is already enabled
|
||||||
if _, enabledStage := isServiceEnabled(service); enabledStage == stage {
|
if _, enabledStage := isServiceEnabled(service); enabledStage == stage {
|
||||||
if printJson {
|
if printJson {
|
||||||
@@ -285,7 +313,7 @@ func showServiceStatus() {
|
|||||||
} else {
|
} else {
|
||||||
fmt.Printf("Enabled: %t\n", serviceEnabled)
|
fmt.Printf("Enabled: %t\n", serviceEnabled)
|
||||||
}
|
}
|
||||||
if serviceState == "running" {
|
if serviceState == "running" && processID > 0 {
|
||||||
fmt.Printf("Process ID: %d\n", processID)
|
fmt.Printf("Process ID: %d\n", processID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -319,12 +347,6 @@ func listAllServices() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print json data if flag is set
|
|
||||||
if printJson {
|
|
||||||
fmt.Println(string(data))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decoode JSON data
|
// Decoode JSON data
|
||||||
var returnedJsonData map[string]any
|
var returnedJsonData map[string]any
|
||||||
err = json.Unmarshal(data, &returnedJsonData)
|
err = json.Unmarshal(data, &returnedJsonData)
|
||||||
@@ -336,12 +358,24 @@ func listAllServices() {
|
|||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set is_enabled and stage fields in json data
|
||||||
|
for _, serviceMap := range returnedJsonData["services"].([]any) {
|
||||||
|
serviceMap.(map[string]any)["is_enabled"], serviceMap.(map[string]any)["stage"] = isServiceEnabled(serviceMap.(map[string]any)["name"].(string))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print json data if flag is set
|
||||||
|
if printJson {
|
||||||
|
data, _ = json.Marshal(returnedJsonData)
|
||||||
|
fmt.Println(string(data))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
for _, serviceMap := range returnedJsonData["services"].([]any) {
|
for _, serviceMap := range returnedJsonData["services"].([]any) {
|
||||||
serviceName := serviceMap.(map[string]any)["name"].(string)
|
serviceName := serviceMap.(map[string]any)["name"].(string)
|
||||||
serviceDescription := serviceMap.(map[string]any)["description"].(string)
|
serviceDescription := serviceMap.(map[string]any)["description"].(string)
|
||||||
serviceState := serviceMap.(map[string]any)["state"].(string)
|
serviceState := serviceMap.(map[string]any)["state"].(string)
|
||||||
serviceEnabled := serviceMap.(map[string]any)["is_enabled"].(bool)
|
serviceEnabled := serviceMap.(map[string]any)["is_enabled"].(bool)
|
||||||
serviceStage := int(serviceMap.(map[string]any)["stage"].(float64))
|
serviceStage := int(serviceMap.(map[string]any)["stage"].(int))
|
||||||
processID := int(serviceMap.(map[string]any)["process_id"].(float64))
|
processID := int(serviceMap.(map[string]any)["process_id"].(float64))
|
||||||
|
|
||||||
fmt.Printf("Name: %s\n", serviceName)
|
fmt.Printf("Name: %s\n", serviceName)
|
||||||
@@ -352,7 +386,7 @@ func listAllServices() {
|
|||||||
} else {
|
} else {
|
||||||
fmt.Printf("Enabled: %t\n", serviceEnabled)
|
fmt.Printf("Enabled: %t\n", serviceEnabled)
|
||||||
}
|
}
|
||||||
if serviceState == "running" {
|
if serviceState == "running" && processID > 0 {
|
||||||
fmt.Printf("Process ID: %d\n", processID)
|
fmt.Printf("Process ID: %d\n", processID)
|
||||||
}
|
}
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
@@ -438,20 +472,22 @@ func setupFlagsAndHelp(flagset *flag.FlagSet, usage, desc string, args []string)
|
|||||||
flagset.Parse(args)
|
flagset.Parse(args)
|
||||||
}
|
}
|
||||||
|
|
||||||
func dialSocket() {
|
func dialSocket() error {
|
||||||
if _, err := os.Stat(path.Join(runstatedir, "esvm/esvm.sock")); err != nil {
|
if _, err := os.Stat(path.Join(runstatedir, "esvm/esvm.sock")); err != nil {
|
||||||
log.Fatalf("Could not find esvm.sock! Error: %s\n", err)
|
return fmt.Errorf("could not find socket! Error: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
conn, err = net.Dial("unix", path.Join(runstatedir, "esvm/esvm.sock"))
|
conn, err = net.Dial("unix", path.Join(runstatedir, "esvm/esvm.sock"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Failed to connect to esvm.sock! Error: %s\n", err)
|
return fmt.Errorf("could not connect to socket! Error: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := conn.SetDeadline(time.Now().Add(30 * time.Second)); err != nil {
|
if err := conn.SetDeadline(time.Now().Add(30 * time.Second)); err != nil {
|
||||||
log.Fatalf("Failed to set write deadline! Error: %s\n", err)
|
return fmt.Errorf("failed to set socket deadline! Error: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func readAllConn(conn net.Conn) ([]byte, error) {
|
func readAllConn(conn net.Conn) ([]byte, error) {
|
||||||
|
|||||||
@@ -9,6 +9,30 @@ import (
|
|||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func serviceExists(service string) bool {
|
||||||
|
dirEntries, err := os.ReadDir(path.Join(sysconfdir, "esvm/services"))
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, entry := range dirEntries {
|
||||||
|
var dataMap map[string]any
|
||||||
|
|
||||||
|
data, err := os.ReadFile(path.Join(sysconfdir, "esvm/services", entry.Name()))
|
||||||
|
|
||||||
|
err = yaml.Unmarshal(data, &dataMap)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if name, ok := dataMap["name"]; ok && name == service {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
func isServiceEnabled(service string) (bool, int) {
|
func isServiceEnabled(service string) (bool, int) {
|
||||||
for stage, services := range readEnabledServices() {
|
for stage, services := range readEnabledServices() {
|
||||||
if slices.Contains(services, service) {
|
if slices.Contains(services, service) {
|
||||||
|
|||||||
@@ -0,0 +1,83 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os/exec"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type BlockDevice struct {
|
||||||
|
Device string
|
||||||
|
UUID string
|
||||||
|
PartUUID string
|
||||||
|
Label string
|
||||||
|
PartLabel string
|
||||||
|
Type string
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetBlockDevices() []BlockDevice {
|
||||||
|
cmd := exec.Command("/sbin/blkid")
|
||||||
|
out, err := cmd.Output()
|
||||||
|
if err != nil {
|
||||||
|
return make([]BlockDevice, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
blockDevices := make([]BlockDevice, 0)
|
||||||
|
|
||||||
|
for _, line := range strings.Split(string(out), "\n") {
|
||||||
|
line := strings.TrimSpace(line)
|
||||||
|
if len(line) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
lineSplit := strings.SplitN(line, ": ", 2)
|
||||||
|
if len(lineSplit) != 2 {
|
||||||
|
return make([]BlockDevice, 0)
|
||||||
|
}
|
||||||
|
device := lineSplit[0]
|
||||||
|
line = lineSplit[1]
|
||||||
|
|
||||||
|
fields := []string{}
|
||||||
|
sb := &strings.Builder{}
|
||||||
|
quoted := false
|
||||||
|
for _, r := range line {
|
||||||
|
if r == '"' {
|
||||||
|
quoted = !quoted
|
||||||
|
} else if !quoted && r == ' ' {
|
||||||
|
fields = append(fields, sb.String())
|
||||||
|
sb.Reset()
|
||||||
|
} else {
|
||||||
|
sb.WriteRune(r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if sb.Len() > 0 {
|
||||||
|
fields = append(fields, sb.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
bd := BlockDevice{Device: device}
|
||||||
|
|
||||||
|
for _, field := range fields {
|
||||||
|
fieldSplit := strings.SplitN(field, "=", 2)
|
||||||
|
if len(fieldSplit) != 2 {
|
||||||
|
return make([]BlockDevice, 0)
|
||||||
|
}
|
||||||
|
fieldName := fieldSplit[0]
|
||||||
|
fieldValue := fieldSplit[1]
|
||||||
|
|
||||||
|
switch fieldName {
|
||||||
|
case "UUID":
|
||||||
|
bd.UUID = fieldValue
|
||||||
|
case "PARTUUID":
|
||||||
|
bd.PartUUID = fieldValue
|
||||||
|
case "LABEL":
|
||||||
|
bd.Label = fieldValue
|
||||||
|
case "PARTLABEL":
|
||||||
|
bd.PartLabel = fieldValue
|
||||||
|
case "TYPE":
|
||||||
|
bd.Type = fieldValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
blockDevices = append(blockDevices, bd)
|
||||||
|
}
|
||||||
|
|
||||||
|
return blockDevices
|
||||||
|
}
|
||||||
+19
-2
@@ -51,6 +51,8 @@ func main() {
|
|||||||
mountVirtualFilesystems()
|
mountVirtualFilesystems()
|
||||||
// Mount filesystems in fstab
|
// Mount filesystems in fstab
|
||||||
mountFilesystems()
|
mountFilesystems()
|
||||||
|
// Run sysctl
|
||||||
|
initSysctl()
|
||||||
// Set hostname
|
// Set hostname
|
||||||
setHostname()
|
setHostname()
|
||||||
// Start service manager
|
// Start service manager
|
||||||
@@ -136,8 +138,6 @@ func startServiceManager() {
|
|||||||
fmt.Print("Initializing service manager... ")
|
fmt.Print("Initializing service manager... ")
|
||||||
|
|
||||||
cmd := exec.Command("/sbin/esvm", path.Join(runstatedir, "esvm"), path.Join(sysconfdir, "esvm"))
|
cmd := exec.Command("/sbin/esvm", path.Join(runstatedir, "esvm"), path.Join(sysconfdir, "esvm"))
|
||||||
cmd.Stdout = os.Stdout
|
|
||||||
cmd.Stderr = os.Stderr
|
|
||||||
err := cmd.Start()
|
err := cmd.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
printErrorAndReboot("Error: could not initialize service manager: %s", err)
|
printErrorAndReboot("Error: could not initialize service manager: %s", err)
|
||||||
@@ -222,6 +222,23 @@ func killProcesses() {
|
|||||||
fmt.Println("Done.")
|
fmt.Println("Done.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func initSysctl() {
|
||||||
|
// Return if sysctl cannot be found
|
||||||
|
if _, err := os.Stat("/sbin/sysctl"); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Print("Running sysctl...")
|
||||||
|
|
||||||
|
err := exec.Command("/sbin/sysctl", "--system").Run()
|
||||||
|
if err != nil {
|
||||||
|
log.Println("Failed!")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("Done.")
|
||||||
|
}
|
||||||
|
|
||||||
func setHostname() {
|
func setHostname() {
|
||||||
fmt.Print("Setting hostname... ")
|
fmt.Print("Setting hostname... ")
|
||||||
|
|
||||||
|
|||||||
+65
-11
@@ -158,23 +158,77 @@ func mountFstabEntries() (error, int) {
|
|||||||
fstype := fields[2]
|
fstype := fields[2]
|
||||||
options := fields[3]
|
options := fields[3]
|
||||||
|
|
||||||
// Replace device prefixes
|
// Convert mount options
|
||||||
if cutSource, ok := strings.CutPrefix(source, "LABEL="); ok {
|
|
||||||
source = "/dev/disk/by-label/" + strings.ReplaceAll(cutSource, " ", "\\x20")
|
|
||||||
} else if cutSource, ok := strings.CutPrefix(source, "UUID="); ok {
|
|
||||||
source = "/dev/disk/by-uuid/" + cutSource
|
|
||||||
} else if cutSource, ok := strings.CutPrefix(source, "PARTLABEL="); ok {
|
|
||||||
source = "/dev/disk/by-partlabel/" + cutSource
|
|
||||||
} else if cutSource, ok := strings.CutPrefix(source, "PARTUUID="); ok {
|
|
||||||
source = "/dev/disk/by-partuuid/" + cutSource
|
|
||||||
}
|
|
||||||
|
|
||||||
flags, data, extra := convertMountOptions(options)
|
flags, data, extra := convertMountOptions(options)
|
||||||
|
|
||||||
|
// Skip if noauto flag is set
|
||||||
if slices.Contains(extra, "noauto") {
|
if slices.Contains(extra, "noauto") {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get block devices
|
||||||
|
blockDevices := GetBlockDevices()
|
||||||
|
|
||||||
|
// Replace device prefixes
|
||||||
|
if strings.Contains(source, "=") {
|
||||||
|
fieldSplit := strings.SplitN(source, "=", 2)
|
||||||
|
if len(fieldSplit) != 2 {
|
||||||
|
if slices.Contains(extra, "nofail") {
|
||||||
|
fmt.Printf("Warning: could not mount fstab entry on line %d: Formatting error\n", i+1)
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
return fmt.Errorf("Formatting error"), i + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldName := fieldSplit[0]
|
||||||
|
fieldValue := fieldSplit[1]
|
||||||
|
|
||||||
|
// Reset source field
|
||||||
|
source = ""
|
||||||
|
|
||||||
|
for _, bd := range blockDevices {
|
||||||
|
bdField := ""
|
||||||
|
|
||||||
|
switch fieldName {
|
||||||
|
case "LABEL":
|
||||||
|
bdField = bd.Label
|
||||||
|
case "UUID":
|
||||||
|
bdField = bd.UUID
|
||||||
|
case "PARTLABEL":
|
||||||
|
bdField = bd.PartLabel
|
||||||
|
case "PARTUUID":
|
||||||
|
bdField = bd.PartUUID
|
||||||
|
default:
|
||||||
|
if slices.Contains(extra, "nofail") {
|
||||||
|
fmt.Printf("Warning: could not mount fstab entry on line %d: Formatting error\n", i+1)
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
return fmt.Errorf("Formatting error"), i + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if bdField == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if bdField == fieldValue {
|
||||||
|
source = bd.Device
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure source was set
|
||||||
|
if source == "" {
|
||||||
|
if slices.Contains(extra, "nofail") {
|
||||||
|
fmt.Printf("Warning: could not mount fstab entry on line %d: could not resolve %s=\"%s\"\n", i+1, fieldName, fieldValue)
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
return fmt.Errorf("could not resolve %s=\"%s\"", fieldName, fieldValue), i + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if fstype == "swap" {
|
if fstype == "swap" {
|
||||||
b := append([]byte(source), 0)
|
b := append([]byte(source), 0)
|
||||||
const SwapFlagPrioShift = 0
|
const SwapFlagPrioShift = 0
|
||||||
|
|||||||
@@ -326,6 +326,12 @@ func (service *EnitService) StartService() (err error) {
|
|||||||
|
|
||||||
service.state = EnitServiceRunning
|
service.state = EnitServiceRunning
|
||||||
|
|
||||||
|
// Set PID to 0 for simple services with a stop command
|
||||||
|
if service.Type == "simple" && service.StopCmd != "" {
|
||||||
|
pid = 0
|
||||||
|
service.processID = 0
|
||||||
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
err := cmd.Wait()
|
err := cmd.Wait()
|
||||||
|
|
||||||
@@ -339,7 +345,9 @@ func (service *EnitService) StartService() (err error) {
|
|||||||
service.restartCount = 0
|
service.restartCount = 0
|
||||||
default:
|
default:
|
||||||
// Kill remaining child processes
|
// Kill remaining child processes
|
||||||
|
if pid != 0 {
|
||||||
syscall.Kill(-pid, syscall.SIGKILL)
|
syscall.Kill(-pid, syscall.SIGKILL)
|
||||||
|
}
|
||||||
|
|
||||||
if service.Type == "simple" && err == nil {
|
if service.Type == "simple" && err == nil {
|
||||||
service.restartCount = 0
|
service.restartCount = 0
|
||||||
|
|||||||
Reference in New Issue
Block a user