emacsclient para acessar o servidor emacs remoto

8

Estou tentando abrir uma sessão emacsclient de um host remoto. Eu andei pelas etapas a seguir no site do tramp. Como posso usar o TRAMP para conectar-se a uma sessão remota do Emacs?

Eu vou levá-lo através do passo

  1. no host remoto colocado no arquivo .emacs

    (require 'server)
    (setq server-host "<IP ADDRESS of remoteHost>"
          server-use-tcp t)
    (server-start)
    
  2. iniciar sessão do emacs no host remoto

  3. copie o ~ / emacs.d / server / server de remoteHost para localHost e mantenha o mesmo caminho. (localHost: ~ / emacs.d / server / server)

  4. no host emacs do host local

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

Mas recebi o seguinte erro no meu 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)

Portanto, parece conectar-se ao remoteHost, mas não consegue encontrar uma rota. Perguntas semelhantes foram feitas no SO. Aqui e aqui . Também há um código legal sobre como copiar diretamente o ~ / .emacs.d / server / server do remoteHost para o localHost aqui .

Qualquer ajuda será muito apreciada.

Atualização Reuni mais algumas informações sobre o assunto. Parece que várias pessoas tentaram essa tarefa e algumas parecem ter sido bem-sucedidas, mas eu encontrei qualquer solução para o meu problema específico. Usando o servidor Emacs e o emacsclient em outras máquinas como outros usuários

Perguntas semelhantes também foram feitas no emacs.stack.exchange, como como usar o emacsclient para conectar-se a uma instância do emacs remota

Update1

Há um post interessante aqui encaminhando gráficos com ssh. É fácil de implementar e funciona muito bem se sua conexão é boa o suficiente, mas não utiliza tramp.

DJJ
fonte
Pergunta 1: Os servidores remotos serão UNIX ou Linux e terão um daemon SSH em execução? Pergunta 2: As versões de todos os emacsclients remotos são compatíveis com a versão local do emacs? Eu configurei com sucesso e usei o emacsclients remoto para conectar-me ao meu emacs local em execução no modo daemon / servidor.
Melioratus
sim para as duas perguntas.
DJJ

Respostas:

8

Acho que uma das coisas que não estão claras nas perguntas frequentes é a necessidade de que o servidor e o cliente sejam resolvidos um do outro. Você pode ver esta discussão de 2009. Eventualmente, naquela época, consegui que funcionasse, mas agora vejo o mesmo que o OP. Isto é o que eu tentei:

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

Eu iniciei o servidor assim:

$ emacs -Q -l setup.el

Isso dará a você uma janela do Emacs. Se você não quiser, comente a (server-start)linha e inicie o Emacs assim:

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

Agora, na máquina remota, copiei o cookie conforme as instruções nas Perguntas frequentes e tentei iniciar o cliente assim:

$ emacsclient -f ~/.emacs.d/server/sx-test /ssh:[email protected]:/path/to/foo

192.168.2.200 é o ip do cliente remoto. É por isso que a resolução de nomes nos dois sentidos é necessária. Essencialmente, /ssh:[email protected]:/path/to/fooé o caminho que você daria ao servidor para editar remotamente.

Eu vejo uma falha como o OP. Corri emacsclientsob o gdb e rastreei o problema até uma falha na conexão ao soquete.

de 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;
    }

Em seguida, executei-o stracee veja o seguinte:

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 +++

Neste ponto, não tenho certeza do que está acontecendo de errado, pois posso executar ping e ssh no servidor.

Quarky
fonte
Parece que meu teste foi um pouco incorreto. Havia vários outros servidores em execução, o que levou a conclusões falsas. Atualizarei a resposta em breve com o que encontrar.
Quarky 29/09/2015
Obrigado @suvayu pela sua resposta. Embora não seja a resposta exata para minha pergunta, postei uma etapa secundária do problema. Mas parece que sua resposta é a solução mais próxima até agora. Vou deixar a pergunta em aberto, apenas por precaução.
DJJ 14/12/2015
@ DJJ Eu acho que é justo. Se eu encontrar uma resolução, atualizarei a resposta.
Quarky
3

Essa não é exatamente a resposta para minha pergunta, mas consegui contornar o problema usando esta solução em uma postagem no SO . Só quero compartilhar a solução com quem ainda está lutando com isso.

A chave está usando o dtach with tramp para manter vivo o processo no host remoto, mesmo que você se desconecte do servidor.

Aqui está o comando para iniciar o R ​​no servidor. É o mesmo código no SO, exceto que eu habilito o encaminhamento de porta para visualizar os gráficos criados no servidor remoto

(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))

Contanto que você não interrompa o processo de propósito ou o servidor não reinicie, você pode desconectar o que quiser e voltar ao processo quando se conectar novamente.

Também é fácil estender para outros processos remotos. Aqui está o que eu uso para python, por exemplo

(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))

Eu ainda preciso usar para reunir as duas funções para ser mais conciso. Mas isso pode fazer você ir.

DJJ
fonte