Compare commits
3 Commits
3cc35fa7ff
...
74868ab2d3
Author | SHA1 | Date | |
---|---|---|---|
74868ab2d3 | |||
4b37214113 | |||
ce34b7b21a |
@ -2,7 +2,4 @@ module ectl
|
||||
|
||||
go 1.23.4
|
||||
|
||||
require (
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
rsc.io/getopt v0.0.0-20170811000552-20be20937449 // indirect
|
||||
)
|
||||
require gopkg.in/yaml.v3 v3.0.1
|
||||
|
@ -1,5 +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/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
rsc.io/getopt v0.0.0-20170811000552-20be20937449 h1:UukjJOsjQH0DIuyyrcod6CXHS6cdaMMuJmrt+SN1j4A=
|
||||
rsc.io/getopt v0.0.0-20170811000552-20be20937449/go.mod h1:dhCdeqAxkyt5u3/sKRkUXuHaMXUu1Pt13GTQAM2xnig=
|
||||
|
@ -59,7 +59,28 @@ func main() {
|
||||
fmt.Println("Usage: ectl service <start/stop/enable/disable/status/list> [service]")
|
||||
return
|
||||
} else if flag.Args()[1] == "list" {
|
||||
fmt.Println("list")
|
||||
if _, err := os.Stat(path.Join(runstatedir, "esvm")); err != nil {
|
||||
log.Fatalf("Could not list services! Error: %s\n", err)
|
||||
}
|
||||
|
||||
entries, err := os.ReadDir(path.Join(runstatedir, "esvm"))
|
||||
if err != nil {
|
||||
log.Fatalf("Could not list services! Error: %s\n", err)
|
||||
}
|
||||
|
||||
for _, entry := range entries {
|
||||
if !entry.IsDir() {
|
||||
continue
|
||||
}
|
||||
|
||||
state := getServiceState(entry.Name())
|
||||
enabled := strconv.FormatBool(isServiceEnabled(entry.Name()))
|
||||
enabled = strings.ToUpper(enabled[:1]) + strings.ToLower(enabled[1:])
|
||||
|
||||
fmt.Println("Service name: " + entry.Name())
|
||||
fmt.Printf(" State: %s\n", state)
|
||||
fmt.Printf(" Enabled: %s\n", enabled)
|
||||
}
|
||||
return
|
||||
} else if len(flag.Args()) <= 2 {
|
||||
fmt.Printf("Usage: ectl service %s <service>\n", flag.Args()[1])
|
||||
@ -226,26 +247,13 @@ func main() {
|
||||
log.Fatalf("Could not get service status! Error: %s\n", err)
|
||||
}
|
||||
|
||||
var state uint64
|
||||
bytes, err := os.ReadFile(path.Join(runstatedir, "esvm", flag.Args()[2], "state"))
|
||||
if err != nil {
|
||||
state = 0
|
||||
}
|
||||
state, err = strconv.ParseUint(string(bytes), 10, 8)
|
||||
state := getServiceState(flag.Args()[2])
|
||||
enabled := strconv.FormatBool(isServiceEnabled(flag.Args()[2]))
|
||||
enabled = strings.ToUpper(enabled[:1]) + strings.ToLower(enabled[1:])
|
||||
|
||||
fmt.Println("Service name: " + flag.Args()[2])
|
||||
switch state {
|
||||
case 0:
|
||||
fmt.Println("Service state: Unknown")
|
||||
case 1:
|
||||
fmt.Println("Service state: Unloaded")
|
||||
case 2:
|
||||
fmt.Println("Service state: Running")
|
||||
case 3:
|
||||
fmt.Println("Service state: Stopped")
|
||||
case 4:
|
||||
fmt.Println("Service state: Crashed")
|
||||
}
|
||||
fmt.Printf(" State: %s\n", state)
|
||||
fmt.Printf(" Enabled: %s\n", enabled)
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -254,6 +262,53 @@ func main() {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
func getServiceState(serviceName string) string {
|
||||
if _, err := os.Stat(path.Join(runstatedir, "esvm", serviceName)); err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
var state uint64
|
||||
bytes, err := os.ReadFile(path.Join(runstatedir, "esvm", serviceName, "state"))
|
||||
if err != nil {
|
||||
state = 0
|
||||
}
|
||||
state, err = strconv.ParseUint(string(bytes), 10, 8)
|
||||
|
||||
switch state {
|
||||
case 1:
|
||||
return "Unloaded"
|
||||
case 2:
|
||||
return "Running"
|
||||
case 3:
|
||||
return "Stopped"
|
||||
case 4:
|
||||
return "Crashed"
|
||||
case 5:
|
||||
return "Completed"
|
||||
default:
|
||||
return "Unknown"
|
||||
}
|
||||
}
|
||||
|
||||
func isServiceEnabled(serviceName string) bool {
|
||||
if _, err := os.Stat(path.Join(sysconfdir, "esvm/enabled_services")); err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
file, err := os.ReadFile(path.Join(sysconfdir, "esvm/enabled_services"))
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
for _, line := range strings.Split(string(file), "\n") {
|
||||
if strings.TrimSpace(line) == serviceName {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func printUsage() {
|
||||
fmt.Println("Available sucommands:")
|
||||
fmt.Println("ectl version | Show enit version")
|
||||
|
@ -1,3 +1,5 @@
|
||||
module enit
|
||||
|
||||
go 1.23.4
|
||||
go 1.23.4
|
||||
|
||||
require golang.org/x/sys v0.31.0
|
||||
|
@ -1,4 +1,2 @@
|
||||
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/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
|
||||
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
|
@ -1,7 +1,6 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
@ -75,43 +74,45 @@ func setProcessName() error {
|
||||
func mountVirtualFilesystems() {
|
||||
fmt.Print("Mounting virtual filesystems... ")
|
||||
|
||||
commonFlags := uintptr(0 | syscall.MS_NOSUID | syscall.MS_RELATIME)
|
||||
commonOptions := "rw,nosuid,relatime"
|
||||
|
||||
// Mount /proc
|
||||
if err := syscall.Mount("proc", "/proc", "proc", commonFlags|syscall.MS_NODEV|syscall.MS_NOEXEC|syscall.MS_REMOUNT, ""); err != nil {
|
||||
if err := mount("proc", "/proc", "proc", commonOptions+",nodev,noexec", false); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Mount /sys
|
||||
if err := syscall.Mount("sys", "/sys", "sysfs", commonFlags|syscall.MS_NODEV|syscall.MS_NOEXEC|syscall.MS_REMOUNT, ""); err != nil {
|
||||
if err := mount("sys", "/sys", "sysfs", commonOptions+",nodev,noexec", false); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Mount /dev
|
||||
if err := syscall.Mount("dev", "/dev", "devtmpfs", commonFlags|syscall.MS_REMOUNT, "mode=755,inode64"); err != nil {
|
||||
if err := mount("dev", "/dev", "devtmpfs", commonOptions+",mode=755,inode64", false); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Mount /run
|
||||
if err := syscall.Mount("run", "/run", "tmpfs", commonFlags|syscall.MS_NODEV|syscall.MS_REMOUNT, "mode=755,inode64"); err != nil {
|
||||
if err := mount("run", "/run", "tmpfs", commonOptions+",nodev,mode=755,inode64", false); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Mount /dev/pts
|
||||
if err := os.Mkdir("/dev/pts", 0755); err != nil && !errors.Is(err, os.ErrExist) {
|
||||
panic(err)
|
||||
}
|
||||
if err := syscall.Mount("devpts", "/dev/pts", "devpts", commonFlags, "gid=5,mode=620,ptmxmode=000"); err != nil {
|
||||
if err := mount("devpts", "/dev/pts", "devpts", commonOptions+",gid=5,mode=620,ptmxmode=000", true); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Mount /dev/shm
|
||||
if err := os.Mkdir("/dev/shm", 0755); err != nil && !errors.Is(err, os.ErrExist) {
|
||||
panic(err)
|
||||
}
|
||||
if err := syscall.Mount("shm", "/dev/shm", "tmpfs", commonFlags|syscall.MS_NODEV, "inode64"); err != nil {
|
||||
if err := mount("shm", "/dev/shm", "tmpfs", commonOptions+",nodev,inode64", true); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Mount securityfs
|
||||
if err := syscall.Mount("securityfs", "/sys/kernel/security", "securityfs", commonFlags, ""); err != nil {
|
||||
if err := mount("securityfs", "/sys/kernel/security", "securityfs", commonOptions, false); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Mount cgroups v2
|
||||
if err := syscall.Mount("cgroup2", "/sys/fs/cgroup", "cgroup2", commonFlags|syscall.MS_NOEXEC, ""); err != nil {
|
||||
if err := mount("cgroup2", "/sys/fs/cgroup", "cgroup2", commonOptions+",noexec,nsdelegate,memory_recursiveprot", false); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
@ -119,12 +120,9 @@ func mountVirtualFilesystems() {
|
||||
}
|
||||
|
||||
func mountFilesystems() {
|
||||
fmt.Print("Mounting filesystems... ")
|
||||
fmt.Print("Mounting fstab entries... ")
|
||||
|
||||
cmd := exec.Command("/bin/mount", "-a")
|
||||
err := cmd.Run()
|
||||
|
||||
if err != nil {
|
||||
if err := mountFstabEntries(); err != nil {
|
||||
log.Println("Could not mount fstab entries!")
|
||||
panic(err)
|
||||
}
|
||||
|
141
cmd/enit/mount.go
Normal file
141
cmd/enit/mount.go
Normal file
@ -0,0 +1,141 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/unix"
|
||||
"os"
|
||||
"slices"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var flagsEquivalence = map[string]uintptr{
|
||||
"dirsync": unix.MS_DIRSYNC,
|
||||
"lazytime": unix.MS_LAZYTIME,
|
||||
"noatime": unix.MS_NOATIME,
|
||||
"nodev": unix.MS_NODEV,
|
||||
"nodiratime": unix.MS_NODIRATIME,
|
||||
"noexec": unix.MS_NOEXEC,
|
||||
"nosuid": unix.MS_NOSUID,
|
||||
"ro": unix.MS_RDONLY,
|
||||
"rw": 0,
|
||||
"relatime": unix.MS_RELATIME,
|
||||
"silent": unix.MS_SILENT,
|
||||
"strictatime": unix.MS_STRICTATIME,
|
||||
"sync": unix.MS_SYNCHRONOUS,
|
||||
"defaults": 0,
|
||||
}
|
||||
|
||||
// Split string flags to mount flags and mount data
|
||||
func convertMountOptions(options string) (flags []uintptr, data string) {
|
||||
for _, flag := range strings.Split(options, ",") {
|
||||
if unixFlag, ok := flagsEquivalence[flag]; ok {
|
||||
flags = append(flags, unixFlag)
|
||||
} else {
|
||||
if data == "" {
|
||||
data = flag
|
||||
} else {
|
||||
data += "," + flag
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return flags, data
|
||||
}
|
||||
|
||||
// Combine a unix flag slice or array into a single uintptr
|
||||
func combineUnixFlags(flagsSlice []uintptr) (flags uintptr) {
|
||||
flags = 0
|
||||
for _, flag := range flagsSlice {
|
||||
flags |= flag
|
||||
}
|
||||
|
||||
return flags
|
||||
}
|
||||
|
||||
// Check whether a certain path is a mountpoint
|
||||
func isMountpoint(mountpoint string) bool {
|
||||
if mountpoint != "/" {
|
||||
mountpoint = strings.TrimRight(mountpoint, "/")
|
||||
}
|
||||
|
||||
if _, err := os.Stat("/proc/mounts"); err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
bytes, err := os.ReadFile("/proc/mounts")
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
for _, line := range strings.Split(string(bytes), "\n") {
|
||||
line = strings.TrimSpace(line)
|
||||
if line == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
if strings.Split(line, " ")[1] == mountpoint {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func mount(source, target, fstype string, options string, mkdir bool) error {
|
||||
flags, data := convertMountOptions(options)
|
||||
|
||||
if isMountpoint(target) && !slices.Contains(flags, unix.MS_REMOUNT) {
|
||||
flags = append(flags, unix.MS_REMOUNT)
|
||||
}
|
||||
|
||||
if mkdir {
|
||||
err := os.MkdirAll(target, 0755)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := unix.Mount(source, target, fstype, combineUnixFlags(flags), data); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func mountFstabEntries() error {
|
||||
if _, err := os.Stat("/etc/fstab"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
bytes, err := os.ReadFile("/etc/fstab")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, line := range strings.Split(string(bytes), "\n") {
|
||||
line = strings.TrimSpace(line)
|
||||
if strings.HasPrefix(line, "#") || line == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
source := strings.Split(line, " ")[0]
|
||||
target := strings.Split(line, " ")[1]
|
||||
fstype := strings.Split(line, " ")[2]
|
||||
options := strings.Split(line, " ")[3]
|
||||
|
||||
flags, data := convertMountOptions(options)
|
||||
|
||||
if slices.Contains(strings.Split(data, ","), "noauto") {
|
||||
continue
|
||||
}
|
||||
|
||||
if isMountpoint(target) && !slices.Contains(flags, unix.MS_REMOUNT) {
|
||||
flags = append(flags, unix.MS_REMOUNT)
|
||||
}
|
||||
|
||||
if err := unix.Mount(source, target, fstype, combineUnixFlags(flags), data); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user