如何告诉 Emacs TRAMP 对 ssh 使用特定参数?

Rya*_*son 7 ssh emacs command-line-arguments tramp

我正在尝试设置我的 Emacs TRAMP 以通过 ssh 访问远程文件,并且我想向 tramp 用于连接的 ssh 命令添加一些额外的参数。有没有办法做到这一点?

我可以通过直接操作变量来做到这一点tramp-methods,但这很麻烦。

Rya*_*son 5

我想出了自己的解决方案,但在这里发布有点太复杂了。如果有人感兴趣,请对此答案发表评论,我会找地方张贴。


编辑:这是我的解决方案,根据要求。

现在,设置一些函数以附加到存储在的内置参数列表中tramp-methods

(defun tramp-get-method-parameter (method param)
  "Return the method parameter PARAM.
If the `tramp-methods' entry does not exist, return NIL."
  (let ((entry (assoc param (assoc method tramp-methods))))
    (when entry (cadr entry))))

(defun tramp-set-method-parameter (method param newvalue)
  "Set the method paramter PARAM to VALUE for METHOD.

If METHOD does not yet have PARAM, add it.
If METHOD does not exist, do nothing."
  (let ((method-params (assoc method tramp-methods)))
    (when method-params
          (let ((entry (assoc param method-params)))
        (if entry
            (setcar (cdr entry) newvalue)
          (setcdr (last method-params) '(param newvalue)))))))

(defun tramp-add-args (programs newargs)
  "Append NEWARGS to the argument list for any of PROGRAMS in `tramp-methods'.

PROGRAMS can be a list of strings, or a single string."
  ;; Allow a single program string or a list of matching programs.
  (when (stringp programs)
    (setq programs (list programs)))
  (message "%s" (list programs newargs))
  (loop for method in (mapcar 'car tramp-methods) do
        (let ((login-program (tramp-get-method-parameter method 'tramp-login-program))
              (copy-program (tramp-get-method-parameter method 'tramp-copy-program))
              (login-args (tramp-get-method-parameter method 'tramp-login-args))
              (copy-args (tramp-get-method-parameter method 'tramp-copy-args)))
          (message "Handling %s" method)
          (message "  Handling login program %s" login-program)
          (when (find login-program programs :test 'string=)
            (message "    Adding to login program %s" login-program)
            (tramp-set-method-parameter method 'tramp-login-args (append login-args newargs)))
          (message "  Handling copy program %s" login-program)
          (when (find copy-program programs :test 'string=)
            (message "    Adding to copy program %s" copy-program)
            (tramp-set-method-parameter method 'tramp-copy-args (append copy-args newargs))))))
Run Code Online (Sandbox Code Playgroud)

最后,使用tramp-add-args将您想要的参数添加到所有基于 ssh 的方法中:

(tramp-add-args
 '("scp" "scp1" "scp2" "scp1_old" "scp2_old" "sftp" "rsync" "ssh" "ssh1" "ssh2" "ssh1_old" "ssh2_old" "scpx" "sshx")
 '(("-o" "ControlPath=~/.ssh/control/emacs-master-%%r@%%h:%%p" "-o" "ControlMaster=auto")))
Run Code Online (Sandbox Code Playgroud)

奖金回合

我上面显示的代码为 ssh 设置了连接共享。如果您希望它可靠地工作,则需要在 Internet 连接中断时清除套接字文件。以下可以实现这一点

首先,创建一个名为的脚本ssh-cleanup并将其放入您的$PATH并将以下内容放入其中:

#!/bin/sh
CONTROL_DIR="$HOME/.ssh/control"
find "$CONTROL_DIR" -type s | xargs --no-run-if-empty -- rm -f
Run Code Online (Sandbox Code Playgroud)

该脚本清除陈旧的控制文件,因为当 ssh 因您拔掉网络电缆或断开无线连接而终止时,这些文件将被遗留下来。

现在设置 emacs 以在适当的时间运行此脚本:

(defun ssh-cleanup ()
  (ignore-errors
    (call-process "ssh-cleanup")))

(defadvice tramp-cleanup-all-connections (after cleanup-control-files activate)
  (ssh-cleanup))
Run Code Online (Sandbox Code Playgroud)

现在,当您运行 时tramp-cleanup-all-connections,您还将清理 ssh 套接字目录。每当您断开连接并重新连接到互联网时,您都应该运行它。

或者,您可以将计算机设置为自动为您执行此操作。

超级奖金回合

如果您在 Linux 上使用网络管理器,您可以让 emacs 在您连接或断开连接时为您做一些事情。

(defcustom network-manager-connect-hook nil
  "List of functions to execute upon successful establishment of
  a network connection."
  :type 'hook
  :group 'network-manager)

(defcustom network-manager-disconnect-hook nil
  "List of functions to execute upon disconnection from the
  network."
  :type 'hook
  :group 'network-manager)

;; Only enable all of this if dbus is found
(when (require 'dbus nil nil)

  (defun network-manager-dbus-signal-handler (nmstate)
    "Execute the appropriate hook when Network Manager connects or
  disconnects."
    (case nmstate
      ((4 1) (run-hooks 'network-manager-disconnect-hook))
      (3 (run-hooks 'network-manager-connect-hook))))

  (defvar network-manager-dbus-registration nil)

  (defun network-manager-integration-enable ()
    (interactive)
    (network-manager-integration-disable) ; Make sure to clean up first
    (setq network-manager-dbus-registration
          (dbus-register-signal :system
                                "org.freedesktop.NetworkManager" "/org/freedesktop/NetworkManager"
                                "org.freedesktop.NetworkManager" "StateChanged"
                                'network-manager-dbus-signal-handler)))

  (defun network-manager-integration-disable ()
    (interactive)
    (when network-manager-dbus-registration
      (dbus-unregister-object network-manager-dbus-registration)
      (setq network-manager-dbus-registration nil)))

  ;; Finally, enable it
  (network-manager-integration-enable))
Run Code Online (Sandbox Code Playgroud)

现在添加 settramp-cleanup-all-connections以在断开连接时运行。

(add-hook 'network-manager-disconnect-hook 'tramp-cleanup-all-connections)
Run Code Online (Sandbox Code Playgroud)