Skip to content

Commit

Permalink
feat: daemon installer
Browse files Browse the repository at this point in the history
  • Loading branch information
ahmetozer committed Jun 27, 2024
1 parent 59f0f21 commit 9d285a7
Show file tree
Hide file tree
Showing 2 changed files with 142 additions and 1 deletion.
4 changes: 3 additions & 1 deletion Readme.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Sandal

Sandal is a basic, deamonless container system for Linux-embedded systems.
Sandal is a basic, lightweight container system for Linux-embedded systems.

This project aims to have a container system which light weight and respects systems disk usage.
It utilizes the squashfs filesystem as a container image, so you can execute the container directly from the file, and easy to distribute it with portable media.
Expand Down Expand Up @@ -162,6 +162,8 @@ sandal cmd minecraft

Run all startup containers and watch in case of hang errors.

To enable systemd or runit, you can use `sandal daemon -install`.

```bash
sandal daemon
2024/06/27 03:09:37 INFO daemon started
Expand Down
139 changes: 139 additions & 0 deletions pkg/cmd/daemon.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package cmd

import (
"errors"
"flag"
"fmt"
"log/slog"
"os"
Expand All @@ -13,6 +15,21 @@ import (

func deamon(args []string) error {

var (
install bool
help bool
)
flags := flag.NewFlagSet("deamon", flag.ExitOnError)

flags.BoolVar(&install, "install", false, "install service files under /etc/init.d/sandal and /etc/systemd/system/sandal.service")
flags.BoolVar(&help, "help", false, "show this help message")

flags.Parse(args)

if install {
return installServices()
}

updateContainers := make(chan bool, 1)

conts, _ := config.AllContainers()
Expand All @@ -35,6 +52,10 @@ func deamon(args []string) error {
}()

slog.Info("daemon started")
if _, err := os.Stat("/etc/init.d/sandal"); err != nil {
slog.Info(`You can enable sandal deamon at startup with "sandal daemon -install" command.` +
`It will install service files for systemd and runit`)
}
for {
for _, cont := range conts {
// oldContPid := cont.ContPid
Expand Down Expand Up @@ -100,3 +121,121 @@ func deamon(args []string) error {

// return nil
}

const initdSandal = `#!/bin/sh
### BEGIN INIT INFO
# Provides: sandal
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop:
# Short-Description: Sandal daemon
### END INIT INFO
set -e
# /etc/init.d/sandal: start and stop the Sandal daemon
umask 022
. /lib/lsb/init-functions
export PATH="${PATH:+$PATH:}/usr/sbin:/sbin"
SANDAL_OPTS="daemon"
case "$1" in
start)
log_daemon_msg "Starting Sandal" "sandal" || true
# shellcheck disable=SC2086
if start-stop-daemon --start --quiet --background -m --oknodo --chuid 0:0 --pidfile /run/sandal.pid --exec /bin/sandal -- $SANDAL_OPTS; then
log_end_msg 0 || true
else
log_end_msg 1 || true
fi
;;
stop)
log_daemon_msg "Stopping Sandal" "sandal" || true
if start-stop-daemon --stop --quiet --oknodo --pidfile /run/sandal.pid --exec /bin/sandal; then
log_end_msg 0 || true
else
log_end_msg 1 || true
fi
;;
restart)
log_daemon_msg "Restarting Sandal" "sandal" || true
start-stop-daemon --stop --background -m --quiet --oknodo --retry 30 --pidfile /run/sandal.pid --exec /bin/sandal
# shellcheck disable=SC2086
if start-stop-daemon --start --quiet --oknodo --chuid 0:0 --pidfile /run/sandal.pid --exec /bin/sandal -- $SANDAL_OPTS; then
log_end_msg 0 || true
else
log_end_msg 1 || true
fi
;;
status)
status_of_proc -p /run/sandal.pid /bin/sandal sandal && exit 0 || exit $?
;;
*)
log_action_msg "Usage: /etc/init.d/sandal {start|stop|restart|status}" || true
exit 1
esac
exit 0`

const systemdSandalService = `
[Unit]
Description=sandal daemon
After=network.target local-fs.target remote-fs.target
[Service]
User=root
RuntimeDirectory=sandal
LogsDirectory=sandal
StateDirectory=sandal
ExecStart=/usr/bin/sandal daemon
Restart=on-abort
[Install]
WantedBy=multi-user.target`

func installServices() error {

var errs []error
slog.Info("creating /etc/init.d/sandal")
err := os.WriteFile("/etc/init.d/sandal", []byte(initdSandal), 0755)
if err == nil {
os.Chmod("/etc/init.d/sandal", 0755) // os.write does not set permission for existing file
slog.Info("enabling service /etc/init.d/sandal -> /etc/rc2.d/S01sandal")
err = os.Symlink("/etc/init.d/sandal", "/etc/rc2.d/S01sandal")
if err != nil {
errs = append(errs, err)
}
} else {
errs = append(errs, err)
}

slog.Info("creating /etc/systemd/system/sandal.service")
err = os.WriteFile("/etc/systemd/system/sandal.service", []byte(systemdSandalService), 0755)
if err == nil {
os.Chmod("/etc/systemd/system/sandal.service", 0755) // os.write does not set permission for existing file
slog.Info("enabling /etc/systemd/system/sandal.service")
cmd := exec.Command("systemctl", "enable", "sandal.service")
cmd.Stderr = os.Stderr
cmd.Stdout = os.Stdout
err = cmd.Start()
if err != nil {
errs = append(errs, err)
}
} else {
errs = append(errs, err)
}

return errors.Join(errs...)

}

0 comments on commit 9d285a7

Please sign in to comment.