ฉันจะใช้ไคลเอ็นต์ Emacs ในพื้นที่เป็น $ EDITOR สำหรับเครื่องระยะไกลที่ฉันเข้าถึงผ่าน TRAMP ได้อย่างไร


44

ฉันมักจะใช้ TRAMP shell-modeในการจัดการเซิร์ฟเวอร์ระยะไกลหลายทั้งสำหรับการแก้ไขไฟล์และทำงานเปลือกหอยระยะไกลใน อย่างไรก็ตามสิ่งนี้ไม่ทำงานเมื่อคำสั่งใช้EDITORตัวแปรเพื่อแก้ไขไฟล์เช่นcrontab -eโดยเฉพาะอย่างยิ่งเพราะshell-modeเป็นเทอร์มินัล "dumb" ที่ไม่สนับสนุนการเรียกใช้ตัวแก้ไขอื่นภายใน

ในพื้นที่ฉันทำสิ่งนี้ด้วยการเรียกที่เหมาะสมemacsclientซึ่งเปิดบัฟเฟอร์ใหม่และทำให้ชีวิตง่ายขึ้น น่าเสียดายที่นี่ไม่สามารถใช้งานได้จากเครื่องระยะไกล

edผมคิดว่าผมสามารถใช้ (ฮะ!)

ฉันจะตั้งค่ารีโมตEDITORที่ให้ฉันแก้ไขไฟล์ด้วยอินสแตนซ์ Emacs ในพื้นที่ได้อย่างไร

คำตอบ:


23

[NOTE]คำตอบนี้ได้รับการแก้ไขอย่างหนักเพื่อติดตามการอัพเดทของwith-editorการพัฒนา ความคิดเห็นส่วนใหญ่น่าจะไม่สมเหตุสมผลอีกต่อไป มีบางความคิดเห็นใหม่ที่ทำเข้าท่า


Magitมีห้องสมุดชื่อที่with-editorให้บริการที่https://github.com/magit/with-editorซึ่งอนุญาตให้คุณใช้ Emacs ท้องถิ่นของคุณเป็น $ EDITOR บนเครื่องระยะไกลผ่าน TRAMP

อีกทางเลือกหนึ่งคือhttps://github.com/habnabit/remote-emacsclientแต่ดูเหมือนซับซ้อนและไม่ธรรมดา

วิธีที่ง่ายที่สุดในการติดตั้งwith-editorคือผ่าน MELPA:

M-x package-install with-editor

มิฉะนั้นเพียงแค่คว้าhttps://github.com/magit/with-editor/blob/master/with-editor.el ที่ใดที่หนึ่งไปยังเส้นทางโหลดของคุณและrequireมัน (ขึ้นอยู่กับเส้นประ)

จากนั้นเพียงแค่เริ่มต้นshell, eshellหรือansi-termและทำต่อไปนี้:

M-x with-editor-export-editor

มันจะถามคุณว่าคุณต้องการ $ EDITOR เพียงแค่กด Enter เพื่อหาEDITORตัวแปรเริ่มต้น จากนั้นภายในเชลล์คุณสามารถพิมพ์crontab -eและแก้ไข crontab ของคุณภายใน emacs กดC-c C-cเพื่อบันทึก crontab หรือC-c C-kเพื่อยกเลิกการแก้ไข

หากคุณต้องการตั้งค่าแบบถาวรมากขึ้น:

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

หรือคุณสามารถใช้M-x with-editor-async-shell-command crontab -e RETสำหรับคำสั่งด่วน


คุณสามารถอธิบายรายละเอียดเกี่ยวกับวิธีที่with-editorห้องสมุดนี้เกี่ยวข้องกับคำถามได้หรือไม่ เสียงมีประโยชน์
Malabarba

@Silex: ฉันจำเป็นต้องตั้งค่า$EDITORตัวแปรเป็นบางสิ่งบางอย่างในเครื่องระยะไกลเพื่อให้ทำงานได้หรือไม่ มันเป็นเพียงแค่เบ็ดemacsclient?
Tikhon Jelvis

แต่ใช่นี้ดูเหมือนว่าฉันต้องการ ฉันจะลองดูที - ฉันคิดว่ามันสามารถติดตั้งได้ด้วยตัวเองโดยไม่ต้องใช้สาขาที่เหลือ?
Tikhon Jelvis

