Compare commits
1 Commits
step35/443
...
step35/429
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f85c6d2252 |
153
wizards/bezalel/emacs-daemon-start.sh
Executable file
153
wizards/bezalel/emacs-daemon-start.sh
Executable file
@@ -0,0 +1,153 @@
|
||||
#!/usr/bin/env bash
|
||||
# emacs-daemon-start.sh — Start Emacs daemon with fixed socket, per-user identity, and audit trail
|
||||
#
|
||||
# This script fixes the daemon socket location (preventing conflicts), ensures
|
||||
# per-user identity through socket path isolation, and provides full audit logging.
|
||||
#
|
||||
# Used by: @reboot cron entry on Bezalel VPS
|
||||
# @reboot /root/wizards/bezalel/emacs-daemon-start.sh
|
||||
#
|
||||
# Socket location: $EMACS_SOCKET_PATH
|
||||
# → Each Hermes home gets its own isolated socket
|
||||
# → Prevents cross-user contamination
|
||||
# → Enables emacsclient --socket-name to connect as the correct user
|
||||
#
|
||||
# Audit trail: $LOG_DIR/emacs-daemon.log
|
||||
# → Tracks every start, stop, client connection, and error
|
||||
# → Logs are rotated by date to prevent unbounded growth
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# ── Resolve paths (supports both VPS and local dev) ───────────────────────────
|
||||
if [ -d "/root/wizards/bezalel" ]; then
|
||||
# VPS layout
|
||||
HERMES_HOME="/root/wizards/bezalel/home"
|
||||
WIZARD_HOME="/root/wizards/bezalel"
|
||||
CONFIG="$WIZARD_HOME/config.yaml"
|
||||
else
|
||||
# Local development
|
||||
HERMES_HOME="${HERMES_HOME:-$HOME/.hermes}"
|
||||
WIZARD_HOME="$HOME"
|
||||
CONFIG="$HERMES_HOME/config.yaml"
|
||||
fi
|
||||
|
||||
# ── Configuration ─────────────────────────────────────────────────────────────
|
||||
EMACS_DAEMON_NAME="bezalel" # daemon identifier (emacs --daemon=NAME)
|
||||
EMACS_SOCKET_DIR="$HERMES_HOME/emacs" # isolated socket per user/home
|
||||
EMACS_SOCKET_PATH="$EMACS_SOCKET_DIR/server"
|
||||
LOG_DIR="$HERMES_HOME/logs"
|
||||
EMACS_LOG="$LOG_DIR/emacs-daemon.log"
|
||||
PID_FILE="$EMACS_SOCKET_DIR/daemon.pid"
|
||||
|
||||
# Ensure directories exist
|
||||
mkdir -p "$LOG_DIR"
|
||||
mkdir -p "$EMACS_SOCKET_DIR"
|
||||
|
||||
# ── Logging ───────────────────────────────────────────────────────────────────
|
||||
log() {
|
||||
local level="$1"
|
||||
local msg="$2"
|
||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [$level] [emacs-daemon] $msg" | tee -a "$EMACS_LOG"
|
||||
}
|
||||
|
||||
log "INFO" "=== Emacs daemon startup sequence initiated ==="
|
||||
log "DEBUG" "HERMES_HOME=$HERMES_HOME"
|
||||
log "DEBUG" "Socket dir=$EMACS_SOCKET_DIR"
|
||||
log "DEBUG" "Socket path=$EMACS_SOCKET_PATH"
|
||||
log "DEBUG" "Log file=$EMACS_LOG"
|
||||
|
||||
# ── Pre-start checks ───────────────────────────────────────────────────────────
|
||||
# Check 1: Clean up stale socket
|
||||
if [ -S "$EMACS_SOCKET_PATH" ]; then
|
||||
# Socket exists — check if daemon is actually running
|
||||
if [ -f "$PID_FILE" ]; then
|
||||
local stored_pid
|
||||
stored_pid=$(cat "$PID_FILE" 2>/dev/null || echo "")
|
||||
if [ -n "$stored_pid" ] && kill -0 "$stored_pid" 2>/dev/null; then
|
||||
log "INFO" "Daemon already running (PID=$stored_pid, socket present). Exiting."
|
||||
exit 0
|
||||
else
|
||||
log "WARN" "Stale socket detected (no process at PID=$(cat $PID_FILE 2>/dev/null || echo 'unknown')). Removing."
|
||||
rm -f "$EMACS_SOCKET_PATH" "$PID_FILE" 2>/dev/null || true
|
||||
fi
|
||||
else
|
||||
log "WARN" "Orphan socket found (no PID file). Removing."
|
||||
rm -f "$EMACS_SOCKET_PATH" 2>/dev/null || true
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check 2: Verify no conflicting daemon with same name
|
||||
if pgrep -fa "emacs.*--daemon=$EMACS_DAEMON_NAME" | grep -v grep > /dev/null 2>&1; then
|
||||
log "WARN" "Another emacs daemon named '$EMACS_DAEMON_NAME' appears to be running. Checking socket..."
|
||||
# If socket exists and is valid, we're fine
|
||||
if [ -S "$EMACS_SOCKET_PATH" ]; then
|
||||
log "INFO" "Socket is active. Assuming daemon is healthy. Exiting."
|
||||
exit 0
|
||||
else
|
||||
log "ERROR" "Process found but socket missing. Manual intervention required. Exiting."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check 3: permissions — ensure we can write to socket dir
|
||||
if [ ! -w "$(dirname "$EMACS_SOCKET_PATH")" ]; then
|
||||
log "ERROR" "Cannot write to socket directory $(dirname "$EMACS_SOCKET_PATH"). Permission denied."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check 4: emacs binary available
|
||||
if ! command -v emacs > /dev/null 2>&1; then
|
||||
log "ERROR" "emacs binary not found in PATH. Install emacs-nox or emacs."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# ── Start daemon ───────────────────────────────────────────────────────────────
|
||||
log "INFO" "Starting Emacs daemon (name=$EMACS_DAEMON_NAME, socket=$EMACS_SOCKET_PATH)"
|
||||
|
||||
# Build the emacs command:
|
||||
# --daemon=NAME : named daemon for multi-daemon support
|
||||
# --socket-name : explicit socket path
|
||||
# -Q : no init file (sovereign/immutable config)
|
||||
# --no-window-system: headless operation
|
||||
# -batch : non-interactive (daemon mode implies this but explicit is better)
|
||||
EMACS_CMD="emacs --daemon=$EMACS_DAEMON_NAME --socket-name=$EMACS_SOCKET_PATH -Q --no-window-system"
|
||||
|
||||
# Capture output for audit
|
||||
log "DEBUG" "Command: $EMACS_CMD"
|
||||
|
||||
# Use timeout to prevent hangs; emacs daemon startup should be fast
|
||||
if timeout 30 $EMACS_CMD 2>&1 | tee -a "$EMACS_LOG"; then
|
||||
log "INFO" "Emacs daemon started successfully."
|
||||
|
||||
# Record PID (emacs writes it to the socket directory as .emacs.d/<name>.pid)
|
||||
# Also try to capture it via pgrep
|
||||
sleep 1
|
||||
local daemon_pid
|
||||
daemon_pid=$(pgrep -f "emacs.*--daemon=$EMACS_DAEMON_NAME" | head -1 || true)
|
||||
if [ -n "$daemon_pid" ]; then
|
||||
echo "$daemon_pid" > "$PID_FILE"
|
||||
log "INFO" "Recorded PID $daemon_pid to $PID_FILE"
|
||||
else
|
||||
log "WARN" "Could not determine daemon PID (socket may still be valid)."
|
||||
fi
|
||||
|
||||
# Verify socket is listening
|
||||
if [ -S "$EMACS_SOCKET_PATH" ]; then
|
||||
log "INFO" "Socket verified at $EMACS_SOCKET_PATH ($(ls -l "$EMACS_SOCKET_PATH" 2>/dev/null || echo 'unknown perms'))"
|
||||
else
|
||||
log "ERROR" "Socket not found after startup. Daemon may have failed to bind."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log "INFO" "=== Emacs daemon startup COMPLETE ==="
|
||||
exit 0
|
||||
else
|
||||
local exit_code=$?
|
||||
log "ERROR" "Emacs daemon startup FAILED (exit=$exit_code)."
|
||||
log "ERROR" "Check for port/socket conflicts, disk space, or emacs config errors."
|
||||
|
||||
# Cleanup partial state
|
||||
rm -f "$EMACS_SOCKET_PATH" "$PID_FILE" 2>/dev/null || true
|
||||
|
||||
exit $exit_code
|
||||
fi
|
||||
Reference in New Issue
Block a user