まだプログラマーですが何か?

プログラマーネタとアスリートネタ中心。たまに作成したウェブサービス関連の話も http://twitter.com/dotnsf

タグ:Linux

自分は学生時代に初めてパソコンを購入しました。NEC PC-9801 DA です。Intel の CPU が 32bit に対応した直後のモデルでした。

当時からプログラミングはしていました。が、どちらかというとまだ「授業で使うため」「単位を取るため」という理由でした。でもそれが20数年後の今の自分の礎になっているのかと思うと感慨深いです。

さて、その当時に流行っていたテキストエディタの1つが MIFES (マイフェス)でした。1985年にメガソフト株式会社から PC-9801 の MS-DOS 環境向けに発売されたこのテキストエディタは強力な検索機能と、マクロ言語によるカスタマイズ性の高さが特徴でした。

と、偉そうなことを言ってますが、実は自分自身は友人の環境を触らせて使わせてもらっていたのでした。本音としては「当時は値段が高くて学生身分の自分には手が出せなかった」のでした。当時のテキストエディタの2大勢力の、もう1方であった Vz (こっちも1万円近くした記憶が・・・)を愛用しており、実は今でも PC-DOS の仮想環境では使っていたりします。

さて、Vz は Windows 環境では Wz エディタとなって進化を続けていますが、MIFES もずっと進化を続けてきました。MIFES の現在の最新バージョンは10で、先日30周年を迎えたようです。おめでとうございます。

そして、なんと MIFES の体験版がダウンロードして使えること、しかも Linux 版が存在していたことを、恥ずかしながらつい先日知りました。この Linux 環境で使えるテキストエディタという意味では Vz/Wz にはなかった環境です。さっそく試してみました。

まずはここから MIFES for Linux をダウンロードします。自分が試した時は milinux-103.tar.gz というアーカイブファイルがダウンロードできました:
http://www.megasoft.co.jp/cgi-bin/try/milinux/cgi/form.pl


なお、動作環境ページに制約事項が書かれています。自分が以下で試した環境は 64bit の CentOS 6.6 で、「64 bit OS の動作保証はしていない」と書かれていますが、一応以下の手順で動いていました、ということを記載しておきます。

この MIFES for Linux を 64bit 環境下で動かすには ld-linux.so2 ライブラリが必要でした。なので、こいつをあらかじめインストールしておきます:
# yum install ld-linux.so.2

で、その後にダウンロードしたファイルを展開すると mifes というフォルダが作られ、その中に一式のファイルが含まれています。これでインストール完了です:
# cp milinux-103.tar.gz /opt
# cd /opt
# tar xzvf milinux-103.tar.gz
# mifes

ここで1点注意が必要です。MIFES for Linux がサポートする日本語エンコードは EUC のみ、ということです。なのでログインに利用している端末(例えば PuTTY や TeraTerm)の日本語設定を EUC に変更する必要があります。以下は TeraTerm の場合の変更内容です(メニューから「設定」-「端末」で、この画面で文字コードを EUC にしています):
2016022001


ここまでの設定をした上で MIFES for Linux を起動します。コマンドは mi で、ファイル名を引数に指定してもいいのですが、とりあえずそのまま起動してみます:
# ./mi

すると DOS 時代の懐かしいテキストエディタインターフェースが Linux の端末上で再現されます。まずはファイル選択画面が開きます:
2016022002


ここで矢印キーを使ってディレクトリを変更しながらファイルを選択します。例えば mi と同じディレクトリにある license.txt を選びました。このファイルを開くには選んだ後に Enter を押します:
2016022003


MIFES 独特の、青い背景に灰色文字で選択したファイルを開くことができました。当時のユーザーには死ぬほど懐かしい「ダイヤモンドカーソルキー(Ctrl+E,S,D,X がそれぞれ矢印キーの上、左、右、下に対応して、ホームポジションに指を置いたままカーソル移動ができるショートカット)」も再現されています。使っていると指が思い出してくれます:
2016022000


メインメニューは F1 キーで、そこから別のファイルを開いたり、終了したり・・・といったオペレーションが可能でした。


唯一気になった点を上げるとすると、やはり UTF-8 エンコードに対応していない、という所でしょうか。今自分の手元にあるソースコードファイルはほぼ UTF-8 で作られており、それらが読み込めないというのはやはり痛いです。とはいえ、今後 MIFES for Linux の進化が期待できるかというと・・・ まあ難しいということを理解しないといけないのだと思っています。

しかし学生時代を含めても、自分の環境下に MIFES をインストールしたのは数えるくらいしかなかったし、それを Linux で行える日がやってくるとは思っていませんでした。

KVM をはじめとするハイパーバイザーの魅力は、OS環境が必要になった場合、テンプレート的な環境を元にすぐ用意できる、ということ。いわゆる LAMP 環境が必要になったら、LAMP 導入済みの仮想環境があれば、それを複製して新しいLAMPの仮想マシンを作れる、というイメージです。