1
@TikhonJelvi: แน่นอนมันจะสามารถติดตั้งได้ด้วยตัวเอง git-modesแต่ตอนนี้มันเป็นเพียงส่วนหนึ่งของ ฉันกำลังติดตาม lib นี้อย่างใกล้ชิดและเป็นเพียงผู้เขียน (@tarsius) ยุ่งกับการปล่อย magit แต่ในที่สุดมันก็จะเป็นแพ็คเกจของมันเอง เกี่ยวกับ $ EDITOR คุณไม่จำเป็นต้องตั้งค่าเป็นอะไรด้วยตัวเองมันทำเมื่อจำเป็นเมื่อคุณเรียกใช้คำสั่งใดก็ตามที่ใช้ Magit ใช้ lib นี้กับ $ GIT_EDITOR
Silex

1
หมายเหตุสิ่งนี้จะหยุดทำงานหลังจาก sshing ไปยังรีโมตจากภายในshell-mode/ term-modeบัฟเฟอร์ที่มีอยู่ นี้สามารถอยู่กับการกำหนดค่าบางอย่างเพิ่มเติมโปรดดูที่emacs.stackexchange.com/questions/5589/... ถ้าคุณได้รับมันในการทำงานแล้วโปรดรายงานผลการวิจัยของคุณในgithub.com/magit/magit/issues/1638
tarsius

1

คำเตือน:ฉันไม่ได้ลองสิ่งนี้

คุณสามารถเป็นส่วนหนึ่งของวิธีการโดยมีฟังก์ชั่นการส่งออกคำสั่งดูคำสั่งสำหรับการเปิดไฟล์โดยใช้ TRAMP รูโหว่หรือไม่ ใช่. การทำงาน? อาจ.

ใช้shell-modeตะขอเบ็ดที่จะเพิ่มให้ในafter-change-hook shell-modeเบ็ดนี้ดูลำดับที่เฉพาะเจาะจง ตัวอย่าง:

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

จากนั้นใช้tramp-find-fileเพื่อเปิดไฟล์ tramp-find-fileนี้ค่อนข้างปลอดภัยเพราะสิ่งเดียวที่ระยะไกลสามารถทำได้คือทริกเกอร์ การยืนยันก่อนจะดี แต่ไม่บังคับ

เมื่อแก้ไขเสร็จแล้วฮุกอื่นสามารถเปิดการออกจากโปรแกรมจำลอง (เช่นโดยการส่งC-c)

กรณีที่เลวร้ายที่สุด (เพื่อความปลอดภัย) คือพวกเขาหาวิธีเรียกใช้รหัสโดยอำเภอใจ หากคุณมีการตั้งค่าตัวแปรบัฟเฟอร์ไว้เสมอผู้โจมตีประสงค์ร้ายสามารถเขียนทับการตั้งค่าที่สำคัญโดยที่คุณไม่รู้ตัว พวกเขายังสามารถเปิดการปฏิเสธการโจมตีบริการโดยทำให้บัฟเฟอร์จำนวนมากเปิด การยืนยันอาจป้องกันการทั้งหมดข้างต้น

โปรแกรมบนรีโมทสามารถนำไปใช้งานได้เล็กน้อยใน C (หรือภาษาอื่น ๆ )


1

https://stackoverflow.com/questions/2231902/originate-edit-of-remote-file-using-emacs-tramp-from-ssh-sessionมีคำตอบที่ยอมรับได้ค่อนข้างง่ายซึ่งมีจำนวน

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

จากนั้นใช้

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

นอกจากนี้ยังมีhttps://stackoverflow.com/questions/12546722/using-emacs-server-and-emacsclient-on-other-machines-as-other-usersซึ่งมีความซับซ้อนมากขึ้น แต่ที่คำตอบ (ประมาณ) สัมผัสคล้ายกัน ฐาน


1

ฉันมีสคริปต์เล็ก ๆ ในเส้นทางของฉันบนโฮสต์ระยะไกลที่~/bin/ecจดชวเลขสำหรับ 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[@]}"

สคริปต์นี้ผ่าน-nและ+args ไม่เปลี่ยนแปลงเป็น emacsclient มิฉะนั้น args จะถือว่าเป็นไฟล์เพื่อให้ Emacs ในพื้นที่ของคุณเปิด แต่ละไฟล์จะขึ้นต้นด้วยโพรโทคอล TRAMP และโฮสต์เพื่อให้ Emacs รู้วิธีเปิด คุณอาจเปลี่ยนssh:เป็นโปรโตคอล TRAMP อื่นได้หากต้องการ

