Wie kann ich meinen lokalen Emacs-Client als $ EDITOR für Remote-Computer verwenden, auf die ich über TRAMP zugreife?

44

Ich verwalte mit TRAMP häufig mehrere Remote-Server, sowohl zum Bearbeiten von Dateien als auch zum Ausführen von Remote-Shells shell-mode. Dies funktioniert jedoch nicht, wenn ein Befehl die EDITORVariable zum Bearbeiten einer Datei verwendet, z. B. crontab -eweil shell-modees sich um ein "dummes" Terminal handelt, das die Ausführung eines anderen Editors in der Datei nicht unterstützt.

Vor Ort mache ich das mit einem entsprechenden Aufruf, emacsclientder einen neuen Puffer öffnet und das Leben sehr erleichtert. Leider funktioniert dies nicht auf dem Remote-Computer.

Ich denke, ich könnte es gebrauchen ed. (Hah!)

Wie kann ich eine Fernbedienung einrichten EDITOR, mit der ich Dateien mit meiner lokalen Emacs-Instanz bearbeiten kann?

Tikhon Jelvis
quelle

Antworten:

23

[HINWEIS] Diese Antwort wurde stark überarbeitet, um den Aktualisierungen der with-editorEntwicklungen zu folgen . Die meisten Kommentare werden wahrscheinlich keinen Sinn mehr ergeben. Es gibt einige neue Kommentare , die tun sinnvoll.


Magit enthält eine Bibliothek mit dem Namen with-editoran verfügbaren https://github.com/magit/with-editor , die Sie Ihren lokalen Emacs als $ EDITOR auf entfernten Rechnern über TRAMP verwenden.

Eine andere Alternative ist https://github.com/habnabit/remote-emacsclient , aber es scheint komplizierter und weniger allgemein.

Die einfachste Art der Installation with-editorist über MELPA:

M-x package-install with-editor

Andernfalls greifen Sie einfach auf https://github.com/magit/with-editor/blob/master/with-editor.el zu, und zwar irgendwo in Ihrem Ladepfad require(dies hängt auch vom Strich ab).

Dann einfach starten shell, eshelloder ansi-termund wie folgt vorgehen:

M-x with-editor-export-editor

Sie werden gefragt, an welchem ​​$ EDITOR Sie interessiert sind. Drücken Sie einfach die Eingabetaste für die Standardvariable EDITOR. Dann können Sie in der Shell crontab -eIhre Crontab in Emacs eingeben und bearbeiten. Drücken Sie C-c C-c, um die Crontab zu speichern oder C-c C-kum die Bearbeitung abzubrechen.

Wenn Sie ein dauerhafteres Setup wünschen:

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

Alternativ können Sie M-x with-editor-async-shell-command crontab -e RETfür schnelle Befehle verwenden.

Silex
quelle
Könnten Sie erläutern, wie diese with-editorBibliothek mit der Frage zusammenhängt? Klingt nützlich
Malabarba
@Silex: Muss ich die $EDITORVariable auf dem Remote-Computer auf einen Wert einstellen, damit dies funktioniert? Lässt es sich einfach einhängen emacsclient?
Tikhon Jelvis
Aber ja, das sieht genau so aus, wie ich es will. Ich muss es irgendwie ausprobieren - ich gehe davon aus, dass es von selbst installiert werden kann, ohne den Rest des Zweigs?
Tikhon Jelvis
1
@TikhonJelvi: es sicherlich wird installierbar sein von selbst, aber jetzt ist es nur ein Teil git-modes. Ich verfolge diese Bibliothek genau und es ist nur so, dass der Autor (@tarsius) damit beschäftigt ist, magit freizugeben, aber irgendwann wäre es ein eigenes Paket. In Bezug auf $ EDITOR müssen Sie nichts selbst festlegen. Dies geschieht bei Bedarf, wenn Sie die Befehle ausführen, die es verwenden. Magit verwendet diese Bibliothek mit $ GIT_EDITOR.
Silex
1
Beachten Sie, dass dies nicht mehr funktioniert, nachdem Sie von einem vorhandenen shell-mode/ term-modebuffer zu einem Remote-Server gesendet haben . Dies kann mit einer zusätzlichen Konfiguration behoben werden (siehe emacs.stackexchange.com/questions/5589/…) . Wenn Sie es zum Laufen bringen, melden Sie Ihre Ergebnisse bitte unter github.com/magit/magit/issues/1638 .
Tarsius
1

Haftungsausschluss: Ich habe das nicht ausprobiert.

Ein Teil des Weges könnte durch die Ausgabe eines Funktionsüberwachungsbefehls für einen Befehl zum Öffnen der Datei mit TRAMP erfolgen. Sicherheitslücke? Ja. Funktionell? Wahrscheinlich.

Verwenden , um einen shell-modeHaken mit einem Haken zum hinzuzufügen after-change-hookin shell-mode. Dieser Hook überwacht eine bestimmte Sequenz. Beispiel:

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

Anschließend wird tramp-find-filedie Datei geöffnet. Dies ist relativ sicher, da die einzige Aktion, die die Fernbedienung ausführen kann, a auslöst tramp-find-file. Eine Bestätigung wäre zunächst gut, aber optional.

Wenn die Bearbeitung abgeschlossen ist, kann ein anderer Hook das Beenden des Dummy-Programms auslösen (z C-c. B. durch Senden ).

