sage han
sage han

Reputation: 315

Why emacsclient can't find socket after executing 'emacs --daemon'

It is so confusing that emacsclient said it can't find socket just after executing emacs --daemon in bash:

$ ps aux | grep emacs
shiangro         1744   0.0  0.0  2432784    604 s000  S+    1:03下午   0:00.00 grep emacs
$ /usr/local/bin/emacs --daemon
("emacs")
Starting Emacs daemon.
Restarting server
$ /usr/local/bin/emacsclient -t
emacsclient: can't find socket; have you started the server?
To start the server in Emacs, type "M-x server-start".
emacsclient: No socket or alternate editor.  Please use:

    --socket-name
    --server-file      (or environment variable EMACS_SERVER_FILE)
    --alternate-editor (or environment variable ALTERNATE_EDITOR)

I have this settings in my .emacs:

(server-start)
(setq server-socket-dir "~/.emacs.d/server")

and it works,the server file ~/.emacs.d/server/server was just there,but emacsclient say it can't find socket,so annoying that I have to tell him the socket file using the -s option.

I find this thorny problem while I want let emacs runing as a daemon after everytime rebooting(start) systerm by using crontab's ◎reboot special strings.

In this case ,cron successfully started the emacs server and the server file ~/.emacs.d/server/server was also there, but later when I started a terminal and tried to emacsclient -t ,it failed and complained can't find socket file!

Although I can bypass this problem by using -s ~/.emacs.d/server/server everytime I excute emacsclient,or alias emacsclient as emacsclient -s ~/.emacs.d/server/server ,but is ther a better way to comfort my heart?

Backgroud:

system: Mac OS X 10.9.2

emacs: GNU Emacs 24.3.1 installed by homebrew

Upvotes: 16

Views: 17013

Answers (5)

Allen D. Ball
Allen D. Ball

Reputation: 2026

On macOS, the emacs socket name is calculated as follows:

export EMACS_SOCKET_NAME="${TMPDIR}/emacs$(id -u)/server"

According to emacsclient, the environment variable EMACS_SOCKET_NAME may be set to override the default. However, this does not seem to work in a Homebrew environment. I have this in my .bashrc which works for me:

export EDITOR="emacsclient --tty"
export ALTERNATE_EDITOR="emacs --no-window-system"

case "$(uname -s)" in
    # ...

    Darwin*)
        export EMACS_SOCKET_NAME="${TMPDIR}/emacs$(id -u)/server"
        export EDITOR="${EDITOR} --socket-name ${EMACS_SOCKET_NAME}"
    ;;
esac

Upvotes: 2

practicalli-johnny
practicalli-johnny

Reputation: 1916

emacsclient only finds the emacs server if I run emacs from the command line. If I run emacs from the Ubuntu launcher then emacsclient fails to connect to the server.

If you want to use the Emacs daemon instead of the server, define the two environment variables

export ALTERNATE_EDITOR="" export EDITOR=emacsclient

You can add these environment variables in either ~/.bashrc or ~/.profile.

If the ALTERNATE_EDITOR environment variable is empty, then Emacs will run its daemon and connect to it.

Upvotes: 3

ocodo
ocodo

Reputation: 30309

Finding the server socket file is the tricky bit, you can use lsof to find it, and then a bit of grep-ing to extract the socket path/filename.

lsof -c emacs | grep server | grep -E -o '[^[:blank:]]*$'

Or on OSX when you expect to be running /Application/Emacs you'd change the command name lsof is looking for with -c Emacs. ie.

lsof -c Emacs | grep server | grep -E -o '[^[:blank:]]*$'

You could use cut instead of the messy filtering grep (searching for non-blanks until the line end [^[:blank:]]*$)

lsof -c Emacs | grep server | cut -c70-

Better yet, squish the interspacing and use cut's field chopping.

lsof -c Emacs | grep server | tr -s " " | cut -d' ' -f8

Now that you have the socket (or it's empty) you can do a conditional start on emacsclient, ie.

#!/bin/bash 

socket_file=$(lsof -c Emacs | grep server | tr -s " " | cut -d' ' -f8)

if [[ $socket_file == "" ]]; then        
    # Just run Emacs (with any arguments passed to the script)
    # It would be a good idea to parse the arguments and clean/remove
    # anything emacsclient specific. 
    # (ie. -e should be --eval for emacs)
    # note that emacsclient doesn't fix these args for you either
    # when using -a / --alternate-editor

    emacs $@ &

    # or on OSX

    /Application/Emacs.app/Contents/MacOS/Emacs $@ &

else

    emacsclient $@ -n -s $socket_file

fi

Upvotes: 17

Diagon
Diagon

Reputation: 493

Since you've done:

/usr/local/bin/emacs --daemon

the server is already started. So, you don't actually need the:

(server-start)
(setq server-socket-dir "~/.emacs.d/server")

in your .emacs. When you follow that approach, the server is placed in /tmp/emacs502 (or maybe some other number). On linux, emacsclient doesn't seem to have trouble finding it there (in that case I'm seeing /tmp/emacs1920), and so "emacsclient -nw" works. I'm trying it on OSX using HomeBrew, as you are, and I find I have to connect using:

emacsclient -nw -s /tmp/emacs502/server

(If you used --deamon=name, then you would use "name" instead of "server" in that last line.)

Upvotes: 11

artscan
artscan

Reputation: 2350

I think emacsclient can look for special file server in standard path only, e.g. in /tmp/emacs1000. If you change this parameter server-socket-dir, then you should tell about it to emacsclient by key -s.

Upvotes: 1

Related Questions