Jak mogę użyć mojego lokalnego klienta Emacs jako $ EDITOR dla zdalnych komputerów, do których mam dostęp przez TRAMP?

44

Często używam TRAMP do zarządzania kilkoma zdalnymi serwerami, zarówno do edycji plików, jak i uruchamiania zdalnych powłok shell-mode. Nie działa to jednak, gdy polecenie używa EDITORzmiennej do edycji pliku, na przykład crontab -edlatego, że shell-modejest to „głupi” terminal, który nie obsługuje uruchamiania w nim innego edytora.

Lokalnie robię to za pomocą odpowiedniego wywołania, emacsclientktóre otwiera nowy bufor i ułatwia życie. Niestety nie działa to ze zdalnego komputera.

Chyba mógłbym użyć ed. (Ha!)

Jak mogę skonfigurować pilota EDITOR, który pozwoli mi edytować pliki za pomocą mojej lokalnej instancji Emacsa?

Tikhon Jelvis
źródło

Odpowiedzi:

23

[UWAGA] ta odpowiedź została mocno zredagowana, aby śledzić aktualizacje with-editorrozwoju. Większość komentarzy prawdopodobnie nie będzie już miała sensu. Jest kilka nowych komentarzy, które mają sens.


Magit zawiera bibliotekę o nazwie with-editordostępnej na https://github.com/magit/with-editor, która pozwala używać lokalnego Emacsa jako edytora $ na zdalnych komputerach przez TRAMP.

Inną alternatywą jest https://github.com/habnabit/remote-emacsclient , ale wydaje się bardziej skomplikowana i mniej ogólna.

Najprostszym sposobem instalacji with-editorjest MELPA:

M-x package-install with-editor

W przeciwnym razie po prostu chwyć https://github.com/magit/with-editor/blob/master/with-editor.el gdzieś na ścieżce ładowania i requireto (to zależy również od myślnika).

Następnie wystarczy uruchomić shell, eshellalbo ansi-termi wykonaj następujące czynności:

M-x with-editor-export-editor

Zapyta Cię, który $ EDITOR jest zainteresowany, po prostu naciśnij klawisz Enter, aby wyświetlić domyślną EDITORzmienną. Następnie wewnątrz powłoki możesz pisać crontab -ei edytować swoją crontab w emacs. Naciśnij, C-c C-caby zapisać crontab lub C-c C-kanulować edycję.

Jeśli chcesz mieć bardziej trwałą konfigurację:

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

Możesz też użyć M-x with-editor-async-shell-command crontab -e RETdo szybkich poleceń.

Silex
źródło
Czy mógłbyś wyjaśnić, w jaki sposób ta with-editorbiblioteka odnosi się do pytania? Brzmi użytecznie
Malabarba,
@Silex: Czy musiałbym ustawić $EDITORzmienną na coś na zdalnym komputerze, aby to zadziałało? Czy to się po prostu zaczepia emacsclient?
Tikhon Jelvis
Ale tak, to wygląda dokładnie tak, jak chcę. Będę musiał spróbować jakoś - zakładam, że można go zainstalować samodzielnie, bez reszty gałęzi?
Tikhon Jelvis
1
@TikhonJelvi: z pewnością będzie można go zainstalować samodzielnie, ale na razie jest to tylko część git-modes. Śledzę dokładnie tę bibliotekę i po prostu jej autor (@tarsius) jest zajęty wypuszczaniem magitów, ale ostatecznie będzie to własny pakiet. Jeśli chodzi o $ EDITOR, nie musisz sam ustawiać go na nic, dzieje się to w razie potrzeby, gdy uruchomisz dowolne polecenia z niego korzystające. Magit używa tej biblioteki z $ GIT_EDITOR.
Silex,
1
Zauważ, że przestanie to działać po sshing do pilota z istniejącego shell-mode/ term-modebufora. Można to rozwiązać za pomocą dodatkowej konfiguracji, patrz emacs.stackexchange.com/questions/5589/… . Jeśli sprawdzisz, czy to działa, zgłoś swoje ustalenia na github.com/magit/magit/issues/1638 .
tarsjusz
1

Oświadczenie: Nie próbowałem tego.

Możesz uzyskać część tego, uruchamiając funkcję watch watch dla polecenia otwarcia pliku za pomocą TRAMP. Dziura bezpieczeństwa? Tak. Funkcjonalny? Prawdopodobnie.

Użyć shell-modehaka, aby dodać do haka after-change-hookw shell-mode. Ten haczyk obserwuje określoną sekwencję. Przykład:

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

Następnie używa tramp-find-filedo otwarcia pliku. Jest to względnie bezpieczne, ponieważ TYLKO RZECZEM, który może zrobić pilot, jest uruchomienie a tramp-find-file. Pierwsze potwierdzenie byłoby dobre, ale opcjonalne.

Po zakończeniu edycji kolejny hak może wywołać wyjście z fałszywego programu (np. Przez wysłanie C-c).

