VPNの表示が緑になり、経路も戻ったのに、開いたままのSSHウィンドウにはプロンプトが戻ってこない。経路を復元しても、それを使っていたTCPの会話は復元されないので、そのウィンドウに入力した内容は失われている。本当の関心がエディタのバッファや長時間の移行作業なら、その作業を一本の接続に結び付けないことが解決策だ。tmuxとジョブ実行基盤は、その問題の別々の半分を解く。

再接続したVPNはソケットを再開しない

TCPにはアドレス変更後に再開するという考えがない。SSH接続は両端で識別され、トンネルが作り直されるとローカルアドレスが変わり、古いソケットは死んでいる。サーバーはやがて気づくが、端末はすぐに気づく。

クライアント側のkeepaliveは死んだ相手をより早く検出する。セッションを戻すことはなく、すでに動いていたコマンドを復旧することもできない。keepaliveは検出器であり、復旧ツールではない。遠隔のコマンドが生き延びたかどうかは何も語らない。

作業はリモートホストに置く

セッションはノートPCではなくリモートホストで作る。いつも通り接続し、そこでtmuxを起動して、その中でエディタや移行作業を動かす。既定のプレフィックスでデタッチすれば、SSH接続が消えてもセッションは動き続ける。ローカルでtmuxを起動しても、閉じたウィンドウからシェルを守るだけで、死んだトンネルから遠隔コマンドを守るわけではない。

ssh [email protected]
tmux new-session -s office-work

VPNが戻ったら、同じホストへ新しいSSH接続を開き、名前で再アタッチする。永続する対象はセッションであり、接続ではない。一週間後でも分かる名前を付けておく。

tmuxとジョブ実行基盤の違い

tmuxはホストが動いている間、対話的なプロセスを生かし続ける。ジョブ実行基盤やサービスマネージャーは非対話のジョブを生かし続け、終了ステータスを記録し、SSHセッションが完全に終わっても耐える。前者は自分で見る作業向けで、後者は予約して後から確認する作業向けだ。

どちらも、ホストが復元するよう設定されていなければ再起動では生き残らない。tmuxセッションはマシンと共に死に、一時的なジョブはユニットとして登録されていなければ起動と共に死ぬ。何を長生きさせる必要があるかで選ぶ。

どちらの方法にも、再接続後に読めるログが必要だ。それがなければ、プロセスが存在することは分かっても、何をしたかは分からない。ログのパスをセッション名の横に書き留めておく。

何が生き残るべきかで決める

作業が途中で止まったときに起きうる最悪の事態で決める。エディタのセッションは保存していないバッファを失うが、それは煩わしいものの復旧できる。変更の半分をコミットする移行作業はそうではなく、結果が記録される実行基盤に軍配が上がる。ジョブが対話的で長いなら、tmuxと記録されたログでたいてい足りる。

systemd-run --user --unit=migrate-customers --collect ./migrate.sh

何を選ぶにせよ、何かを再実行する前に記録された結果を確認する。最後の行が欠けていれば、サーバーが何をコミットしたかではなく、ノートPCが何を見たかが分かる。その区別こそ、作業を最初から接続の外に置く理由であり、デタッチと再アタッチのモデルはその最小の形だ。

関連記事