This repository has been archived on 2026-06-13. You can view files and clone it, but cannot push or open issues or pull requests.
anvillm/services/sysvinit/rc.anvillm

118 lines
3.9 KiB
Bash
Executable File

#!/bin/sh
# /etc/rc.d/rc.anvillm
#
# Start/stop/restart the AnviLLM backend server (anvillm).
#
# anvillm exposes a 9P filesystem (anvillm/) used by Claude Code sessions and
# bots for session management, mailbox communication, beads task tracking, and
# the event bus.
#
# This script follows Slackware rc conventions:
# - Enable service: chmod 755 /etc/rc.d/rc.anvillm
# - Disable service: chmod 644 /etc/rc.d/rc.anvillm
#
# To start automatically at boot, add to /etc/rc.d/rc.local:
# if [ -x /etc/rc.d/rc.anvillm ]; then
# /etc/rc.d/rc.anvillm start
# fi
#
# To stop cleanly at shutdown, add to /etc/rc.d/rc.local_shutdown:
# if [ -x /etc/rc.d/rc.anvillm ]; then
# /etc/rc.d/rc.anvillm stop
# fi
#
# ── configuration ─────────────────────────────────────────────────────────────
#
# ANVILSRV_USER Login name of the user whose AnviLLM instance to manage.
# The anvillm binary is expected at ~/bin/anvillm.
#
# NAMESPACE 9P namespace directory. Defaults to /tmp/ns.$ANVILSRV_USER
# matching the Plan 9 client.Namespace() convention used by
# anvillm. The PID file lives at $NAMESPACE/anvillm.pid.
#
ANVILSRV_USER="${ANVILSRV_USER:-}"
NAMESPACE="${NAMESPACE:-}"
# ── resolve derived paths ─────────────────────────────────────────────────────
if [ -z "$NAMESPACE" ] && [ -n "$ANVILSRV_USER" ]; then
NAMESPACE="/tmp/ns.${ANVILSRV_USER}"
fi
DAEMON="/home/${ANVILSRV_USER}/bin/anvillm"
# ── helpers ───────────────────────────────────────────────────────────────────
anvillm_env() {
# Print the environment preamble used in every su invocation.
printf "export NAMESPACE='%s'; export HOME='/home/%s'; export PATH='/home/%s/bin:/usr/local/bin:/usr/bin:/bin'" \
"$NAMESPACE" "$ANVILSRV_USER" "$ANVILSRV_USER"
}
check_config() {
if [ -z "$ANVILSRV_USER" ]; then
echo "rc.anvillm: ANVILSRV_USER is not set — edit this script or set the variable." >&2
return 1
fi
if [ ! -x "$DAEMON" ]; then
echo "rc.anvillm: ${DAEMON} not found or not executable." >&2
return 1
fi
return 0
}
anvillm_start() {
check_config || return
echo "Starting anvillm (user=${ANVILSRV_USER}, namespace=${NAMESPACE})..."
mkdir -p "$NAMESPACE"
chown "$ANVILSRV_USER" "$NAMESPACE" 2>/dev/null
# anvillm start daemonizes itself and writes its own PID file at
# $NAMESPACE/anvillm.pid. It also detects if it is already running and
# exits with an error in that case — no extra guard needed here.
su -s /bin/sh -l "$ANVILSRV_USER" -c "$(anvillm_env); '${DAEMON}' start"
}
anvillm_stop() {
check_config || return
echo "Stopping anvillm (user=${ANVILSRV_USER})..."
su -s /bin/sh -l "$ANVILSRV_USER" -c "$(anvillm_env); '${DAEMON}' stop"
# Remove the 9P socket left behind by anvillm.
rm -f "${NAMESPACE}/agent" 2>/dev/null
}
anvillm_restart() {
anvillm_stop
sleep 1
anvillm_start
}
anvillm_status() {
check_config || return
su -s /bin/sh -l "$ANVILSRV_USER" -c "$(anvillm_env); '${DAEMON}' status"
}
# ── dispatch ──────────────────────────────────────────────────────────────────
case "$1" in
start)
anvillm_start
;;
stop)
anvillm_stop
;;
restart)
anvillm_restart
;;
status)
anvillm_status
;;
*)
echo "Usage: $0 {start|stop|restart|status}"
;;
esac