WP-CLI を SSH 越しに何度も実行すると、コマンドそのものより前の「接続の確立」に時間を取られていることに気づきます。1回ごとに TCP 接続、鍵交換、認証をやり直しているためです。
OpenSSH には、一度確立した接続を使い回す ControlMaster(接続の多重化)という仕組みがあります。この記事では、何が起きているのか、設定の書き方、注意点を、実サーバーで測った数値とあわせて整理します。
補足: 測定は手元の Mac(OpenSSH 10.2)から国内のレンタルサーバーへ、
trueコマンドを繰り返し実行して行いました。回線やサーバーによって数値は変わるため、あくまで一例として読んでください。
SSH 接続のたびに何をしているか
ssh host command を実行するたびに、次の手順が最初から行われます。
- TCP 接続を開く
- 暗号化方式を交渉し、鍵を交換する
- サーバーを確認し、公開鍵で認証する
- セッションを開き、コマンドを実行する
実際に作業したいのは4だけですが、1〜3 は毎回かかります。1回あたりは気にならなくても、スクリプトから何十回も呼ぶと、待ち時間の大半がここになります。
ControlMaster の考え方
ControlMaster は、最初の接続を「親(マスター)」として残し、2回目以降のコマンドをその接続の上に相乗りさせる仕組みです。
- 最初の
sshが接続を張り、手元に 制御用のソケットファイルを作る - 2回目以降の
sshは、そのソケット経由で既存の接続にセッションだけを追加する - 新たな鍵交換や認証は行われない
つまり、1〜3 を最初の1回だけに減らす設定です。
設定の書き方
~/.ssh/config に、ホストごとに次のように書きます。ホスト名・ユーザー名・鍵のパスは例です。
Host myserver
HostName example.com
User deploy
IdentityFile ~/.ssh/example_key
ControlMaster auto
ControlPath ~/.ssh/cm-%C
ControlPersist 60
- ControlMaster auto: ソケットがなければ自分がマスターになり、あれば相乗りする
- ControlPath: ソケットファイルの置き場所。
%Cは接続先情報から作られるハッシュで、ホストごとに別のパスになる - ControlPersist 60: 最後のセッションが終わっても、マスター接続を60秒だけ裏で残す
ControlPersist が重要です。これがないと、最初のセッションが終わった時点でマスターも終了し、次のコマンドは再び新規接続になってしまいます。
ControlPath のパスは長すぎるとエラーになることがあります(ソケットのパス長には OS ごとの上限があります)。%C を使うと短く収まります。
実測してみた
同じサーバーへ true を5回続けて実行し、合計時間を測りました(1回の測定です)。
| 条件 | 5回の合計 |
|---|---|
| 多重化なし | 2.64秒 |
| 多重化あり(ControlPersist 30) | 0.83秒 |
5回のうち、多重化ありで本当に接続を張ったのは最初の1回だけです。残りは既存の接続に乗るだけなので、1回あたりの時間が小さくなりました。
一方、WP-CLI(wp option get blogname)を3回続けた場合は次のとおりでした。
| 条件 | 3回の合計 |
|---|---|
| 多重化なし | 3.36秒 |
| 多重化あり | 2.64秒 |
差は小さくなっています。WP-CLI 自体が PHP を起動して WordPress を読み込む時間を使うため、接続の確立分を省いても、全体に占める割合が下がるためです。多重化で省けるのは接続の確立ぶんだけで、コマンド本体の実行時間は変わりません。短いコマンドを何度も呼ぶ場面ほど効果が見えやすい、という理解が実態に近いと思います。
状態の確認と終了
マスター接続が生きているかは -O check、明示的に終了するには -O exit で操作できます。
ssh -O check myserver
ssh -O exit myserver
測定の際にも、終わったら -O exit でマスターを止めています。
気をつけたい点
- ソケットファイルの扱い: ソケットを持っている人は、その接続を使える状態になります。置き場所は自分だけが読み書きできるディレクトリにし、共用の場所には置かないのが原則です。
- 古いソケットが残る: 異常終了でソケットが残ると、接続に失敗することがあります。その場合はソケットファイルを削除してから再接続します。
- 接続が切れると全部影響する: 相乗りしているセッションは、マスターが落ちると一緒に切れます。長時間の作業や大きなファイル転送は、別接続に分けたほうが安心な場面もあります。
- ControlPersist を長くしすぎない: 放置した接続が残り続けるため、数十秒〜数分程度にとどめるのが無難です。
- 認証や設定を変えた直後: マスターが古い設定のまま残っていると、新しい設定が反映されないように見えます。
-O exitで止めてから試してください。
まとめ
- SSH は接続のたびに、TCP・鍵交換・認証をやり直している。
- ControlMaster は最初の接続を使い回し、2回目以降のその手順を省く。
ControlMaster auto・ControlPath・ControlPersistの3つを~/.ssh/configに書くのが基本。- 実測では、短いコマンド5回で 2.64秒 → 0.83秒。ただし WP-CLI のように実行自体が重いコマンドでは差が小さくなる。
- ソケットの置き場所と、マスター切断時の影響に気をつける。
複数サーバーを扱うなら、まず「~/.ssh/config でホスト別設定を整理する」で設定を整えたうえで、接続を繰り返すホストにだけ多重化を足してみてください。