emacs –daemon mit launchd und KeepAlive

Problem

Wer den Emacs unter OSX als daemon starten will, kann das mittels launchd-Skript machen.

Das Verfahren wird schon an verschiedenen Stellen beschrieben.

Problematisch wird es nur, wenn im launchd-Skript „KeepAlive“ benutzt wird, da der Emacs einen Fork macht, was launchd nicht mag – siehe Emacs-Bugeintrag.

Lösung

Als Workaround habe ich mir einen emacsdaemon.sh –Wrapper geschrieben:

$HOME/Library/Scripts/emacsdaemon.sh

#/bin/sh

EMACS_DIR=/usr/local/Cellar/emacs/HEAD/
EMACS=${EMACS_DIR}/bin/emacs
EMACSCLIENT=${EMACS_DIR}/bin/emacsclient

getPid(){
 PID=$($EMACSCLIENT -e '(emacs-pid)' 2> /dev/null)
 echo $PID
}
anywait(){
 for pid in "$@"; do
 while kill -0 "$pid"; do
 sleep 5
 done
 done
}

DAEMON_PID=$(getPid)

on_complete() {
 echo $(date +%R)' Ended.' >> "$LOG"
 kill -9 $DAEMON_PID
 exit
}

trap 'on_complete 2> /dev/null' SIGTERM SIGINT SIGHUP EXIT

case $1 in 
 status)
    if [ -z "$DAEMON_PID" ]; then 
       echo "Emacs-Daemon NOT RUNNING"
    else
       echo "Emacs-Daemon running PID:$DAEMON_PID"
    fi
 ;;
 stop)
    kill -9 $DAEMON_PID
    exit 0
 ;;
 launchd)
    test -z "$DAEMON_PID" && {
        $EMACS -daemon
        sleep 1
    }
    DAEMON_PID=$(getPid)
    test -z "$DAEMON_PID" && {
       echo "not running -> exit"
       sleep 2
       exit 1
    }
    anywait $DAEMON_PID
 ;;
 wait)
    anywait $DAEMON_PID
 ;;
esac

EMACS_DIR sollte evtl angepasst werden

$HOME/Library/LaunchAgents/gnu.emacs.daemon.plist

<?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 <plist version="1.0">
 <dict>
 <key>Label</key>
 <string>gnu.emacs.daemon</string>
 <key>ProgramArguments</key>
 <array>
 <string>~/Library/Scripts/emacsdaemon.sh</string>
 <string>launchd</string>
 </array>
 <key>RunAtLoad</key>
 <true/>
 <key>KeepAlive</key>
 <true/>
 <key>EnableGlobbing</key>
 <true/> 
 <key>ServiceDescription</key>
 <string>Gnu Emacs Daemon</string>
 </dict>
 </plist>

Einsatz

Einfach einmal per launchctl laden und der Emacs ist nach jeden Login als daemon gestartet.

$ launchctl load $HOME/Library/LaunchAgents/gnu.emacs.daemon.plist
$ ps ax | grep -i emacs
52370   ??  S      0:00.08 sh /Users/xxx/Library/Scripts/emacsdaemon.sh launchd
52382   ??  Ss     0:03.18 /usr/local/Cellar/emacs/HEAD/Emacs.app/Contents/MacOS/Emacs -nw --daemon=^J3,4^J