7

I'm trying to open an emacsclient session from a remote host. I walked through the following steps on the tramp website How can I use TRAMP to connect to a remote Emacs session?.

I'll walk you through the step

  1. on the remote host put in .emacs file

    (require 'server)
    (setq server-host "<IP ADDRESS of remoteHost>"
          server-use-tcp t)
    (server-start)
    
  2. start emacs session on remote host

  3. copy the ~/emacs.d/server/server from remoteHost to localHost keep the same path. (localHost:~/emacs.d/server/server)

  4. on local host emacs shell

    emacsclient /ssh:test@remoteHost:/tmp/test.py

But got the following error on my localHost

;; emacsclient: can't find socket; have you started the server?
;; To start the server in Emacs, type "M-x server-start".
;; emacsclient: connected to remote socket at `Remotehost`
;; emacsclient: connect: No route to host
;; 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)

So it seems to connect to remoteHost but cannot find a route. Similar questions have been ask on SO. Here and here. There are also some nice code about copying directly the ~/.emacs.d/server/server from remoteHost to localHost here.

Any help will be greatly appreciated.

Update I have gathered some more information about the matter. It's seem that a number of people have attempted this task and some seems to have succeeded but I could find any solution to my specific problem. Using Emacs server and emacsclient on other machines as other users

Similar questions have also been ask on emacs.stack.exchange like how-do-i-use-emacsclient-to-connect-to-a-remote-emacs-instance

Update1

There is an interesting post here forwarding graphics with ssh. It's easy to implement and works pretty well if your connection is good enough but it does not make use of tramp.

  • Question 1: Will the remote servers be UNIX or Linux and have an SSH daemon running? Question 2: Are the versions of all remote emacsclients compatible with local emacs version? I've successfully setup and used remote emacsclients to connect back to my local emacs running in daemon/server mode. – Melioratus Oct 1 '15 at 14:20
  • yes to both of your questions. – DJJ Oct 2 '15 at 15:17
7
+50

I think one of the things unclear from the FAQ is the necessity that both server and client be resolveable from each other. You can see this thread from 2009. Eventually, back then I did get it to work, but now I do see the same as the OP. This is what I tried:

setup.el:

(require 'server)

(setq server-name "sx-test"       ; name of the server
      server-host "192.168.2.198" ; server ip
      server-use-tcp t)

(server-start)                    ; comment out when using --daemon

I started the server like this:

$ emacs -Q -l setup.el

This will give you an Emacs window though. If you do not want that, comment out the (server-start) line, and start Emacs like this:

$ emacs -Q -l setup.el --daemon

Now on the remote machine, I copied the cookie as instructed in the FAQ, and attempted to start the client like this:

$ emacsclient -f ~/.emacs.d/server/sx-test /ssh:user@192.168.2.200:/path/to/foo

192.168.2.200 is the ip of the remote client. This is why both-way name resolution is necessary. Essentially, /ssh:user@192.168.2.200:/path/to/foo is the tramp path you would give to server to edit remotely.

I see a failure just like the OP. I ran emacsclient under gdb, and traced back the problem to a failure in connecting to the socket.

from emacsclient.c:

  /* Set up the socket.  */
  if (connect (s, (struct sockaddr *) &server, sizeof server) < 0) /* <-- fails here */
    {
#ifdef WINDOWSNT
      if(!(w32_window_app () && alternate_editor))
#endif
      sock_err_message ("connect");
      return INVALID_SOCKET;
    }

I then ran it under strace, and see the following:

write(1, "emacsclient: connected to remote"..., 57emacsclient: connected to remote socket at 192.168.2.198
) = 57
socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) = 3
connect(3, {sa_family=AF_INET, sin_port=htons(40266), sin_addr=inet_addr("192.168.2.198")}, 16) = -1 EHOSTUNREACH (No route to host)
write(2, "emacsclient: connect: No route t"..., 39emacsclient: connect: No route to host
) = 39
write(2, "emacsclient: error accessing ser"..., 80emacsclient: error accessing server file "/home/jallad/.emacs.d/server/sx-test"
) = 80
exit_group(1)                           = ?
+++ exited with 1 +++

At this point I'm not sure what is going wrong, as I can ping and ssh into the server.

  • Looks like my testing was a bit incorrect. There were several other servers running which led to false conclusions. I'll update the answer soon with what I find. – suvayu Sep 29 '15 at 10:16
  • Thanks @suvayu for your answer. Though it's not the exact answer to my question I've posted a side step to the problem. But It seems that your answer is the closest solution so far. I'll let the question open just in case – DJJ Dec 14 '15 at 13:58
  • @DJJ I think that's fair. If I find a resolution, I'll update the answer. – suvayu Dec 14 '15 at 14:04
3

That's not exactly the answer to my question but I managed to sidestep the problem by using this solution from a post in SO. Just wanting to share the solution with the one who are still struggling with this.

The key is using dtach with tramp to keep the process alive on the remote host alive even if your disconnect from the server.

Here is the command to launch R on the server. It's the same code on SO except I enable port forwarding to view graphics created on the remote server

(defvar R-remote-host "remotehost")
(defvar R-remote-session "R")

(defun R-remote (&optional remote-host session)
  "Connect to the remote-host's dtach session running R."
  (interactive (list
        (read-from-minibuffer "R remote host: " R-remote-host)
        (read-from-minibuffer "R remote session: " R-remote-session)))
  (pop-to-buffer (make-comint (concat "remote-" session)
              "ssh" nil "-X"  "-t" "-t" remote-host
              "dtach" "-A" (concat ".dtach-" session)
              "-z" "-E"  "-r" "none"
              inferior-R-program-name "--no-readline"
              inferior-R-args))
  (ess-remote (process-name (get-buffer-process (current-buffer))) "R")
  (setq comint-process-echoes t))

As long as you don't kill the process on purpose or the server doesn't restart you can disconnect as you like and get back the process when you connect again.

It's easy to extend to other remote processes as well. Here is the one I use for python for example

(defvar remote-host "remotehost")
(defvar remote-session "python")
(defun python-remote (&optional remote-host session)
  "Connect to the remote-host's dtach session running python."
  (interactive (list
        (read-from-minibuffer "R remote host: " remote-host)
        (read-from-minibuffer "R remote session: " remote-session)))
  (pop-to-buffer (make-comint (concat "remote-" session)
              "ssh" nil "-t" "-t" remote-host
              "dtach" "-A" (concat ".dtach-" session)
              "-z" "-E" "-r" "none"
             "python" )
         )
  (setq comint-process-echoes t))

I still need to use to pull both functions together to be more concise. But it might get you going.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.