¿Cómo puedo usar mi cliente local de Emacs como $ EDITOR para máquinas remotas a las que accedo a través de TRAMP?

44

A menudo uso TRAMP para administrar varios servidores remotos, tanto para editar archivos como para ejecutar shells remotos shell-mode. Sin embargo, esto no funciona cuando un comando usa la EDITORvariable para editar un archivo, como crontab -eespecialmente porque shell-modees un terminal "tonto" que no admite ejecutar otro editor dentro de él.

A nivel local, hago esto con una llamada apropiada emacsclientque abre un nuevo búfer y hace la vida muy fácil. Desafortunadamente, esto no funciona desde la máquina remota.

Supongo que podría usar ed. (¡Ja!)

¿Cómo puedo configurar un control remoto EDITORque me permita editar archivos con mi instancia local de Emacs?

Tikhon Jelvis
fuente

Respuestas:

23

[NOTA] esta respuesta fue editada en gran medida para seguir las actualizaciones de los with-editordesarrollos. La mayoría de los comentarios probablemente ya no tengan mucho sentido. Hay algunos comentarios nuevos que tienen sentido.


Magit contiene una biblioteca con nombre with-editordisponible en https://github.com/magit/with-editor que le permite usar su Emacs local como $ EDITOR en máquinas remotas a través de TRAMP.

Otra alternativa es https://github.com/habnabit/remote-emacsclient , pero parece más complicado y menos genérico.

La forma más sencilla de instalar with-editores a través de MELPA:

M-x package-install with-editor

De lo contrario, solo tome https://github.com/magit/with-editor/blob/master/with-editor.el en algún lugar de su ruta de carga y requireesto (también depende del guión).

A continuación, sólo tiene que iniciar shell, eshello ansi-termy hacer lo siguiente:

M-x with-editor-export-editor

Le preguntará qué $ EDITOR le interesa, simplemente presione Intro para la EDITORvariable predeterminada . Luego, dentro del shell, puede escribir crontab -ey editar su crontab dentro de emacs. Presione C-c C-cpara guardar el crontab o C-c C-kpara cancelar la edición.

Si desea una configuración más permanente:

(add-hook 'shell-mode-hook  'with-editor-export-editor)
(add-hook 'term-mode-hook   'with-editor-export-editor)
(add-hook 'eshell-mode-hook 'with-editor-export-editor)

Alternativamente, puede usar M-x with-editor-async-shell-command crontab -e RETpara comandos rápidos.

Sílex
fuente
¿Podría explicar cómo se with-editorrelaciona esta biblioteca con la pregunta? Suena útil
Malabarba
@Silex: ¿Necesitaría establecer la $EDITORvariable en algo en la máquina remota para que esto funcione? ¿Simplemente se engancha emacsclient?
Tikhon Jelvis
Pero sí, esto parece exactamente lo que quiero. Tendré que intentarlo de alguna manera, ¿supongo que se puede instalar solo, sin el resto de la rama?
Tikhon Jelvis
1
@TikhonJelvi: ciertamente será instalable por sí mismo, pero por ahora es solo una parte git-modes. Estoy siguiendo de cerca esta biblioteca y es solo que su autor (@tarsius) está ocupado lanzando magit, pero eventualmente sería un paquete propio. Acerca de $ EDITOR, no necesita configurarlo usted mismo, se hace cuando es necesario cuando ejecuta los comandos que lo usan. Magit usa esta lib con $ GIT_EDITOR.
Silex
1
Tenga en cuenta que esto dejará de funcionar después de enviar a un control remoto desde un búfer shell-mode/ existente term-mode. Esto se puede solucionar con alguna configuración adicional, consulte emacs.stackexchange.com/questions/5589/… . Si logra que funcione, informe sus hallazgos en github.com/magit/magit/issues/1638 .
tarsius
1

Descargo de responsabilidad: no he intentado esto.

Puede obtener parte del camino al tener una salida de comando de observación de función para que un comando abra el archivo usando TRAMP. Agujero de seguridad? Si. ¿Funcional? Probablemente.

Use un shell-modegancho para agregar un gancho para after-change-hooken shell-mode. Este gancho vigila una secuencia específica. Ejemplo:

;; RemoteTRAMP token: <authentication token maybe?>
;; RemoteTRAMP edit: /path/to/my/file

Luego se utiliza tramp-find-filepara abrir el archivo. Esto es relativamente seguro porque lo ÚNICO que puede hacer el control remoto es activar a tramp-find-file. Una confirmación primero sería buena pero opcional.

Cuando finaliza la edición, otro enlace puede activar la salida del programa ficticio (por ejemplo, mediante el envío C-c).

El peor de los casos (por seguridad) es que encuentran una manera de ejecutar código arbitrario. Si tiene variables de búfer configuradas para evaluar siempre, un atacante malintencionado podría sobrescribir configuraciones importantes sin su conocimiento. También podrían lanzar un ataque de denegación de servicio al hacer que se abran muchos búferes. Es probable que las confirmaciones eviten todo lo anterior.