Najgorszym przypadkiem (dla bezpieczeństwa) jest to, że znajdują sposób na uruchomienie dowolnego kodu. Jeśli masz ustawione zmienne bufora, aby zawsze oceniać, złośliwy atakujący może zastąpić ważne ustawienia bez Twojej wiedzy. Mogą również przeprowadzić atak typu „odmowa usługi”, powodując otwarcie wielu buforów. Potwierdzenia mogą prawdopodobnie zapobiec wszystkim powyższym.

Program na pilocie może być trywialnie zaimplementowany w C (lub innym języku).

J David Smith
źródło
1

https://stackoverflow.com/questions/2231902/originate-edit-of-remote-file-using-emacs-tramp-from-ssh-session ma dość prostą akceptowaną odpowiedź, która wynosi

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

a następnie użyj

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

Istnieje również https://stackoverflow.com/questions/12546722/using-emacs-server-and-emacsclient-on-other-machines-as-other-users, który jest bardziej złożony, ale w którym odpowiedzi również (z grubsza) są podobne zasady.

potrójny
źródło
1

Mam mały skrypt na mojej ścieżce na zdalnym hoście w ~/bin/ec, skrót od 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[@]}"

Skrypt przechodzi -ni +argumenty pozostają niezmienione w emacsclient, w przeciwnym razie argumenty są traktowane jako pliki do otwarcia lokalnego Emacsa. Każdy plik ma prefiks protokołu TRAMP i hosta, więc Emacs wie, jak go otworzyć. ssh:Jeśli wolisz, możesz być w stanie przejść na inny protokół TRAMP.

Musisz zastąpić znazwą hosta swojego zdalnego komputera. Jest to wykorzystywane przez lokalnych Emacsa do łączenia się za pośrednictwem TRAMP. (Być może będziesz w stanie używać go hostnametutaj dla ogólności. Wolę używać małych wpisów jak zw moim lokalnym ssh_configdla zwięzłości, a pilot nie ma pojęcia, że ​​to robię. Spróbuj!)

Stosowanie:

  • ec file w zdalnej powłoce otwiera plik w lokalnym Emacsie i czeka
  • ec -n file w zdalnej powłoce otwiera plik w lokalnym Emacsie i zwraca
  • export EDITOR=~/bin/ecna odległość .bashrcsprawia, że ​​magia się dzieje

Aby upewnić się, że mój serverplik jest dobry, mam to w mojej lokalnej .emacs, ponownie używając małej nazwy hosta 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 jest zdalnym przekaźnikiem. Umieściłem to w moim lokalnym, ~/.ssh/ssh_configaby zautomatyzować przekazywanie, a także rzeczy ControlMaster dla szybkości.

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

Na koniec upewnij się, że TRAMP wie o tobie, ssh_configjeśli go używasz:

(require 'tramp)
(tramp-set-completion-function "ssh"
  '((tramp-parse-sconfig "~/.ssh/config")))
Andy
źródło
0

Może to wymagać drobnych poprawek, ale oto pomysł:

EDITOR="ssh artagnon@luneth \"emacsclient -n /`hostname`:$1\""
artagnon
źródło
1
Masz na myśli ssh'ing z powrotem ze zdalnego serwera do klienta, na którym działa Emacs? To często nie jest możliwe.
Gilles „SO- przestań być zły”
Cóż, jeśli nie możesz dotrzeć do klienta, na którym działa Emacs, nic nie możesz zrobić.
artagnon
2
Możesz poprosić ssh za pomocą ~ / .ssh / config, aby zawsze przekierowywał lokalnego odbiornika ssh do portu na zdalnym komputerze. Prawdopodobnie chciałbyś również przekazać swojego agenta ssh, choć opinie różnią się co do tego, jak bezpieczne jest to. Pozwoli ci to wrócić, wykonując EDITOR = "ssh $ user @ localhost: 1234 ..."
Ben Hyde
Inną opcją może być napisanie małego opakowania do wywołania edit-
server.el
0

Harold Abnabit wymyślił to podejście 1 :

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

1 na podstawie wcześniejszego artykułu Ryana Barretta (do którego prowadzi).

FWIW jest też https://stackoverflow.com/q/5154224/324105, w którym Petri Lehtinen wymyślił https://gist.github.com/akheron/850795 . Wyobrażam sobie, że bardziej złożone rozwiązania są lepsze, ale bardzo proste podejście może nadal być interesujące.

phils
źródło
0

Naprawdę zaskoczony, nikt sshfsjeszcze nie wspomniał . Tak zwykle robię, gdy jestem zdalny:

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

Chociaż multi-termnie synchronizuje lokalnego katalogu roboczego ze zdalnym katalogiem, przewyższa wszystkie inne rozwiązania, których wypróbowałem. Chociaż śledzenie katalogu byłoby na pewno mile widziane.

Benjamin Lindqvist
źródło