morimorihogeです.新年一発目の投稿です.最近木曾が改二になりました.
Web開発に限らず,UNIX系で動作するシステムの開発・運用に携わっていると常にターミナルクライアントを開いているということが多いかと思います.Web開発やサーバインフラの構築・運用をやっていると,自分のローカルPCだけではなく,リモート上の別マシンに接続し,テストサーバや本番サーバでコマンドを打って作業する機会が多くなります.
そんな中「ローカルマシンのコンソールだと思ってrmしたら実は本番系サーバだった」「なんか色々実行してて処理が怪しいなと思ったら別のサーバだった」という思いをしたことがあるのは僕一人だけじゃないと思います.
今回はこういった問題を防止するために僕が普段から守っているターミナルの運用ポリシを紹介してみようと思います.あまり技術的な話はないですが,普段開発・運用を仕事としてしていく上でのノウハウです.
タブ機能のあるターミナルクライアントソフトを使い,同時に開くウィンドウを一つにする
ターミナルクライアントのウィンドウは原則1つに集約するため,タブ切替機能のあるソフトを使います.Mac環境であればOS標準のターミナルが今はタブ対応していますし,iTerm2の様な別ソフトを使うこともできます.Windowsはここ最近の事情は詳しくないのですが,Poderosaがまだ人気があるのでしょうか.ちなみに僕はiTerm2派ですが,これはMac OS Xの標準ターミナルがタブ対応していなかった頃に使っていたのでそれを惰性で使い続けているだけです.
ターミナルクライアントのウィンドウを一つしか開かないようにすると「あ,このウィンドウってどのサーバにログインしてたっけ?」とか,Command+Tab(WindowsならAlt+Tab)でウィンドウを切替ながら作業しているときに,間違って他の端末を叩いてしまう危険性が減ります.
複数サーバのログをリアルタイム監視したいなど,例外的に二つ以上のウィンドウを並べてみたいということはありますが,そういうときは妥協しても良いと思います(ターミナルクライアントの画面分割機能やscreen/tmux使えという話もあるでしょう).とにかく大事なのは「原則」1つのウィンドウで使うということです.複数ウィンドウで作業していても,その場合は用途が終わったら必ず一つのウィンドウを残して閉じるように心がけます.
各タブへのショートカットキーを定義し,タブに意味づけをする
次はタブ運用の話です.まずは複数タブになったときにタブ間を移動出来るショートカットキーを設定します.
この際に注意なのは「相対移動のショートカットを使わず,絶対移動のショートカットを使う」ということです.相対移動のショートカットとは「一つ右のタブに切り替え」や「一つ前に開いていたタブに切り替え」のことです.一方絶対移動は「1つめのタブに切り替え」「4つめのタブに切り替え」ですね.
iTerm2だと,Command + 数字キーで左からN番目のタブを選択できます.とりあえず9個まではこれで問題無いですね.10個以上開くことはないわけではないですが,それほど多いことではないので今のところ気にしていません.
次に,タブに意味づけをします.僕の場合「1つめのタブ(一番左のタブ)はローカルマシン上の作業専用にし,リモートログインには使用しない」「2つめ以降のタブはリモートログイン作業専用に使う」の二つを守っています.
これにより,ターミナルクライアントがどんなタブを開いていようが「Command + 1を押せば必ずローカルのターミナルにアクセスできる」という状態が約束されます.
ちなみに,iTerm2ではタブ切り替えのための装飾キーを設定から変更することができます.
1つの接続先に対しては1つのタブしか割り当てない
最後に各タブの中の運用になります.ここでは「1接続先につきタブ一つ」を原則とします.サーバ構築をしていると,一般ユーザ,deploy用ユーザ,rootなどを渡り歩いて作業することが多くありますが,このときには「同じサーバに対して複数のシェルが欲しい場合,screen/tmuxを使ってタブは1枚に集約する」というルールを適用します.
tmuxについては弊社yamasitaのできるtmux-5分でわかる?仮想端末入門-を読んでもらうとして,screenを知らない人は,tmuxよりも昔から使われているtmuxみたいな奴という認識をしておけば良いと思います.
tmuxに乗り換えたいなーと思いつつも昔から使っているscreenを使い続けているだけです
また,screenのウィンドウを運用する際にもポリシがあり,0番は必ずログインしたユーザのシェルにします(sudoしない).別のユーザのシェルを使う場合は,別のscreenウィンドウを開いてsudoします.さらに言うと,rootは何かと良く使うので,1番のscreenウィンドウはroot用に使うことが多いです.
こうすることで「表示しているターミナルでscreenが動いていた場合,ctrl+z 0をすれば必ずユーザのシェルになる(rootではない)」ことが保証されます.また,screenセッションを残したままscreenをdetachするときは「rootシェルを開いたままdetachしない(原則rootシェルはdetach前にログアウトする)」というポリシで運用します.
踏み台経由でアクセスしないといけないサーバには,.ssh/configを書いてローカルから1コマンドでログインする
AWS VPCを使って複数台のサーバを使ったシステムの構築などをしていると,DBサーバなどの直接インターネットに接続しないホストに対して繋ぐためには踏み台サーバを経由することがあります.
こういった時に,特に何も考えないのであれば,一度踏み台サーバにsshして,そこからターゲットマシンに対してさらにsshすると思います.
ただ,このやり方には「踏み台サーバーターゲットマシン間のsshセッションが切断されたとき,踏み台サーバにログインしているsshコンソールが残る」という問題があります.ターゲットマシンで作業をしていて少し作業を中断した後戻ってきた際,いつの間にかsshセッションが切断されていて,踏み台サーバで間違ってターゲットマシンで実行するコマンドを叩いてしまった,という事故の原因になります.
こうした事故を防止するため,踏み台経由アクセスをする場合には以下の様な設定をローカルマシンの.ssh/configに記述して接続します.
Host target.example.com
HostName 192.168.123.123
ProxyCommand ssh fumidai.example.com nc %h %p
これで「ssh target.example.com」とすれば,fumidaiに一旦接続した後にtargetに接続することができます.この方式で接続した場合,targetとfumidai間のsshセッションが切れると自動的にローカルーfumidai間のセッションも切断されるので,意図せずfumidaiのsshコンソールが開かれた状態になることはありません.
ちなみに,多段で踏み台を踏まないといけない場合は,
Host fumidai2.example.com
HostName 192.168.123.123
ProxyCommand ssh fumidai1.example.com nc %h %p
Host target.example.com
HostName 10.0.0.123
ProxyCommand ssh fumidai2.example.com nc %h %p
と書けば「ローカルマシン -> fumidai1 -> fumidai2 -> target」と接続できます.稀にncコマンドが入っていないホストがいたりしますが,そういった場合にはroot権限が無くてもbusyboxをホームディレクトリに置いて使えば解決します.
まとめ
ここまでに書いた運用方針を守ると,以下のことが確約されます.
- 一番左のタブ(Command+1)は常にローカルマシンのシェルが開いている
- 二つ以上のタブが開いている場合,リモートへの接続セッションがある(もしくは開こうとした形跡がある)
- 各タブは必ず異なるホストに接続しているため,開いているタブ数-1が接続先ホストの数となる
- screenセッションが開いている場合,ウィンドウ番号0はログインユーザのシェル,1が開いていればrootとして使っていることがあるので注意する
- リモートセッション用のタブがローカルシェルを開いている場合,回線切断などで切断されたことを意味する
これにより,
- よく分からなくなったらとりあえずCommand+1を押せばローカルシェルが開いている状態になる
- リモート接続を切断しようと思ったら,1番目のタブを残して全部閉じれば良い
- タブを見ればどこに接続しているかがわかるので,1つのタブの中で作業している分には,どのscreenセッションがどのホストに接続しているのかといったことをかんがえなくて良い
という恩恵が受けられます.
オペレーションミスというのはどんなに慣れているエンジニアでもゼロにすることはできないですが,ミスの可能性を減らすことはできます.
今回の様にツールの使い方に気をつける方法だったり,chef/capistranoを使ってそもそもコンソールからの設定作業の数を減らすという方法もあるでしょう.
何にせよ,ちょっとしたことに気を遣うことで大惨事を避けられるのであれば,積極的に改善すべきだと思います.