が、KVM でこれをやろうとすると結構ひっかかるポイントがあります。具体的な環境にも依存するのですが、自分の場合は KVM のゲストOSにはDHCPを適用していました。これが後々大きな問題になりうるとは・・・ 試行錯誤を繰り返してなんとか形になったので、ここにまとめておきます。


そもそもどこでつまづくのか?

おさらいですが、仮想マシンを複製して新しい仮想マシンを作って利用する、ということは以下のような流れになります:
(1) 複製元の仮想ゲスト環境から、新しい仮想ゲスト環境を複製する
(2) 複製後の仮想環境の IP  アドレスを確認する
(3) 複製後の仮想環境にリモートアクセスして利用する

※ (1) のコマンドは、例えば複製元の KVM ドメイン名が guest1、複製先が guest2、複製先のイメージファイルを /var/lib/libvirt/images/guest2.img に指定するとしたら以下のようになります:
# virt-clone --original guest1 --name guest2 --file /var/lib/libvirt/images/guest2.img

この流れの中でつまづく可能性があるのは2点です:

まず自分の環境では DHCP でゲスト環境の IP アドレスを動的に割り振っています。なので (1) で複製したゲスト環境の IP アドレスを事前に想定することができないので、起動してもどうやって (3) のリモートアクセスしていいのか分からないのです。

そのためには (2) の手順が必要になります。具体的には KVM の virsh コマンドを使って親ホストから子ゲストにコンソールログインして IP  アドレスを確認することになります。この手順も含めて紹介しますが、裏を返せば (2) が可能になるように (1) の複製元仮想ゲスト環境を設定しておくことが必要になる、ということです。

※ KVM ホストが RUNLEVEL = 5 の GUI 環境で運用されている場合は、virt-manager の画面から直接目的の仮想環境のコンソールを開いてログインすることも可能ですが、RUNLEVEL = 3 の CUI 環境で運用しているケースを想定し、また最終的にはシェルスクリプト1つで複製からネットワーク設定の変更まで一発で変更できるような処理にしたいので、コンソールログインができるような環境を整えておくことをおすすめします。

もう一点の問題は (1) を普通にコマンドを実行して行っただけでは複製後のマシンのネットワークインターフェースが有効にならない(ループバックインターフェースのみが有効な状態で起動する)、ということです。複製元の環境がDHCPで、MACアドレスを持ってDHCPサーバーに問い合わせた結果のIPアドレスを割り振られています。この辺りは OS インストール前後の設定項目なのであまり意識して設定していない人もいると思いますが、具体的な内容は /etc/sysconfig/network-script/ifcfg-eth0 などに記載されています。

そして KVM の複製コマンドではこれらの情報ごと複製されることになります。つまり複製元の MAC アドレスが書かれた設定ファイルが、異なる MAC アドレスを持つ環境下にコピーされてしまうことになり、このファイルではDHCP サーバーから IP アドレスを正しく 取得することができないのでした。加えて複製元環境にホスト名が設定されていた場合は /etc/hosts や /etc/sysconfig/network なども複製元の情報を保持したままコピーされることになるので、これらのファイルもそのままでは正しくない、ということになります。これらを解決するには複製直後のネットワーク環境に対していくつかの変更が必要になるのでした。


KVM のゲスト Linux 環境にコンソールログインするための設定

こちらは以前のブログエントリで触れておきました。複製元のゲストOS環境にこちらで紹介した設定をして、コンソールログインが可能な状態にしておいてください。


KVM の Linux 環境のネットワーク関連設定ファイル

まずは複製後に変更の必要がある(可能性のある)ファイル4つと、その変更内容を羅列します:

・ /etc/hosts

複製前の環境にホスト名(例えば xxx.host.com)を設定していると、/etc/hosts にこのような記述がされているはずです。
 127.0.0.1  xxx.host.com localhost localhost.localdomain ...

で、この内容が複製先にもそのまま反映されることになります。それで問題ないケースと問題になるケースがあると思うのですが、問題になるケースでは複製先での変更が必要です。

・ /etc/sysconfig/network

上記の /etc/hosts と同じ理由です。/etc/sysconfig/network にはホスト名が記述されています。
 NETWORKING=yes
 HOSTNAME=xxx.host.com

この内容がそのまま複製先に反映されて影響があるケースでは複製先での変更が必要になります。

・ /etc/sysconfig/network-scripts/ifcfg-eth0

この作業の肝になる部分です。/etc/sysconfig/network-scripts/ifcfg-eth0 にはネットワークインターフェースの設定が記述されており、このファイルに関しては複製元の情報をそのまま使うことはできません

