diff options
| author | Robert Günzler <r@gnzler.io> | 2025-09-22 18:36:58 +0200 |
|---|---|---|
| committer | Robert Günzler <r@gnzler.io> | 2025-09-22 19:53:54 +0200 |
| commit | 78e1a5e6df2cbd4e4dafb15d18345ab94825e317 (patch) | |
| tree | f2213bfd48209db2741f04de211cef48b73bae97 | |
initial commit
Signed-off-by: Robert Günzler <r@gnzler.io>
| -rwxr-xr-x | bin/sv | 117 | ||||
| -rwxr-xr-x | bin/svtree-init | 8 | ||||
| -rwxr-xr-x | bin/svtree-run | 50 | ||||
| -rw-r--r-- | dirs.conf | 6 | ||||
| -rwxr-xr-x | run-image/service/.s6-svscan/SIGTERM | 3 | ||||
| -rw-r--r-- | run-image/service/s6-svscan-log/notification-fd | 1 | ||||
| -rwxr-xr-x | run-image/service/s6-svscan-log/run | 8 |
7 files changed, 193 insertions, 0 deletions
diff --git a/bin/sv b/bin/sv new file mode 100755 index 0000000..2f2bcf2 --- /dev/null +++ b/bin/sv @@ -0,0 +1,117 @@ +#!/bin/sh +set -eu +[ -n "${DEBUG:-}" ] && set -x + +SYS_RT=/run +USER_RT=$XDG_RUNTIME_DIR + +main() +{ + # NOTE: this assumes that: + # system services have their live dir at /run/s6-rc + # user services have their live dir at $XDG_RUNTIME_DIR/s6-rc + local rt=$SYS_RT + [ "${1:-}" = "-u" ] && rt=$USER_RT && shift + [ "${UID:-$(id -u)}" -ne 0 ] && rt=$USER_RT + local l=$rt/s6-rc + + # NOTE: this assumes that: + # $l/compiled is a symlink to a directory inside the confdir + # which contains a directory src, defining the s6-rc source + local confdir + confdir=$(readlink -e "$l/compiled") + confdir=$(dirname "$confdir") + test -d "$confdir/src" + + local cmd=${1:-} + shift + + case "$cmd" in + ## + ## db + ## + reload|recompile) + export LIVEDIR="$l" + export STATEDIR="$confdir" + export SRCDIR="$confdir/src" + exec s6-rc-recompile + ;; + + ## + ## service + ## + up|start) + exec s6-rc -v2 -l "$l" -b start $@ + ;; + + dn|down|stop) + exec s6-rc -v2 -l "$l" -b stop $@ + ;; + + re|restart) + $0 dn $@ && $0 up $@ + ;; + + st|status|info) + local sv=${1:?} + s6-rc-db -l "$l" type $sv >/dev/null 2>&1 || exit 1 + + printf 'Service (%s):\n' $(s6-rc-db -l "$l" type $sv) + for ln in $(s6-rc-db -l "$l" atomics $sv) + do + printf '%s: ' $ln + s6-svstat "$l/servicedirs/$ln" + done | sort -k 2 | column -s ':' -t + + printf '\nDependencies:\n' + s6-rc-db -l "$l" dependencies $sv + + # NOTE: this assumes logs are stored in $rt/log + logfile="$rt/log/$sv/current" + if test -f "$logfile"; then + printf '\nLogs (%s):\n' "$logfile" + tail -n 10 "$logfile" + fi + ;; + + logtail|logs) + local sv=${1:?} + # NOTE: this assumes logs are stored in $rt/log + logfile="$rt/log/$sv/current" + if test -f "$logfile"; then + tail -f "$logfile" + fi + ;; + + ## + ## bundles + ## + bundle-ls) + find "$confdir/src" -mindepth 1 -maxdepth 1 -exec sh -c 'test "$(cat {}/type)" = "bundle" && basename {}' \; + ;; + + bundle-add) + # TODO: add confirmation? + local sv=${1:?} + local bundle=${2:?} + touch "$confdir/src/$bundle/contents.d/$sv" + ;; + bundle-del) + # TODO: add confirmation? + local sv=${1:?} + local bundle=${2:?} + rm "$confdir/src/$bundle/contents.d/$sv" + ;; + + ## + ## listall + ## + ls|list|ps|*) + [ "${1:-}" = "-a" ] && exec s6-rc-db -l "$l" list services + exec s6-rc -v2 -l "$l" -a list + ;; + + esac +} + +main $@ diff --git a/bin/svtree-init b/bin/svtree-init new file mode 100755 index 0000000..65d3fa2 --- /dev/null +++ b/bin/svtree-init @@ -0,0 +1,8 @@ +#!/bin/execlineb -P + +importas -iS HOME +importas -iS XDG_RUNTIME_DIR + +envfile -I ../dirs.conf + +exec s6-rc-recompile diff --git a/bin/svtree-run b/bin/svtree-run new file mode 100755 index 0000000..b5121cc --- /dev/null +++ b/bin/svtree-run @@ -0,0 +1,50 @@ +#!/bin/execlineb -P + +importas -iS HOME +importas -iS XDG_RUNTIME_DIR + +envfile -I ../dirs.conf + +# compiled (setup by init script) +if { eltest -e ${COMPILED_DIR} } + +# TODO: cgroup support +#define CG /sys/fs/cgroup/usr +#if { test -d ${CG} } +#if { test -w ${CG}/cgroup.procs } + +# nuke any other svscan process +foreground { s6-svscanctl -qN ${SCAN_DIR} } +foreground { s6-svwait -D ${SCAN_DIR}/s6rc-fdholder } + +# cleanup +foreground { rm -rf ${SCAN_DIR} } +foreground { elglob l ${LIVE_DIR}* rm -rf ${l} } + +# setup rundir +if { cp -va -- ${CONF_DIR}/run-image/service ${SCAN_DIR} } + +background { + # catch-all logger + fdmove -c 4 2 + redirfd -wnb 2 ${SCAN_DIR}/s6-svscan-log/fifo + fdmove -c 1 2 + + # TODO: why do we need this? + execline-cd ${HOME} + + # run s6 + s6-svscan ${SCAN_DIR} +} + +# setup s6-rc +foreground { s6-rc-init -c ${COMPILED_DIR} -l ${LIVE_DIR} -d -- ${SCAN_DIR} } + +# launch default target +foreground { s6-rc -v2 -l ${LIVE_DIR} -pu change default } + +# block on s6 +importas -i scanpid ! +wait -i { ${scanpid} } + +exit 0 diff --git a/dirs.conf b/dirs.conf new file mode 100644 index 0000000..8f5894d --- /dev/null +++ b/dirs.conf @@ -0,0 +1,6 @@ +STATE_DIR=/etc/s6-rc" # "${XDG_CONFIG_HOME}/s6-rc" +LIVE_DIR=/run/s6-rc # "${XDG_RUNTIME_DIR}/s6-rc" +SCAN_DIR=/run/service # "${XDG_RUNTIME_DIR}/service" + +SOURCE_DIR="${STATEDIR}/src" +COMPILED_DIR="${STATEDIR}/compiled" diff --git a/run-image/service/.s6-svscan/SIGTERM b/run-image/service/.s6-svscan/SIGTERM new file mode 100755 index 0000000..21a3d4c --- /dev/null +++ b/run-image/service/.s6-svscan/SIGTERM @@ -0,0 +1,3 @@ +#!/bin/execlineb -P +foreground { s6-rc -bDa } +s6-svscanctl -t . diff --git a/run-image/service/s6-svscan-log/notification-fd b/run-image/service/s6-svscan-log/notification-fd new file mode 100644 index 0000000..00750ed --- /dev/null +++ b/run-image/service/s6-svscan-log/notification-fd @@ -0,0 +1 @@ +3 diff --git a/run-image/service/s6-svscan-log/run b/run-image/service/s6-svscan-log/run new file mode 100755 index 0000000..e780032 --- /dev/null +++ b/run-image/service/s6-svscan-log/run @@ -0,0 +1,8 @@ +#!/bin/execlineb -P + +importas -SuD "n2 s2000000 T" LOG_DIRECTIVES + +fdmove -c 1 2 +redirfd -rnb 0 fifo +if { install -d /run/user/1000/uncaught-logs } +s6-log -d3 -bp -- ${LOG_DIRECTIVES} /run/user/1000/uncaught-logs |