คุณต้องแทนที่zด้วยชื่อโฮสต์ของเครื่องระยะไกลของคุณ Emacs ในพื้นที่นี้ใช้สำหรับเชื่อมต่อผ่าน TRAMP (คุณอาจจะสามารถใช้hostnameที่นี่เพื่อทั่วไปฉันชอบที่จะใช้รายการเล็ก ๆ เช่นzในท้องถิ่นของฉันssh_configเพื่อความกะทัดรัดและห่างไกลก็ไม่รู้ว่าฉันกำลังทำอะไรอยู่ลองดูสิ!)

การใช้งาน:

  • ec file ในเปลือกระยะไกลเปิดไฟล์ใน Emacs ท้องถิ่นและรอ
  • ec -n file ในเปลือกระยะไกลเปิดไฟล์ใน Emacs ท้องถิ่นและส่งกลับ
  • export EDITOR=~/bin/ecในระยะไกล.bashrcทำให้ความมหัศจรรย์เกิดขึ้น

เพื่อให้แน่ใจว่าserverไฟล์ของฉันดีฉันมีในท้องถิ่นของฉัน.emacsอีกครั้งโดยใช้ชื่อโฮสต์เล็ก ๆ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)

พอร์ต 9999 เป็น RemoteForward ฉันใส่สิ่งนี้ไว้ในพื้นที่ของฉัน~/.ssh/ssh_configเพื่อทำการส่งต่อโดยอัตโนมัติรวมถึงสิ่งที่ ControlMaster ใช้เพื่อความรวดเร็ว

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

สุดท้ายตรวจสอบให้แน่ใจว่า TRAMP ทราบเกี่ยวกับตัวคุณssh_configหากคุณใช้:

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

0

อาจต้องปรับแต่งเล็กน้อย แต่นี่คือความคิด:

EDITOR="ssh artagnon@luneth \"emacsclient -n /`hostname`:$1\""

1
คุณหมายถึงกำลังกลับจากเซิร์ฟเวอร์ระยะไกลไปยังไคลเอนต์ที่ Emacs กำลังทำงานอยู่หรือไม่? ที่มักจะเป็นไปไม่ได้
Gilles 'หยุดชั่วร้าย'

ถ้าคุณไม่สามารถติดต่อลูกค้าที่ Emacs กำลังทำงานอยู่มันเป็นไปไม่ได้เลยที่จะทำอะไร
artagnon

2
คุณสามารถถาม ssh ผ่านทาง ~ / .ssh / config เพื่อส่งต่อผู้ฟัง ssh ท้องถิ่นไปยังพอร์ตบนเครื่องระยะไกล คุณอาจต้องการส่งต่อตัวแทน SSH ของคุณด้วยเช่นกันแม้ว่าความคิดเห็นจะแตกต่างกันไปตามความปลอดภัยของมัน สิ่งนี้จะช่วยให้คุณสามารถกลับมาใช้ EDITOR = "ssh $ user @ localhost: 1234 ... "
Ben Hyde

อีกตัวเลือกหนึ่งอาจจะเขียนกระดาษห่อขนาดเล็กเพื่อแก้ไขโทร-server.el
stsquad

0

Harold Abnabit เกิดขึ้นด้วยวิธีนี้1 :

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

1อ้างอิงจากบทความก่อนหน้าโดย Ryan Barrett (ซึ่งเขาลิงก์)

FWIW ยังมีhttps://stackoverflow.com/q/5154224/324105ซึ่ง Petri Lehtinen ขึ้นมาด้วยhttps://gist.github.com/akheron/850795 ฉันคิดว่าการแก้ปัญหาที่ซับซ้อนมากขึ้นนั้นดีกว่า แต่วิธีการง่ายๆอาจยังคงเป็นที่สนใจ


0

ประหลาดใจจริงๆไม่มีใครได้กล่าวถึงsshfsเลย นี่คือสิ่งที่ฉันมักจะทำเมื่อฉันไปไกล:

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

แม้ว่าmulti-termจะไม่ซิงค์ dir ที่ทำงานในท้องถิ่นกับ dir จากระยะไกล แต่มันก็เอาชนะโซลูชันอื่น ๆ ทั้งหมดที่ฉันได้ลองใช้โดยใช้เวลานาน แม้ว่าการติดตาม dir จะเป็นคุณสมบัติต้อนรับอย่างแน่นอน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.