118 lines
3.9 KiB
Bash
Executable File
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
|