web-dev-qa-db-ja.com

sshに特定の引数を使用するようにEmacsTRAMPに指示するにはどうすればよいですか?

Ssh経由でリモートファイルにアクセスするようにEmacsTRAMPを設定しようとしていますが、trampが接続に使用するsshコマンドにいくつかの引数を追加したいと思います。これを行う方法はありますか?

変数tramp-methodsを直接操作することでそれを行うことができますが、それは厄介です。

7

私は自分の解決策を思いついたが、ここに投稿するには少し複雑すぎる。興味のある方は、この回答にコメントしてください。どこかに投稿します。


編集:要求に応じて、これが私の解決策です。

次に、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))))))

最後に、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")))

ボーナスラウンド

上に示したコードは、sshの接続共有を設定します。これを確実に機能させるには、インターネット接続がダウンしたときにソケットファイルをクリアする必要があります。以下はこれを達成することができます

まず、ssh-cleanupというスクリプトを作成し、それを$PATHに入れて、次のように入れます。

#!/bin/sh
CONTROL_DIR="$HOME/.ssh/control"
find "$CONTROL_DIR" -type s | xargs --no-run-if-empty -- rm -f

このスクリプトは、古い制御ファイルをクリーンアップします。これは、ネットワークケーブルを抜いたか、ワイヤレスを切断したためにsshが停止すると、これらのファイルが取り残されるためです。

次に、適切なタイミングでこのスクリプトを実行するようにemacsを設定します。

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

(defadvice tramp-cleanup-all-connections (after cleanup-control-files activate)
  (ssh-cleanup))

ここで、tramp-cleanup-all-connectionsを実行すると、sshソケットディレクトリもクリーンアップされます。インターネットを切断して再接続するときはいつでも、これを実行する必要があります。

または、自動的に実行するようにコンピューターを設定することもできます。

スーパーボーナスラウンド

LinuxでNetworkManagerを使用している場合は、接続または切断したときに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))

次に、切断時に実行するセットtramp-cleanup-all-connectionsを追加します。

(add-hook 'network-manager-disconnect-hook 'tramp-cleanup-all-connections)
5

一度だけ使うと便利な方法が思いつかない。

より永続的なセットアップを行うには、sshレベルで構成を行います(これには、Emacsの外部で作業するという副次的な利点もあります)。 ~/.ssh/configで、追加のオプションを使用してホストエイリアスを定義し、Trampを使用してエイリアスに接続します。例えば。 ~/.ssh/config

Host foo
HostName foo.example.com
User rt
ProxyCommand /usr/bin/nc -X connect -x proxy:3128 %h %p

次に、Emacsで/ssh:foo:/path/to/fileを開きます。