具体的には以下のような変更が必要です:
- 固定 IP アドレスで運用する場合は複製先には異なる IP アドレスを指定する
- DHCP で運用する場合は複製元の MAC アドレス情報を複製先のものに書き換える
- 更に UUID については複製元の情報を複製先で使うわけにはいかないため、新たに用意する

(DHCP の例)
DEVICE="eth0"
BOOTPROTO="dhcp"
HWADDR="XX:XX:XX:XX:XX:XX"
NM_CONTROLLED="no"
ONBOOT="yes"
TYPE="Ethernet"
UUID="nnnnnnnn-nnnn-nnnn-nnnn-nnnnnnnnnnnn"
  : 

・ /etc/udev/rules.d/70-persistent-net.rules

このファイルにも MAC アドレスが記述されているので、複製先では複製先の MAC アドレスに必ず書き換える必要があります

SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="XX:XX:XX:XX:XX:XX", ATTR{type}=="1", KERNEL=="eth*", NAME="eth0"


KVM のゲスト Linux 環境のネットワーク関連設定ファイルの変更

なお、以下の説明では guest1 というドメイン名の KVM ゲストから guest2 というドメイン名の KVM ゲストを複製したものとして説明を続けます。guest2 には guest1 のネットワーク設定情報が残っているので変更する必要がある、という状況を想定しています。


まずは KVM のホストからゲスト環境のファイルシステムにアクセスするために、KVM ホストに libguestfs パッケージを導入します:

# yum install libguestfs libguestfs-tools libguestfs-tools-c

libguestfs パッケージが KVM ホストに導入されると KVM ホストから KVM ゲストのファイルシステムに直接アクセスすることが可能になります。なお、その際は目的の KVM ゲストはシャットダウン状態にしておきます。


例えば KVM ゲスト : guest2 の特定のファイル(例 /etc/hosts)を表示するには、KVM ホストから以下のコマンドを実行します。 -d でゲスト環境のドメインを指定します:

# virt-cat -d guest2 /etc/hosts

127.0.0.1  xxx.host.com localhost localhost.localdomain ...

ファイルを編集するには virt-edit コマンドを実行します。パラメータは同じです:

# virt-edit -d guest2 /etc/hosts

/etc/hosts に変更の必要がある場合は適宜変更して保存します。再度 virt-cat コマンドで変更後の内容を確認します。

# virt-cat -d guest2 /etc/hosts

127.0.0.1  yyy.host.com localhost localhost.localdomain ...
(ホスト名を xxx.host.com から yyy.host.com に変更した場合)


ホスト名の変更が必要な場合は 同様にして /etc/sysconfig/network ファイルも編集します:

# virt-edit -d guest2 /etc/sysconfig/network

# virt-cat -d guest2 /etc/sysconfig/network

NETWORKING=yes
HOSTNAME=yyy.host.com
(ホスト名を xxx.host.com から yyy.host.com に変更した場合)


次に複製先の /etc/sysconfig/network-scripts/ifcfg-eth0 ファイルを編集しますが、その前に複製先環境の MAC アドレスを確認します:

# virsh domiflist guest2

Interface Type Source Model MAC
-------------------------------------------------------
- bridge br0 virtio 'YY:YY:YY:YY:YY:YY'
(YY:YY:YY:YY:YY:YY 部分が guest2 の MAC アドレスです)

また複製先用の UUID も uuidgen コマンドで事前に用意しておきます:

# uuidgen

mmmmmmmm-mmmm-mmmm-mmmm-mmmmmmmmmmmm
(8桁-4桁-4桁-4桁-12桁の文字列が guest2 用の新しい UUID です)

guest2 の MAC アドレスと UUID が決まったので、この内容を guest2 の /etc/sysconfig/network-scripts/ifcfg-eth0 を編集して反映させます:

# virt-edit -d guest2 /etc/sysconfig/network-scripts/ifcfg-eth0

DEVICE="eth0"
BOOTPROTO="dhcp"
HWADDR="YY:YY:YY:YY:YY:YY"
NM_CONTROLLED="no"
ONBOOT="yes"
TYPE="Ethernet"
UUID="mmmmmmmm-mmmm-mmmm-mmmm-mmmmmmmmmmmm"
  : 


最後に複製先の /etc/udev/rules.d/70-persistent-net.rules ファイルを編集して、複製先環境の MAC アドレスを指定して保存します:
 
# virt-edit -d guest2 /etc/udev/rules.d/70-persistent-net.rules
 
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="YY:YY:YY:YY:YY:YY", ATTR{type}=="1", KERNEL=="eth*", NAME="eth0"


これで複製先で変更が必要なネットワーク設定は以上です。これらの変更後に guest2 を起動するとネットワークが有効な状態で立ち上がります:

# virsh start guest2

# virsh list
(guest2 が「実行中」として表示されるようになるまで待つ)


