¿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?
[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.
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.
¿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:
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).
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:
¿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
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.
with-editor
relaciona esta biblioteca con la pregunta? Suena útil$EDITOR
variable en algo en la máquina remota para que esto funcione? ¿Simplemente se enganchaemacsclient
?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.shell-mode
/ existenteterm-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 .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-mode
gancho para agregar un gancho paraafter-change-hook
enshell-mode
. Este gancho vigila una secuencia específica. Ejemplo:Luego se utiliza
tramp-find-file
para abrir el archivo. Esto es relativamente seguro porque lo ÚNICO que puede hacer el control remoto es activar atramp-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).
fuente
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
y luego usar
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.
fuente
Tengo un pequeño script en mi camino en el host remoto en
~/bin/ec
, abreviatura de emacsclient.Esta secuencia de comandos pasa
-n
y 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 cambiarssh:
a un protocolo TRAMP diferente si lo prefiere.Debe reemplazarlo
z
con el nombre de host de su máquina remota. Emacs local lo utiliza para conectarse a través de TRAMP. (Es posible que pueda usarhostname
aquí por generalidad. Prefiero usar entradas pequeñas comoz
en mi localssh_config
por 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 esperaec -n file
en el shell remoto abre el archivo en Emacs local y devuelveexport EDITOR=~/bin/ec
en remoto.bashrc
hace que la magia sucedaPara asegurarme de que mi
server
archivo es bueno, tengo esto en mi local.emacs
, nuevamente usando el pequeño nombre de hostz
:El puerto 9999 es un RemoteForward. Puse esto en mi local
~/.ssh/ssh_config
para automatizar el reenvío, además de las cosas ControlMaster para la velocidad.Finalmente, asegúrese de que TRAMP sepa de usted
ssh_config
si lo usa:fuente
Podría requerir un poco de ajustes, pero esta es la idea:
fuente
Harold Abnabit propuso este enfoque 1 :
http://blog.habnab.it/blog/2013/06/25/emacsclient-and-tramp/
1 basado en un artículo anterior de Ryan Barrett (al que se vincula).
FWIW también hay https://stackoverflow.com/q/5154224/324105 en el que Petri Lehtinen ideó https://gist.github.com/akheron/850795 . Me imagino que las soluciones más complejas son mejores, pero un enfoque muy simple aún podría ser interesante.
fuente
Realmente sorprendido que nadie ha mencionado
sshfs
todavía. Esto es lo que suelo hacer cuando voy a distancia:Si bien
multi-term
no 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.fuente