Daydreaming in Brookline, MA

emacs+tramp-modeでシームレスにリモートワークする

1 はじめに

現在の職場では、各エンジニアにLinux(Fedora)の入ったデスクトップPCとノートPCが与えられています。COVIDのためにリモートワークとなって以来、私はノートPC(MacBookを選びました)のみアパートに持ち帰り、デスクトップPCはVPN経由でsshで入って使っていました。

emacsのいいところは、それがターミナル上で動くCUIアプリケーションとしても動くことで、sshで入ったリモートマシン上でもほぼ全ての機能がそのまま使えるところです。仕事で使うPythonスクリプトの開発も普通に行なえます。

2 trampモード

しかし、emacsにはtramp-modeという強力な機能が標準で備わっていることを最近知りました。trampを使うと、リモートマシン上のファイルをまるでそれらがローカルにあるかのように扱えます。しかも、diredやmagitもシームレスに動作するようなのです。emacsのキラーアプリであるorg-modeも、もちろんそのまま使えます(.org は単なるテキストファイルなので)。これは試してみるしかありません。

2.1 インストール

ここ に前提が書かれています。また、trampでつなげる対象のリモートマシンに対するsshの設定をしておいてください。パスワード無しでsshできるようにしておくと便利と思います。

パッケージインストールは簡単です。

M-x list-packages

でパッケージリストを表示し、 tramp をサーチして、 i > x でインストールします。 M-x package-install > tramp でもOKです。

2.2 使ってみる

リモートのファイルが開けるか確認します。 C-x C-f > /ssh:<user>@<host>:/path/to/file で、ちょっとしたタイムラグがあり、普通にリモートのファイルが開けます。diredでも同様です。 C-x d > /ssh:<user>@<host>:/path/to/direcroty で行けます。拍子抜けなほどあっけなく成功しました。

sudo でファイルやディレクトリを開く場合には、

/ssh:<user>@<host>|sudo::/path/to/file

のように指定します。操作の途中でパスワードを聞かれます。

WindowsのPuTTYでは、 /ssh の代わりに /plink を指定するそうです。他にもいくつかのプロトコルがサポートされています。詳しくは ここ を参照ください。

2.2.1 magit

magitはgit操作をemacs上で行う、emacsのキラーアプリの一つです。ものすごく便利で、私も毎日のように使っています。git管理対象のリモートファイルを開いているときに、普通に M-x g でmagit-status (git status相当)をします。そしていつものように s (stage) > c c (commit)でコミットメッセージを入力し、 C-c C-c コミットします。その後、やはりいつものように P u (push)でプッシュしたら、何事もなく動いてしまいました。これはすごいです!

2.2.2 org-mode

emacsのもう一つのキラーアプリです。このブログもorg-modeを使って書いています。 .org は単なるテキストファイルなので、全くシームレスにtramp-modeが使えます。

2.2.3 ブックマーク

trampは便利ですが、毎回 C-x C-f 等でリモートホスト+ファイルやディレクトリを指定するのが少し面倒です。そこで、emacsの ブックマーク機能 を使います。

  • C-x r m: ブックマークする
  • C-x r l: ブックマークをリストする
  • M-x bookmark-delete: ブックマークを消す。ブックマークをリストして d > x でも行けます

これがものすごく便利で、tramp-modeとの相性が抜群です。

2.2.4 shell mode

trampはemacsのshell-mode(M-x shell)でも動きますが、companyのオートコンプリート(グローバルで設定している)が編集をブロックして使いものにならないので抑止します。

(add-hook 'shell-mode-hook (lambda () (company-mode -1)) 'append)
(add-hook 'eshell-mode-hook (lambda () (company-mode -1)) 'append)  # eshell用

しばらくshell modeを使ったところ、fedora VMにsshした時に、cd (change directory)をしてもプロンプトが変わらないことに気が付きました。また、trampが設定するプロンプトは長すぎるので、短くしたいです。そこで、以下のような変更をFedora VMの .bashrc に入れました。

# Reset the prompt for remote TRAMP shells.
if [ ! "$INSIDE_EMACS" = "" ] ;then
  PS1="[\u@\h \w]$ "
fi