Der schlimmste Fall (aus Sicherheitsgründen) ist, dass sie einen Weg finden, beliebigen Code auszuführen. Wenn Sie Puffervariablen festlegen, die immer ausgewertet werden sollen, kann ein böswilliger Angreifer wichtige Einstellungen ohne Ihr Wissen überschreiben. Sie könnten auch einen Denial-of-Service-Angriff starten, indem viele Puffer geöffnet werden. Bestätigungen könnten wahrscheinlich all das verhindern.

Das Programm auf der Fernbedienung könnte einfach in C (oder einer anderen Sprache) implementiert werden.

J David Smith
quelle
1

https://stackoverflow.com/questions/2231902/originate-edit-of-remote-file-using-emacs-tramp-from-ssh-session hat eine ziemlich einfache akzeptierte Antwort, die sich beläuft

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

und dann verwenden

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

Es gibt auch https://stackoverflow.com/questions/12546722/using-emacs-server-and-emacsclient-on-other-machines-as-other-users, der komplexer ist, bei dem sich die Antworten aber auch (grob) ähnlich berühren Basen.

Tripleee
quelle
1

Ich habe ein winziges Skript in meinem Pfad auf dem Remote-Host unter ~/bin/ec, kurz für 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[@]}"

Dieses Skript übergibt -nund +args unverändert an emacsclient. Andernfalls werden args als Dateien behandelt, die Ihr lokaler Emacs öffnen soll. Jeder Datei wird das TRAMP-Protokoll und der Host vorangestellt, damit Emacs weiß, wie man sie öffnet. Möglicherweise können Sie zu ssh:einem anderen TRAMP-Protokoll wechseln, wenn Sie dies vorziehen.

Sie müssen durch zden Hostnamen Ihres Remote-Computers ersetzen . Dies wird von lokalen Emacs verwendet, um eine Verbindung über TRAMP herzustellen. (Möglicherweise können Sie dies hostnamehier allgemein verwenden. Ich bevorzuge der Kürze halber winzige Einträge wie zin meiner ssh_configLandessprache, und die Fernbedienung hat keine Ahnung, dass ich das mache. Probieren Sie es aus!)

Verwendungszweck:

  • ec file in der Remote-Shell öffnet die Datei in lokalem Emacs und wartet
  • ec -n file in der Remote-Shell öffnet die Datei in lokalem Emacs und kehrt zurück
  • export EDITOR=~/bin/ecIn der Ferne .bashrcgeschieht die Magie

Um sicherzustellen, dass meine serverDatei in Ordnung ist, habe ich dies in meinem lokalen .emacsVerzeichnis wieder unter Verwendung des winzigen Hostnamens 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)

Port 9999 ist eine RemoteForward. Ich habe dies in mein lokales ~/.ssh/ssh_configeingefügt, um die Weiterleitung zu automatisieren, und das ControlMaster-Zeug, um die Geschwindigkeit zu erhöhen.

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

Stellen ssh_configSie abschließend sicher, dass TRAMP über Ihre Daten informiert ist, wenn Sie diese verwenden:

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

Könnte ein bisschen Feineinstellung erfordern, aber hier ist die Idee:

EDITOR="ssh artagnon@luneth \"emacsclient -n /`hostname`:$1\""
artagnon
quelle
1
Meinen Sie damit, vom Remote-Server auf den Client zurückzukehren, auf dem Emacs ausgeführt wird? Das ist oft nicht möglich.
Gilles 'SO- hör auf böse zu sein'
Wenn Sie den Client, auf dem Emacs ausgeführt wird, nicht erreichen können, ist es unmöglich, etwas zu tun.
Artagnon
2
Sie können ssh über ~ / .ssh / config auffordern, den lokalen ssh-Listener immer an einen Port auf dem Remote-Computer weiterzuleiten. Sie möchten wahrscheinlich auch Ihren ssh-Agenten weiterleiten, obwohl die Meinungen darüber, wie sicher das ist, unterschiedlich sind. Auf diese Weise können Sie mit EDITOR = "ssh $ user @ localhost: 1234 ..."
Ben Hyde,
Eine andere Möglichkeit wäre vielleicht, einen kleinen Wrapper zu schreiben, um edit-server.el
stsquad
0

Harold Abnabit hat sich diesen Ansatz ausgedacht 1 :

http://blog.habnab.it/blog/2013/06/25/emacsclient-and-tramp/

1 basiert auf einem früheren Artikel von Ryan Barrett (auf den er verweist).

FWIW gibt es auch https://stackoverflow.com/q/5154224/324105, in dem Petri Lehtinen mit https://gist.github.com/akheron/850795 kam . Ich stelle mir vor, dass komplexere Lösungen besser sind, aber ein sehr einfacher Ansatz dennoch von Interesse sein könnte.

Phils
quelle
0

Wirklich überrascht, dass noch niemand etwas erwähnt sshfshat. Das mache ich normalerweise, wenn ich fernsteuere:

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

Während multi-termdas lokale Arbeitsverzeichnis nicht mit dem Remote-Verzeichnis synchronisiert wird, übertrifft es alle anderen Lösungen, die ich bei weitem versucht habe. Obwohl dir Tracking ein willkommenes Feature wäre.

Benjamin Lindqvist
quelle