上記「KVM のゲスト Linux 環境にコンソールログインするための設定」が複製元(guest1)で済んでいれば、複製先である guest2 にもその内容が複製されているので guest2 にコンソールログインできるはずです。KVM のコンソールログインについてはこちらのエントリも参考にしてください:

# virsh console guest2


コンソールログインした先で ifconfig コマンドを実行して、guest2 に DHCP で割り当てられた IP アドレスを確認します。eth0 にアドレスが付与されていれば成功!

# ifconfig

eth0   Link encap:Ethernet  HWaddr YY:YY:YY:YY:YY:YY
           inet addr:ZZZ.ZZZ.ZZZ.ZZZ  Bcast:ZZZ.ZZZ.ZZZ.255  Mask:255.255.255.0
             :
(ZZZ.ZZZ.ZZZ.ZZZ 部分が guest2 のIPアドレスです)


なお、コンソールログインから抜けるには CTRL+] を押します:


これで KVM の複製コマンドで複製した仮想マシンでもネットワークが有効になりました。IP アドレスまで確認できているので、後は KVM ホスト経由でなくても普通に ssh などでリモートアクセスすることもできるようになりました。


とりあえず一連の作業としてはこんな感じですが、色々面倒なので自分の環境用に一部をシェルスクリプト化しました。具体的には以下の条件下で使えるつもりです:
・KVM ホストのシェルから実行する前提
・KVM ゲストの複製元も複製先も DHCP 設定
・KVM ゲストイメージはデフォルト設定のまま /var/lib/libvirt/images/ に存在している
・KVM ゲストイメージのドメイン名が XXX のイメージファイルは /var/lib/libvirt/images/XXX.img とする 
・複製先の /etc/hosts, /etc/sysconfig/network は書き換えない
・複製先のMACアドレスを自動取得&UUIDを自動生成して /etc/sysconfig/network-scripts/ifcfg-eth0 と /etc/udev/rules.d/70-persistent-net.rules を書き換える
・複製先の起動は行わない

そのシェルスクリプトはこちらです: clone-guest.sh

この内容についてはこちらの記事を参考にしています:
http://lab.adn-mobasia.net/?p=471


使い方は KVM ホストにコピーして、実行権限付与後に以下のように実行します:

# ./clone-guest.sh guest1 guest2
(guest1 が複製元ドメイン名、guest2 が複製先ドメイン名、guest1 にはコンソールログインの設定が済んでいて、かつ停止中であること)

すると /var/lib/libvirt/images/guest1.img を元に /var/lib/libvirt/images/guest2.img が複製され、そのネットワーク定義ファイルが上記の条件で自動的に書き換えられて、でいつでも起動できる、という状態で生成されます。もし起動まで自動で行いたいのであれば clone-guest.sh の最後に以下の一行を追加すればできると思います:

$cmd_virsh start $clone_domain_name


このサンプルでは /etc/hosts や /etc/sysconfig/network の変更は(しなくても起動まではするはずなので)行っていませんが、絶対に必要になるような環境では中身を参考にしながら変えられると思うので挑戦してみてください。

またこのサンプルはあくまで DHCP 環境を前提にしています。固定 IP にも対応するようなのは、ちょっと面倒な気もしますが、どなたか挑戦してみてください。
 
ともあれ、いろいろ手入力しないといけない状況と比べると格段に簡単になりました。仮想環境が理想に近づきました。 

KVM の virsh console コマンドを使って、(極端な話、ネットワークが有効になっていなくても)ホストOSからゲストOSにコンソールログインすることができる、ことになっています。

が、何も考えずに virsh console (ドメイン名) を実行すると 

ドメイン XXXX に接続しました

エスケープ文字は ^] です

と表示され、ここで Enter キーを押すとログインプロンプトが表示される・・・はずなのですが、なぜか固まってしまいます。 

どうもゲストOS側でコンソールログインをするための設定が必要な模様。結論としては次の2点:

(1) /etc/grub.conf にカーネルオプションを追加設定

kernel /vmlinuz-2.6.18-238.el6 ro root=/dev/***   console=tty0 console=ttyS0,115200n8
(kernel で始まる行の最後に赤字部分を追加、kernel で始まる行が複数ある場合は全てに設定)

(2) /etc/inittab にコンソールモードの設定を追加

S0:12345:respawn:/sbin/agetty ttyS0 115200
(赤字の一行を追加)


これで再起動後に、改めてホストOSから virsh console XXXX でコンソールログインが可能になります。

なお、コンソールから抜けるには CTRL+] です。


ゲストOSが
 ・別のゲストOSを元に複製で作成して、
 ・DHCPでIPアドレス設定するようになっていて、
 ・かつGUIが使えない(virt-manager から参照できない)
ようなケースでは、起動直後のIPアドレスを確認するための手段が「コンソールログインして ifconfig」しかないので、この方法が必要になるのでした。



このページのトップヘ