keisyuのブログ

最近めっきりエンジニアリングしなくなった厄年のおじさんがIT技術をリハビリするブログ。

Amon2を使ったアプリ開発 (その2)

前回 ( Amon2を使ったアプリ開発 - keisyuのブログ ) はDBI経由でMySQLからデータを引っ張ってくるところまでできました。今回はまず取り出したデータをHTML上で確認できるようにします。
Amon2は Text::Xslate をそのテンプレートエンジンに採用しています。lib/SimpleBBS/Web/View.pm にその初期化コードがあります。
私は TT2 compatible のテンプレート syntax が好みなのでそれに変更します.

   my $view = Text::Xslate->new(+{
        'syntax'   => 'TTerse',   # Kolon -> TTerse

この段階ですでにデフォルトのテンプレート tmpl/index.tx で :cascade 構文が効かなくなったので画面が崩れますがそれでOKです。
新規に tmpl/index.tt を新規に作成します

<html>
<head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
</head>
<body>

<form action="[% uri_for('/post') %]" method="post">
    <input type="text" name="body">
    <input type="submit" value="post">
</form>

[% FOR entry IN entries %]
    <li> [% entry.id %] : [% entry.body %] - [% entry.created_at %]
[% END %]

</body>
</html>

これをテンプレートとして指定するために lib/SimpleBBS/Web/Dispatcher.pm で

any '/' => sub {
    ...
    return $c->render('index.tt', {
        entries => \@entries,
    });
    ....

とします。これで以下のような画面になります。
f:id:keisyu:20140216221823j:plain:w300
まだ、/post のメソッドが定義されていませんので追記します。Dispacher.pm に以下のコードを追記します。

post '/post' => sub {
    my($c) = @_;
    $c->dbh->do( q[
        INSERT INTO entries (body) VALUES (?)
    ], undef, $c->req->param('body'));
    return $c->redirect('/');
};

これで投稿もできる。とおもいきや投稿すると「403 XSRF detected.」と表示されてしまいます。
basicのflavorだと XSRF の対応がデフォルトみたいですね。この辺も改めてあとで調べるとしてとりあえず無効にしときます。
lib/SimpleBBS/Web.pm の中のload_pluginから以下を削除と Dispacher.pm内のsessionに関する記述を削除します。

    '+SimpleBBS::Web::Plugin::Session',

これで投稿もできるようになりました。
f:id:keisyu:20140216224715j:plain:w300

番外 (もっと便利にデバックできるために)

コードの修正で失敗したりと500エラー等がでたときにWeb画面でバックトレースの画面が見えるようなプラグインPlackにあります。
また、実行のプロファイルが取れるプラグインplackに用意されていますplackのbuilder (script/simplebbs-server) の中に以下の2つを記述します

builder {
    ...
    enable 'Plack::Middleware::Debug';
    enable 'Plack::Middleware::StackTrace',force => 1;

上のDebugはモジュールがインストールされていませんのでcpanfileに requires 'Plack::Middleware::Debug'; を記述して carton install も必要です。これにてそれぞれ以下のようなプロファイルやバックトレースが出力されます。

  • Plack::Middleware::Debug

f:id:keisyu:20140216225613j:plain:w300

  • Plack::Middleware::StackTrace

f:id:keisyu:20140216225815j:plain:w300

Amon2を使ったアプリ開発

前回は amon2 を触ってみましたが ( Amon2 (PSGI フレームワーク) - keisyuのブログ ) これで少しアプリっぽいものを作って勉強してみようと思います。作るものは掲示板みたいなものを作って見ようと思います。

まずは amon2-setup.pl で flavor はBasicでスタートすることにします。

$ amon2-setup.pl --flavor=Basic SimpleBBS 
$ carton install

今回はplackupを使って起動して開発することにします。-R オプションに監視ディレクトリを指定して起動するとコードの変更時にサーバを停止することなく自動でリロードされるようで便利のようです。

$ carton exec -- plackup -R ./lib  -Ilib script/simplebbs-server

さて作るもの(方針)はこんな感じにします

  • 超簡易な掲示板
  • DBはMySQLを使う
  • flavor:BasicでバンドルされているORM(Teng)は使わずにdbhで操作する
  • Templeteのsyntaxは TT2 compatible が慣れているのでそれを使う( ひな形のは捨てる )。
  • その他開発に便利そうなやつは勉強がてら触ってみる。

DB(TABLE)の定義

投稿が保存される単一テーブルにします sql/mysql.sql を以下にします

CREATE TABLE IF NOT EXISTS entries (
    id      INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
    body    VARCHAR(255),
    created_at  TIMESTAMP
) CHARSET=utf8;

MySQLにDatabaseを定義してテーブルを作成します

$ sudo mysqladmin create SimpleBBS
$ cat sql/mysql.sql | mysql -u root SimpleBBS 

dbh (MySQL) を使う準備

cpanfile に以下を追記します

requires 'Amon2::Plugin::DBI';
requires 'DBD::mysql';

そしてインストールします

$ carton install

config/development.pl はデフォルトでsqliteに接続するひな形になっているのでこれを以下に変更します

+{
    'DBI' => [
        "dbi:mysql:dbname=SimpleBBS", 'root', '',
        +{
            mysql_enable_utf8 => 1,
        }
    ],
};

開発

とりあえず、テンプレートを触るのはもうちょっと後にして、DBに直接エントリーを数個入れてそれがちゃんと取り出せるか確認してみます。

mysql> insert into entries (body) values ('Hello!'),('Amon2'),('World!!');          
mysql> select * from entries;
+----+---------+---------------------+
| id | body    | created_at          |
+----+---------+---------------------+
|  1 | Hello!  | 2014-02-16 18:25:58 |
|  2 | Amon2   | 2014-02-16 18:25:58 |
|  3 | World!! | 2014-02-16 18:25:58 |
+----+---------+---------------------+

lib/SimpleBBS/Web.pm の中にこのアプリで利用するプラグインをロードする箇所があるのでそこにDBIを追加します

__PACKAGE__->load_plugins(
...
    'DBI',
);

lib/SimpleBBS/Web/Dispatcher.pm に各URLのエントリーポイント毎の処理を記述する箇所がありますので '/' の部分で先ほどの entries テーブルをSELECTして標準出力に表示してみることにします。

...
use Data::Dumper;
...
any '/' => sub {
    my ($c) = @_;
    my $entries = $c->dbh->selectall_arrayref(q[
            SELECT * FROM entries ORDER BY id DESC
        ], { Slice => {} });
    print Dumper $entries;
    ...

これでWebページにブラウザでアクセスするとサーバが起動しているシェルに

$VAR1 = [
          {
            'created_at' => '2014-02-16 18:25:58',
            'body' => 'World!!',
            'id' => '3'
          },
          {
            'created_at' => '2014-02-16 18:25:58',
            'body' => 'Amon2',
            'id' => '2'
          },
          {
            'created_at' => '2014-02-16 18:25:58',
            'body' => 'Hello!',
            'id' => '1'
          }
        ];

と表示されました。ちゃんとDBI経由でMySQLからデータが取得できているようです。ちょっとMVCっぽく各entryの要素をModel化します。
lib/SimpleBBS/Model/Entry.pm を以下で定義します。

package SimpleBBS::Model::Entry;

use Class::Accessor::Lite (
    new => 1,
    ro => [ qw(
        id body created_at
    )], 
);

1;

これをつかて先ほどのDispacher.pmを若干修正します

...
use SimpleBBS::Model::Entry;

any '/' => sub {
    my ($c) = @_;
    my @entries = map {
        SimpleBBS::Model::Entry->new($_)
    } @{$c->dbh->selectall_arrayref(q[
            SELECT * FROM entries ORDER BY id DESC
        ], { Slice => {} })};
    print Dumper @entries;
    ....

これで出力されるログは

$VAR1 = bless( {
                 'created_at' => '2014-02-16 18:25:58',
                 'body' => 'World!!',
                 'id' => '3'
               }, 'SimpleBBS::Model::Entry' );
$VAR2 = bless( {
                 'body' => 'Amon2',
                 'created_at' => '2014-02-16 18:25:58',
                 'id' => '2'
               }, 'SimpleBBS::Model::Entry' );
$VAR3 = bless( {
                 'body' => 'Hello!',
                 'created_at' => '2014-02-16 18:25:58',
                 'id' => '1'
               }, 'SimpleBBS::Model::Entry' );

となりました。今回のサンプルではここまでModel化する必要は全く無いですがね...

Amon2 (PSGI フレームワーク)

先日PSGIアプリケーションの基本を触ってみたので ( まずはperlbrew や cpanm と carton とか。 - keisyuのブログ ) Webアプリっぽいのを作ってみる。
今は素でアプリを作ることはほとんどなくどの言語でもフレームワークを使うことが多いのですが、私は重量級のフレームワークはどうしても好きになれないので
PerlPSGIサポートの軽量級のフレームワークをと探してみたら Amon2 - Amon2 - Web application framework for Rapid web development がその一つだということで使ってみることにする。

インストールは cpanm を利用して以下のコマンド一発でOKです。

$ cpanm Amon2

インストールが終わったらAmon2のアプリケーションのひな形を作る amon2-setup.pl のコマンドがインストールされます。--flavor というオプションでひな形のタイプが選択できるようで標準で色々あるようです。

% amon2-setup.pl
Usage:
        % amon2-setup.pl MyApp

            --flavor=Basic      basic flavour (default)
            --flavor=Lite       Amon2::Lite flavour (need to install)
            --flavor=Minimum    minimalistic flavour for benchmarking
            --flavor=Standalone CPAN uploadable web application(EXPERIMENTAL)

            --vc=Git         setup the git repository (default)

            --list-flavors (or -l) Shows the list of flavors installed

            --help   Show this help

で私は書いたようにあんまり色々自動で作られるのが好きじゃないので --flavor=Lite ってのをまず試してみようと思います。need to install とあるのでインストールしてセットップしてみる. Amon2::Setup::Flavor::Lite - search.cpan.org

$ cpanm Amon2::Setup::Flavor::Lite
$ amon2-setup.pl --flavor=Lite MyApp
$ find MyApp | grep -v .git
MyApp
MyApp/app.psgi
MyApp/Makefile.PL
MyApp/t
MyApp/t/01_root.t
MyApp/t/Util.pm
MyApp/xt
MyApp/xt/03_pod.t

作られた。(こんだけ...思ってた以上に少ない...).
とりあえず何も編集せずに起動してみる.
f:id:keisyu:20140215191353j:plain
こんなシンプルな画面が立ち上がりました。なんとなく --flavor=Basic も試してみたくなったのでやってみると

$ carton install
$ carton exec perl -Ilib script/myapp2-server

こういう手順で起動しなさいと出た。Basic だと色んなモジュールが必要だけど cpanfile 作っといたので各自 carton 環境下で動かしなさいということか.

f:id:keisyu:20140215193651j:plain

起動した。何もしていないに等しいけど今日はここまで。

yum レポジトリの追加 (rpmforge, epel,remi)

今日は軽めに。

CentOSの標準のレポジトリだと、各種パッケージが存在しない場合があります。ので以下の3つのレポジトリを追加します。

$ curl -LO http://pkgs.repoforge.org/rpmforge-release/rpmforge-release-0.5.3-1.el6.rf.x86_64.rpm
$ sudo rpm -ivh rpmforge-release-0.5.3-1.el6.rf.x86_64.rpm 
$ curl -LO http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
$ sudo rpm -ihv epel-release-6-8.noarch.rpm 
$ curl -LO http://rpms.famillecollet.com/enterprise/remi-release-6.rpm
$ sudo rpm -ihv remi-release-6.rpm 
repiはデフォルトは無効なので enable にする。
$ sudo vi /etc/yum.repos.d/remi.repo 

MySQLのインストールとベンチマーク(sysbench)

MySQL

MySQLも気がつけば5.6ですね。(私がバリバリ使っていた時は4.1とか5.0の時代でした...).
現在ダウロードできる5.6, 5.5, 5.1 を切り替えてインストールできる環境の構築とそれぞれでベンチマークを取ってみることにします。

MySQLのダウンロードは MySQL :: Download MySQL Community Server ここですが、色々種類があります。
RPM版とかもありますが、私が毎回使っているのは

  • Linux - Generic (glibc 2.5) (x86, 64-bit), Compressed TAR Archive (もしくは32bit版)

です。RPMだと各種ファイルが散らばってしまってあんまり好きじゃないですので毎度 TAR Archive でインストールしています。3バージョン以下のようにダウンロードしました。(ファイル名の命名とかバラバラやな...)

$ ls -ltr
合計 608308
-rw-rw-r-- 1 keisyu keisyu 304788904  2月 13 01:45 2014 mysql-5.6.16-linux-glibc2.5-x86_64.tar.gz
-rw-rw-r-- 1 keisyu keisyu 184478489  2月 13 01:47 2014 mysql-5.5.36-linux2.6-x86_64.tar.gz
-rw-rw-r-- 1 keisyu keisyu 133630298  2月 13 01:48 2014 mysql-5.1.73-linux-x86_64-glibc23.tar.gz

install

mysqlユーザを追加します。

$ sudo groupadd mysql
$ sudo useradd -r -g mysql mysql

tar.gzを /usr/local 以下に展開します

$ sudo tar -zxvf mysql-5.6.16-linux-glibc2.5-x86_64.tar.gz -C /usr/local/

3バージョンとも展開しました。アクティブにたいバージョンをmysqlシンボリックリンクします。

$ cd /usr/local
$ sudo ln -s mysql-5.6.16-linux-glibc2.5-x86_64 mysql
$ ls -l
...
lrwxrwxrwx   1 root root   34  213 01:54 2014 mysql -> mysql-5.6.16-linux-glibc2.5-x86_64
drwxr-xr-x  13 root root 4096 115 20:28 2013 mysql-5.1.73-linux-x86_64-glibc23
drwxr-xr-x  13 root root 4096  213 01:52 2014 mysql-5.5.36-linux2.6-x86_64
drwxr-xr-x  13 root root 4096  213 01:50 2014 mysql-5.6.16-linux-glibc2.5-x86_64

PATHに設定しときます (.zshrc とかにも書いとく)

$ export PATH=/usr/local/mysql/bin:$PATH

初期DBの作成をします

$ sudo ./scripts/mysql_install_db --user=mysql --datadir=/var/mysql/data56

たまにココで

Installing MySQL system tables..../bin/mysqld: error while loading shared libraries: libaio.so.1: cannot open shared object file: No such file or directory

なんて怒られることありますが、その場合は libaio というライブラリをインストールしてください。

$ sudo yum install libaio

my.cnfと起動

my.cnf は書けば長くなることが多いですがひとまずは最低限の記述を定義しておき /etc/my.cnf に保存します

[mysqld]
character-set-server=utf8  #5.1では default-character-set=utf8
socket=/tmp/mysql.sock

起動します.

$ sudo /usr/local/mysql/bin/mysqld_safe --user=mysql --datadir=/var/mysql/data56 &

停止は mysqladmin で行います

$ sudo /usr/local/mysql/bin/mysqladmin shutdown

起動は service に登録すると便利です。

$ sudo cp support-files/mysql.server /etc/init.d/mysql  # ファイル内のdatadirの定義だけ追記しときます
$ sudo /sbin/service mysql start
$ sudo /sbin/service mysql stop
さらに必要に応じて
$ sudo chkconfig --add mysql
$ sudo chkconfig mysql on 

接続確認

# mysql 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.6.16 MySQL Community Server (GPL)

Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show variables like 'version%';
+-------------------------+------------------------------+
| Variable_name           | Value                        |
+-------------------------+------------------------------+
| version                 | 5.6.16                       |
| version_comment         | MySQL Community Server (GPL) |
| version_compile_machine | x86_64                       |
| version_compile_os      | linux-glibc2.5               |
+-------------------------+------------------------------+
4 rows in set (0.00 sec)

sysbench

sysbench ( System performance benchmark ) はベンチマークツールです。CPU,メモリ,I/Oのパフォマンスも計測できますがDataBaseのベンチマークも行うことができます。 インストールは epel のレポジトリにありますので yum でインストール可能です。
ベンチマークをする際には以下のようなパラメータを指定します。

  • 検査テーブルのレコード数
  • Readonlyのみ/ReadWrite
  • 同時アクセス数(スレッド数)
  • 計測時間
  • MySQL接続情報

等を指定します。例えば100万行の検査テーブルに対して60秒間,4スレッドをReadのみのパフォーマンスを計測する場合は以下のコマンドでまず準備をします。

sysbench \
 --test=oltp\
 --oltp-read-only=on\
 --db-driver=mysql\
 --mysql-user=root\
 --mysql-socket=/tmp/mysql.sock\
 --oltp-table-size=1000000\
 --num-threads=4\
 --max-requests=0\
 --max-time=60\
 prepare

最後の prepare の部分を以下に変更します。

prepare 初期化(検査前に1回だけ行う)
run 計測
cleanup 後始末(最後に行う)

runに変更して実行すると

sysbench 0.4.12:  multi-threaded system evaluation benchmark

Running the test with following options:
Number of threads: 4

Doing OLTP test.
Running mixed OLTP test
Doing read-only test
Using Special distribution (12 iterations,  1 pct of values are returned in 75 pct cases)
Using "BEGIN" for starting transactions
Using auto_inc on the id column
Threads started!
Time limit exceeded, exiting...
(last message repeated 3 times)
Done.

OLTP test statistics:
    queries performed:
        read:                            260260
        write:                           0
        other:                           37180
        total:                           297440
    transactions:                        18590  (309.81 per sec.)
    deadlocks:                           0      (0.00 per sec.)
    read/write requests:                 260260 (4337.32 per sec.)
    other operations:                    37180  (619.62 per sec.)

Test execution summary:
    total time:                          60.0048s
    total number of events:              18590
    total time taken by event execution: 239.8965
    per-request statistics:
         min:                                  1.62ms
         avg:                                 12.90ms
         max:                                 76.98ms
         approx.  95 percentile:              19.17ms

Threads fairness:
    events (avg/stddev):           4647.5000/8.26
    execution time (avg/stddev):   59.9741/0.00

という風な結果が60秒後に表示されます。 309 TPS(transactions/sec) って部分の指標を結果としてよく使うと思います。

ベンチマーク (のまね事)

5.6, 5.5, 5.1 のMySQLでそれぞれ計測してみます。以下の点などを考慮していないのでまったくもって計測のまね事だということにご注意ください。

  • my.cnfの設定を全くしてなく全てデフォルト(Innodbのメモリ関連の値も全くチューニングなし)
  • sysbenchを動かすサーバがMySQLの稼働しているサーバと同じ
  • そもそもMacBookProのViertualBox上のCentOS
Threads=> 1 4 8 16
MySQL5.6 314 312 312 316
MySQL5.5 375 371 370 395
MySQL5.1 375 361 360 355

前述のとおりお遊びなのでこのデータを考察することの意味はありませんが
1スレッドですでにCPUがぶっ飛んでるからスレッド数を上げたところで意味なし... 5.5が一番TPS高いのはちょっと面白かった。
...
...
そうはいってもイマイチ面白みのなさすぎる結果だったのでVirtualBoxのCPU割り当てを8個にしてみた。

Threads=> 1 4 8 16
MySQL5.6+1CPU 314 312 312 316
MySQL5.6+8CPU 128 244 185 196

う~ん?

daemontools でプロセス監視 (svscan, supervise, multilog)

daemontools ( http://cr.yp.to/daemontools.html )でプロセス監視を運用上よくやりますが、毎度ググってを繰り返すので自分で書いとこうと思います。

daemontools は以下のツールで構成されるプロセス監視のユーティリティです

svscan サービスディレクトリの監視
supervise プロセスの監視および制御
multilog ロギング

daemontools - Wikipedia

daemontools のインストール

yumrpm もイマイチこれや!ってのがないので、本家?からソース毎ダウンロードしてインストールします

$ curl -O http://cr.yp.to/daemontools/daemontools-0.76.tar.gz
$ tar zxvf daemontools-0.76.tar.gz
$ cd admin/daemontools-0.76/
$ curl -O http://djbware.csi.hu/patches/daemontools-0.76.errno.patch
$ patch -p1 < daemontools-0.76.errno.patch
$ sudo ./package/install 

インストールが完了すると /usr/local/bin, /command あたりにそれらしい実行ファイルが作成されていると思いますが、すべての実体がソースを展開したところに配置されているのでまじめに運用するときにはそこからちゃんと検討しないといけない。

svscan

まずはdaemontools本丸である svscan を起動しなければいけない。起動は svscanboot コマンドで行うがインストールでは /etc/inittab にそれが記載されている

SV:123456:respawn:/command/svscanboot

が、CentOSでは?これが効かないのでこれはコメントアウトしてupstartによる起動に変更する。以下のような内容の /etc/init/svscan.conf を作成する

start on runlevel [12345]
respawn
exec /command/svscanboot

これでOS起動時に svscan が立ち上がるし、このプロセスが落ちても自動復旧(再立ち上げ)される。

$ ps ax | grep svscan
  586 ?        Ss     0:00 /bin/sh /command/svscanboot
  594 ?        S      0:00 svscan /service

試しにsvscanのプロセスをkillしてみると、/var/log/messages に

Feb 12 22:49:01 localhost init: svscan main process ended, respawning

と記録され再びsvscanが立ち上がってます。これでsvscanがプロセスから消えることは無い状態になりました.

supervise

次にパッケージ(デーモンサービス)を監視する supervise です。パッケージはそれぞれひとつのディレクトリ内で管理されます。

daemon_name/run   #デーモンの実行ファイルをrunとして配置する。

としてそれを

/service/daemon_name

として配置することでsvscanの管理下となります。( daemon_name を別のパスで作成してシンボリックリンクを貼ることで配置することも一般的です)
今回は動作確認のため簡単なデーモン?をシェルで作ってみました。

$ cat run 
#!/bin/sh

i=1
while [ 1 ];
do
  echo $i
  i=`expr $i + 1`
  sleep 1
done;

実際にはrunはデーモンで動作するプログラムを起動するシェルになる場合が一般的です。その場合は run のシェルの中で exec を利用して目的のプログラムを起動します。
今回のディレクトリ構成は

$ find ~/test_job/
/home/keisyu/test_job/
/home/keisyu/test_job/run
$ chmod +t test_job

とします。test_job にスティッキービットを立てる必要があるのでそうします (chmod +t)
これ(test_jobディレクトリ)を/serviceにリンクします。すると run が起動します。

$ sudo ln -s /home/keisyu/test_job 
$ ps ax 
 1221 ?        S      0:00 supervise test_job
 1222 ?        S      0:00 /bin/sh ./run
$ sudo svstat /service/test_job/    #サービスの状態を確認するコマンド
/service/test_job/: up (pid 1222) 197 seconds

test_job/supervise というフォルダが自動的に作成されますがdaemontoolsの管理用なので触らないです.

$ sudo svc -u /service/test_job  # サービス(run)を起動します
$ sudo svc -d /service/test_job  # サービス(run)を停止させます
  • d -u 以外にも run に各種シグナルが送れますので必要であればググってください。

multilog

デーモンが標準/エラー出力等を行う情報を記録するためのコマンドです。supervise と合わせて使うことで deamontoolsで管理しているプロセスにおけるロギングの管理が用意になります。
先ほどの test_job におけるロギングを行うということで実際にやってみます

test_job/
test_job/run
test_job/supervise #これは自動的に作られる
test_job/log
test_job/log/run
test_job/log/supervise #これは自動的に作られる
test_job/log/main #これは自動的に作られる

という形で log のフォルダとその直下に run というファイルを配置します。 run はmultilogを起動するシェルであり最低限の内容として以下にします。

#!/bin/sh
exec multilog t ./main

すると log/main フォルダ以下に current ファイルが生成され run の出力がロギングされます。

# tail -f current 
...
@4000000052fb885a329f8e7c 89
@4000000052fb885b32d7b57c 90
@4000000052fb885c32f7439c 91
@4000000052fb885d3320861c 92
...

なんかよくわからんくなった時の対応

run コマンドを修正したいとかそうした時にsvscanの管理下にある状態で修正すると混乱します
その場合は以下の手順でやる。

# cd /service
# mv test_job .test_job
# svc -dx /service/.test_job
# log 以下の supervise, multilogってプロセスが死んでくれないのでkillする。正しい方法がわからん...
# 色々修正
# mv .test_job test_job
# svc -u /service/test_job

|

Linux自動インストール = Kickstart

昨日 VirttualBox に CentOSをインストールしてホストPC(MAC)からSSHで接続できるようにしました。
ここまでは飽きるほどやってたことなので今までやってみたことなかった Kickstart でのインストールをやってみます。

Kiskstartファイル ks.cfg

Kickstartでは自動インストールのレシピをファイル化しそれをLinuxインストール時に読み込ませて自動インストール実施します。
Kickstartファイルはあちこちでサンプルが落ちていますが、前回CentOSをインストールした時にその記録が /root/anaconda-ks.cfg に保存されています。これがKickstartファイルとして利用できます。こんな感じです。

# Kickstart file automatically generated by anaconda.

#version=DEVEL
install
url --url=http://ftp.riken.jp/Linux/centos/6.5/os/x86_64/
lang en_US.UTF-8
keyboard jp106
network --onboot yes --device eth0 --bootproto dhcp --noipv6
network --onboot no --device eth1 --bootproto dhcp --noipv6
rootpw  --iscrypted $6$xMBrykBveErIkSvJ$CX1l27S1.jpV7kGs9RtcMgrjchmhQ4PVApun5B/w/WEDQtTkRxDsyl/KcpwZtIG7JYwuEp3Rtj2k06rXjnwhc0
firewall --service=ssh
authconfig --enableshadow --passalgo=sha512
selinux --enforcing
timezone --utc Asia/Tokyo
bootloader --location=mbr --driveorder=sda --append="crashkernel=auto rhgb quiet"
# The following is the partition information you requested
# Note that any partitions you deleted are not expressed
# here so unless you clear all partitions first, this is
# not guaranteed to work
#clearpart --linux --drives=sda
#volgroup VolGroup --pesize=4096 pv.008002
#logvol / --fstype=ext4 --name=lv_root --vgname=VolGroup --grow --size=1024 --maxsize=51200
#logvol swap --name=lv_swap --vgname=VolGroup --grow --size=819 --maxsize=819

#part /boot --fstype=ext4 --size=500
#part pv.008002 --grow --size=1


repo --name="CentOS"  --baseurl=http://ftp.riken.jp/Linux/centos/6.5/os/x86_64/ --cost=100

%packages --nobase
@core
%end
  • eth1がonboot no になってますね。これを yes にすればいい感じになりそう
  • selinux --enforcing ってなってるからこれを --disabled にしたらいい感じになりそう。
  • firewallってのはiptablesのデフォルト設定みたいです。

などなど、色々なオプションはRedHadのドキュメント - 28.4. キックスタートのオプション に記載されています。

まずはKickstartを試してみることを再優先にすべくあまり編集せずに以下の3行だけ変更

network --onboot yes --device eth1 --bootproto dhcp --noipv6
firewall --disabled
selinux --disabled

このファイルをLinuxインストール時にしているんですが、どうやって読み込ませるのか色いろあるんですが(FDDやCDROMからとか)、ネットワーク越しでHTTPダウンロードさせるのが楽で慣例っぽいのでそれにする。HTTPサーバは母艦にhttpdたてるのもよし、外部のサーバからダウンロードさせるもよし、今回はGitHubに保存してそこからダウンロードさせることにします。

https://raw2.github.com/******/centos_install/master/anaconda-ks.cfg

Kiskstart での自動インストール

VirtualBoxで新規OSをエントリーするところまでは同じ。(CentOS.isoを指定したり、ホストオンリーアダプターアダプタの追加も忘れずに)
インストールCD-ROM起動直後のメニューで「esc」を押します。boot: プロンプトが出るので

> linux text ks=https://raw2.github.com/hiyuzawa/centos_install/master/anaconda-ks.cfg

として起動します。
...
...
と思ったらなぜか、「Error downloading kickstart file」って言われた。。
ホストPCにhttpd立ち上げて http://192.168.56.1/anaconda-ks.cfg だとうまくいった。(http://localhost/にしててハマった)

若干対話的な選択が残るもののおおかた自動でインストールされた。