El programa en el control remoto podría implementarse trivialmente en C (o en cualquier otro lenguaje).

J David Smith
fuente
1

https://stackoverflow.com/questions/2231902/originate-edit-of-remote-file-using-emacs-tramp-from-ssh-session tiene una respuesta aceptada bastante simple que equivale a

(setq server-use-tcp t)
(setq server-host "name_of_local_machine")
(server-start)
;; Maybe also muck with `server-auth-dir`

y luego usar

emacsclient -f ~/.emacs.d/server/server /`hostname`:/path/to/local/file

También hay https://stackoverflow.com/questions/12546722/using-emacs-server-and-emacsclient-on-other-machines-as-other-users que es más complejo pero donde las respuestas también (aproximadamente) tocan similares bases.

tripleee
fuente
1

Tengo un pequeño script en mi camino en el host remoto en ~/bin/ec, abreviatura de emacsclient.

#!/bin/bash

params=()
for p in "$@"; do
  if [ "$p" == "-n" ]; then
    params+=( "$p" )
  elif [ "${p:0:1}" == "+" ]; then
    params+=( "$p" )
  else
    params+=( "/ssh:z:"$(readlink -f $p) )
  fi
done
emacsclient --server-file=$HOME/.emacs.d/server/server "${params[@]}"

Esta secuencia de comandos pasa -ny los argumentos +no cambian a emacsclient; de lo contrario, los argumentos se tratan como archivos para que los abra su Emacs local. Cada archivo tiene como prefijo el protocolo TRAMP y el host para que Emacs sepa cómo abrirlo. Es posible que pueda cambiar ssh:a un protocolo TRAMP diferente si lo prefiere.

Debe reemplazarlo zcon el nombre de host de su máquina remota. Emacs local lo utiliza para conectarse a través de TRAMP. (Es posible que pueda usar hostnameaquí por generalidad. Prefiero usar entradas pequeñas como zen mi local ssh_configpor brevedad, y el control remoto no tiene idea de que estoy haciendo esto. ¡Pruébelo!)

Uso:

  • ec file en el shell remoto abre el archivo en Emacs local y espera
  • ec -n file en el shell remoto abre el archivo en Emacs local y devuelve
  • export EDITOR=~/bin/ecen remoto .bashrchace que la magia suceda

Para asegurarme de que mi serverarchivo es bueno, tengo esto en mi local .emacs, nuevamente usando el pequeño nombre de host z:

(setq server-use-tcp t
      server-port    9999)
(defun server-start-and-copy ()
  "Start server and copy server file to remote box."
  (interactive)
  (server-start)
  (copy-file "~/.emacs.d/server/server" "/z:.emacs.d/server/server" t)
  (chmod "/z:.emacs.d/server/server" (string-to-number "644" 8))
  )
(add-hook 'emacs-startup-hook 'server-start-and-copy)

El puerto 9999 es un RemoteForward. Puse esto en mi local ~/.ssh/ssh_configpara automatizar el reenvío, además de las cosas ControlMaster para la velocidad.

Host z
HostName dev.example.com
User dev
ControlMaster auto
ControlPath ~/.ssh/z.sock
RemoteForward 9999 localhost:9999

Finalmente, asegúrese de que TRAMP sepa de usted ssh_configsi lo usa:

(require 'tramp)
(tramp-set-completion-function "ssh"
  '((tramp-parse-sconfig "~/.ssh/config")))
Andy
fuente
0

Podría requerir un poco de ajustes, pero esta es la idea:

EDITOR="ssh artagnon@luneth \"emacsclient -n /`hostname`:$1\""
artagnon
fuente
1
¿Te refieres a regresar del servidor remoto al cliente donde se ejecuta Emacs? Eso a menudo no es posible.
Gilles 'SO- deja de ser malvado'
Bueno, si no puede comunicarse con el cliente donde se ejecuta Emacs, es imposible hacer nada.
artagnon
2
Puede pedirle a ssh, a través de su ~ / .ssh / config, que siempre reenvíe el oyente local ssh a un puerto en la máquina remota. Probablemente también desee reenviar su agente ssh, aunque las opiniones varían en cuanto a qué tan seguro es eso. Esto le permitirá volver haciendo EDITOR = "ssh $ user @ localhost: 1234 ..."
Ben Hyde
Otra opción quizás sería escribir un pequeño contenedor para llamar a edit-server.el
stsquad
0

Realmente sorprendido que nadie ha mencionado sshfstodavía. Esto es lo que suelo hacer cuando voy a distancia:

1) multi-term; sshfs user@host:/dir/i/want/ /mnt/point/on/my/machine
2) open whatever I want to edit in my local emacs
3) get-term; ssh user@host to launch executables etc

Si bien multi-termno sincroniza el directorio de trabajo local con el directorio remoto, supera todas las demás soluciones que probé por asomo. Aunque el seguimiento de directorios sería una característica bienvenida de seguro.

Benjamin Lindqvist
fuente