Emacs キーバインド その3 矩形リージョン・レジスタ

さて、第3回です。
今回は、使う場面が限定されるけど、使いこなすとスゴいシリーズです。

いろいろ
「消去」は「キル」と違って、内容を覚えずに消します。

  • M-SPC :カーソル前後の空白文字をまとめて消去
  • C-x o :前後の空行を 1行だけ残して消去
  • C-h w COMMAND :コマンド COMMAND を実行するキーバインドを表示

矩形リージョン
通常のリージョン(カーソルとマークの間の文字全て)ではなく、カーソルとマークが左上と右下に来るような矩形(四角形)の中の文字だけを対象とします。
よって、カーソル・マーク間の行に含まれていても、矩形の外側の文字は対象になりません。

  • C-x r k :矩形をキルして右側の文字列を左へ(詰めるように)移動
  • C-x r y :最後にキルした矩形を、カーソル位置を左上としてヤンク(ヤンク矩形範囲内の文字列は右へ(逃がすように)移動)
  • C-x r d :矩形内を消去して右側の文字列を左へ(詰めるように)移動
  • C-x r c :矩形内を空白で上書き(範囲外への影響は無し)
  • C-x r o :矩形サイズの空白を挿入して、矩形内の文字列を右へ(逃がすように)移動

レジスタ
レジスタとは 1文字の名前(a、b、x、y など)が付いた保管場所です。
新しい物を入れると、前に入っていた物は消えてしまいます。

以下の REG_CHAR はレジスタを表す 1文字の名前とします。

  • C-x r s REG_CHAR :リージョン内容をレジスタにコピー
  • C-x r i REG_CHAR :レジスタ内容をカーソル位置に挿入
  • C-x r C-SPC/C-@ REG_CHAR :カーソル位置をレジスタに記録
  • C-x r j REG_CHAR :レジスタに記録されている位置へカーソルを移動
  • M-x list-register :空でないレジスタの内容を一覧表示

Emacs キーバインド その2 ヘルプ・リージョン・キーマクロ

続けての投稿です。

第2回はちょっと慣れてきた人向けのシリーズです。
ヘルプ、範囲選択と切り貼り、+α を書いています。

ヘルプ

  • C-h b :キーバインドの一覧を表示
  • C-h k KEY :キーバインド KEY の説明を表示
  • C-h m :現在のモードに関する説明を表示
  • C-h a STRING :文字列 STRING を含むコマンドのリストを表示

マーク

  • C-SPC/C-@ :カーソル位置にマークを設定してリージョン指定を開始
  • C-u C-SPC/C-@ :一つ前のマーク位置に移動
  • C-x C-x :カーソル位置とマーク位置を入れ替え(と同時にリージョンに設定)

「リージョン」とはマークとカーソルに挟まれている部分です。
リージョンを対象にするコマンドや、リージョン設定中に実行するとリージョン内だけで動くコマンドがあります。

キルとヤンク
「キル」は「切り取り(カット)」の、「ヤンク」は「貼り付け(ペースト)」の Emacs 版です。

  • C-w :リージョンをキル
  • M-w :リージョンの内容を残したままキル(いわゆる「コピー」)
  • C-y :カーソル位置へヤンク(キルしてあった内容を挿入)
  • M-z CHAR :文字 CHAR まで(CHAR も含めて)キル