なお、shellモードでは C-p を押すと、bashのヒストリー機能が使えず、カーソルが上に行ってしまいます。bashの C-p に対応するshellモードでのキーは M-p です。同様に、 M-nM-r が使えます。

2.2.5 Python開発

elpyはtrampをサポートしていないようなので、私は 前回のエントリ で書いたようにeglot + python-lsp-serverに移行しました。eglotからは pylsp が見つかりさえすれば普通に動くようです。私の環境ではフルパスで指定しない限り pylsp が見つからないエラーが出ていたので、以下をinit.elに設定しました。

(add-to-list 'tramp-remote-path 'tramp-own-remote-path)

2.2.6 スリープからの復帰

編集中のファイルをセーブせずにMacBook Proのふたを閉じて数十分放置した後でどうなるか試してみました。リモートPCにはVPN接続していますが、スリープすると切れてしまいます。再度VPNを2段階認証してつなぎ、 C-x C-s でセーブしようとすると、しばらく頑張った後で以下のメッセージが出ました。

It has been detected that you want to modify a file that someone else has already started modifying in Emacs.

You can <s>teal the file; the other user becomes the intruder if (s)he ever unmodifies the file and the changes it again. You can <p>roceed; you edit at your own (and the other user's) risk. You can <q>uit; don't modify this file.

<s>と<p>の違いがよくわかりませんが、試しに<s>を押したところ、うまくセーブできました。<s>はロックを奪い、<p>はロックを取らずにセーブするということに見えます。この解釈が正しいとすると、<s>が正しいように思います。

一方で、MacBook上で動いているFedora VMへのssh接続は、Macのスリープに影響されませんでした。スリープ解除後、何事もなかったかのように普通に継続編集やセーブができます。ホストとゲストが同時にスリープ、解除となることで、セッション切れが起きないようです。

完全なシームレスではありませんが、trampはスリープからの復帰に対して、比較的うまく対応してくれることがわかりました。

2.2.7 ファイルコピーが遅い

diredの操作でローカルとリモートのファイルコピーに時間がかかり、その間 emacs をブロックする問題があるそうです。私はまだ困っていないので試していませんが、いくつか ソリューションがある ようです。

2.3 地球の反対側から使ってみる

日本に一時帰国する機会がありましたので、日本からボストン近郊にあるオフィスのFedora PCに対して(VPN経由で)trampを使ってみました。結論から言うと、相当に忍耐を要するレベルで遅いです。dired、shellモード、ファイルの編集、magitそれぞれがとても遅い。

まずは、最初にファイル等を開くまでが遅く、その後もリモートに対して何かをしにいく度に固まります。遅い以外には大きな問題はまだ起きていませんが、普通の人は投げ出すレベルで遅いです。

sshで入ってリモートマシンでemacsを開いたり、gitをコマンドラインで使うとそこまで遅くはないので、国をまたいでリモートマシンに入る場合には、素直にsshした方が良さそうです。個人的に、少し残念な結果となりました。

3 おわりに

これまで、リモートマシンにsshで入ってemacsを使うことで満足していましたが、tramp-modeを使ってあたかもローカルで作業しているかのようにリモートファイルを扱うやり方は、より便利だと感じました。 ターミナルやVMのデスクトップGUIを行ったり来たりする必要がなく、mac上のemacsで全て閉じることがとても快適です。

しかしここまで来ると、逆にMacBookだけあればいいような気もしてきます。大事なデータはgitlab等にもあり、処理能力を必要とするビルドはビルドサーバーがやります(私は使っていませんが)。デスクトップPCのうれしさは複数の大きなディスプレイが使えることにもありますが、自宅からのリモートアクセスではその恩恵にあずかることができません。

しばらく考えてみたところ、オフィスのデスクトップPC(Linux)はリモートワークにおいて以下の用途で使えそうです。

  • 会社貸与のノートPCではセキュリティ的に厳しい環境を作ることができる(これはノートPC上でVMを動かしても。。。。ごにょごにょ)
  • cronデーモンで定期的にタスクを実行できる(例: サーバー監視スクリプト)
  • 24時間稼働、ノートPCより豊富なリソースをいかし、自分だけの自由な実験環境として使える
    • 複数VMでクラスタを構成(例: ceph)
    • ネイティブなDocker実行環境
    • これらを使った長時間実験