いろいろ

  • C-x C-n :カーソルのある桁位置を行移動(C-n,C-p)の目標桁に設定
  • C-u C-x C-n :上で設定した目標桁を解除
  • C-x = :カーソル位置の情報(文字コード、文字位置、桁位置)を表示
  • M-( :かっこの対「()」を挿入して、その中にカーソルを移動
  • C-x n n :表示(と編集)をリージョン内のみに限定(ナローイング)
  • C-x w :ナローイングの解除

キーボードマクロ
記録開始から終了までの操作を覚えておいて再利用します。

  • C-x ( :マクロの記録を開始
  • C-x ) :マクロの記録を終了
  • C-x e :最後に記録したマクロを実行
  • M-x insert-kbd-macro ENTER :最後に記録したマクロの内容をカーソル位置に挿入

設定ファイル(.emacs など)にマクロ内容を保存しておく事で、次回以降の Emacs 起動時でも利用できます。
ただし、名前を付けてキーバインドを設定(global-set-key などを利用)しないとダメですが。

Emacs キーバインド その1 カーソル移動

ふと思い立って Emacs マニュアルを片手にキーバインドをまとめ直したので記録します。

第1回はカーソル移動についてです。…一部検索も含みますが。

言うまでもありませんが「C-x」は Ctrl キーを押しながら x を押すという意味です。
同様に「M-x」は Alt キーを押しながら(あるいは ESC を押してから) x を押します。
あと「C-x n」は「C-x」の後に(Ctrl を放してから) n を押します。

以下で使用している「a/b」は独自表記で a または b を意味します。
そのキーバインドの説明で【上、下】のように書いてあれば、a の時が「上」で b の時は「下」と考えてください。

単位ごとの移動

  • C-p/C-n :【後方(上)、前方(下)】の行へ移動
  • C-b/C-f :1文字【後方(左)、前方(右)】に移動
  • M-b/M-f :1単語【後方(左)、前方(右)】に移動
  • M-a/M-e :文 1つだけ【後方(左)、前方(右)】に移動
  • M-[/M-](角括弧の開き/閉じ) :1段落【後方(上)、前方(下)】に移動
  • C-x [/](角括弧の開き/閉じ) :1ページ(^L文字で区切られている)【後方(上)、前方(下)】に移動

先頭と末尾への移動

  • C-a/C-e :行の【先頭、末尾】へ移動
  • M-</M-> :バッファの【先頭、末尾】へ移動

スクロール・位置指定

  • C-v :1画面進む(下)方向にスクロール
  • M-v :1画面戻る(上)方向にスクロール
  • C-l :現在行が画面中央に来るようにスクロール
  • M-g M-g :指定する行番号へ移動
  • M-r :画面中央の行へカーソル移動

検索(インクリメンタルサーチ)
文字を入力しながら検索します。1文字入れるごとに候補を絞り込みます。

  • C-s :前方(画面下)へサーチ、サーチ中なら前方の次候補へ移動
  • C-r :後方(画面上)へサーチ、サーチ中なら後方の次候補へ移動

現在位置で検索を終了したければ ENTER か、カーソル移動コマンドを使えばいいです。
検索開始位置に戻りたい場合には C-g を利用します。


特殊:プログラムのソースファイル向け

  • C-M-b/C-M-f :式 1つ分だけ【後方(左)、前方(右)】に移動
  • C-M-p/C-M-n :リスト 1つ分だけ【後方(左)、前方(右)】に移動
  • C-M-a/C-M-e :最上位のまとまり(関数定義など) 1つ分だけ【後方(上)、前方(下)】に移動
  • C-M-u/C-M-d :リスト階層で 1つ【上(外)、下(中)】へ移動
  • M-m :現在行の先頭の非空白文字(字下げした行頭)へ移動

とまあ色々とありますが、とりあえず下の 3パターンだけ覚えておけば何とかなります。

  • C-p/C-n/C-b/C-f :1つ【上、下、左、右】へ移動
  • C-s/C-r :【前方(下)、後方(上)】へ検索開始・次候補へ移動
  • C-v/M-v :1画面【前方(下)、後方(上)】へスクロール

余裕があれば 単語移動の M-b/M-f、行頭 C-a、行末 C-e、バッファ先頭/末尾 M-<、M-> も覚えておくと便利です。

仮想 IP アドレスをフェイルオーバーする方法

お久しぶりです。
相変らず不定期更新で、作業メモばかりのブログです。

今回は (Debian系)Linux で、仮想 IP アドレスをフェイルオーバーする方法のメモです。
簡単に言うと、サーバ 2台の状態で片方がコケた時に残ってる方でサービスを継続したい時に使う手法です。って、全然簡単じゃないですね…

では下準備からです。
■材料

  • サーバ 2台(もちろん仮想マシンでも可)
  • ネットワーク 2個(つまり NIC 2枚ずつとハブ 2個)
  • クライアントマシン 1台(切り替え状況をチェックします)

■準備手順

  1. サーバに Debian系OS(最近だと Ubuntu が多いですかね)を入れます
  2. サーバに fake パッケージをインストールします(send_arp コマンドが入ります)
  3. サーバに arping パッケージをインストールします
  4. サーバを 2つのネットワークに接続する設定をします(/etc/network/interfaces ですね)
    便宜上それぞれを WAN と LAN と呼びます。また、サーバ名は srv1、srv2 とします。

    • LAN(eth0):192.168.1.0/24, srv1(192.168.1.11), srv2(192.168.1.12)
    • WAN(eth1):10.0.0.0/24, srv1(10.0.0.11), srv2(10.0.0.12)
  5. クライアントマシン(名前:cli)を WAN に接続します(IP:10.0.0.20)

それで、実際に切り替える操作です。

  • 仮想 IP アドレス($VIP)を 10.0.0.1 とします
  • WAN側デバイス($DEV = eth1)の MAC アドレス($MAC)を次だとします
    • srv1(000011110000)
    • srv2(222200002222)

■メイン側サーバ(srv1)へ仮想 IP を付けます

srv1> ip addr add $VIP/24 dev $DEV

■クライアント側からチェックします

  • IP アドレス:「cli> ping $VIP
  • ARP キャッシュ:「cli> arp」(10.0.0.1 が 000011110000 になるはずです)

■仮想 IP をフェイルオーバーするコマンドです
ここでは仮想 IP の存在チェックを繰り返して、失敗したら 仮想 IP の設定と ARP キャッシュの更新通知を行います。

  1. 仮想 IP の存在チェック:「srv2> arping -q -c 1 -I $DEV $VIP
  2. 仮想 IP の設定(srv1 の時と同様):「srv2> ip addr add $VIP/24 dev $DEV
  3. ARP キャッシュの更新通知:「srv2> send_arp $VIP $MAC 255.255.255.255 ffffffffffff $DEV $MAC ffffffffffff reply

たぶん、実際には下に書いたようなスクリプトを実行することになります。

■srv1 の仮想 IP を外します
srv1> ip addr del $VIP dev $DEV

■クライアント側からチェックします
前と同様に ping と arp を実行します。
arp の表示で 10.0.0.1 が 222200002222 に変わっているはずです。


仮想 IP フェイルオーバー用スクリプト


#!/bin/bash

VIP="10.0.0.1"
DEV="eth1"
BCAST_IP="255.255.255.255"
BCAST_MAC="ffffffffffff" # f x 12

health_check() {
arping -q -c 1 -I $DEV $VIP
return $?
}

ip_failover() {
MAC=`ip link show $DEV | egrep -o '([0-9a-f]{2}:){5}[0-9a-f]{2}' | head -1 | tr -d \:`
ip addr add $VIP/24 dev $DEV
send_arp $VIP $MAC $BCAST_IP $BCAST_MAC $DEV $MAC $BCAST_MAC reply
}

while health_check; do
echo "health check ok!"
sleep 1
done
echo "fail over!"
ip_failover

もちろん、実際に使う時には echo の部分はコメントアウトする事になるでしょう。


また、作業中に気付いた点は以下の通りです。

  • 仮想 IP のチェックは 「arping -q -c 1 -I $DEV $VIP」 の方が 「ping -c 1 $VIP >/dev/null」 よりも早くダウンに気付きました
  • Web でクライアント(実際には WAN のルータ)に 「echo 1 > /proc/sys/net/ipv4/conf/all/arp_accept」 を設定した方が良いと書いてありましたが、今回は設定値が 0 でも期待通りに動きました
  • ARP キャッシュ更新に使う send_arp コマンドですが、Web で調べた 「send_arp $VIP $MAC $BCAST_IP $BCAST_MAC $DEV」 では期待する ARP Reply ではなく ARP Request になってしまいました