2012年12月31日月曜日

2012年大晦日オフロードツーリングへ行ってきたよ

1年ぶりのツーリング

今年はなかなか時間が取れず行けなかった山へのお散歩に久しぶりに行ってきました。メンバーは4人で、自分と前から一緒に行ってるオフーロードの先生、今回初めてお会いする先輩、それと自分の会社の後輩です。

天気もよく、気持ちよかったです

My machine RM-85 


これが私のバイクです2ストロークの85ccで結構パワーがあっていい感じです

先生の今日のマシン TM-100



外国のバイクでエンデューロレースでは活躍しているTMです、パワーもありますが下も粘りがあり凄い乗りやすいバイクです。その他にもRMX-250、XLR-80改など変なバイクも多数所有しています、さすが先生です



XR-250にKLX-125とセブンで待ち合わせ


真ん中は2002年式XR-250です、シュラウド、倒立サスでカチッと決待った感じで落ち着いた感じのXRでした。右は僕の会社の後輩で新車のKLX-125です、去年も一緒に行ったのですが今回は自分のマシンで参戦です、綺麗なのでチョット汚すのは気が引けるのですが、オフローダーがそんなことを行ってる場合ではありません、頑張って逝きましょうか 笑...



やはりXRはいいですね、まとまったデザインが好きです、でセブンで燃料補給しました

2012年、走り納め



山頂に到着、支度して走る前です


ひと山駆け上がると、こんな綺麗な景色の山頂へさらに登れます、意外と中伊豆の景色は富士山もみえ、天気がいいと素晴らしいです。

さらに、山奥へ入って行きます、えらい急坂のダウンヒルからそのままヒルクライムで汗だくです、(@Д@; アセアセ・・・


ちなみに、しかもここで穴にフロントがおちて前のめりにコケました。山は下に何があるか分からないので皆さんバイクで入るときは気をつけてください(えっ?入らない、そうだよね)

さらに山奥へ....

さらに林道を奥へ進みます、林道っていってもケモノ道です。


よく分からないところでこけてました、笑


よく分からないところでこけてました

ここは傾斜角45度位あって結構きつい上り坂です、みなさんこんな感じで登って逝きました 笑


KLX-125ヒルクライム、笑えます


XR-250ヒルクライム、安定しています



ベテランのスピードです

残念ながら私の動画はありません、残念です

しばし、休憩...

走ってばかりではありません、坂の上でチョット休憩です。世間話など楽しい話題で盛り上がりました。くだらない話の方が多かったような、覚えていません。




そこも絶景です


今日は走りやすいです、清々しい

皆さんよい年をお迎えください

今年も大晦日に走ってきました、いつも2人で走っていましたが、今年は4人で一緒に走れて楽しかったです、伊豆はほんとに綺麗で走るところが充実しているとつくづく思い知らされます。


2山越えて3時間あまり爆走してきました、川もあり、ガレ場、ケモノ道、テクリカルなダウンヒル、パワー全開のヒルクライム、ケツは滑るし、腰は痛いし、でもすっきりデス。

運動不足のプログラーマーから、暇人のプータローでも、メンバー募集中です。

また来年1月2日に走りに行ってきます、伊豆に在住のオフローダーの皆さん一緒に逝きませんか?。笑

2012年12月30日日曜日

LXCのネットワーク設定...続き

LXCのネットワーク設定の不具合を解決

前回作成したLXC(Linux Container)でしたがネットワーク設定がいまいちだったので見直してみた。これで良いのかは微妙なのですが、うまく行ってるっぽいので報告まで
LXCのインストールは前のネタを参照して下さい

まず、ホスト側の設定ファイルのネットワークの設定と、sysfsの設定値をいじくってこんな感じでコメントアウトされている2行を有効にする

karky7 ~ # diff /opt/lxc-gentoo/gentoo2.conf /opt/lxc-gentoo/gentoo2.conf.ORG
16c16
< lxc.network.link = br0
---
> #lxc.network.link = br0
26c26
< lxc.mount.entry=sys /opt/lxc-gentoo/gentoo2/sys sysfs defaults 0 0
---
> #lxc.mount.entry=sys /opt/lxc-gentoo/gentoo2/sys sysfs defaults 0 0
で起動してみる

karky7 ~ # lxc-start -f /opt/lxc-gentoo/gentoo2.conf -n gentoo2

INIT: version 2.88 booting
   OpenRC 0.11.8 is starting up Gentoo Linux (x86_64) [LXC]


 * /proc is already mounted
 * /run/openrc: creating directory
 * /run/lock: creating directory
 * /run/lock: correcting owner
 * Creating user login records ...
 [ ok ]
 * Cleaning /var/run ...
 [ ok ]
 * Wiping /tmp directory ...
 [ ok ]
 * Updating /etc/mtab ...
 [ ok ]
 * Bringing up interface lo
 *   127.0.0.1/8 ...
 [ ok ]
 *   Adding routes
 *     127.0.0.0/8 via 127.0.0.1 ...
 [ ok ]
 * setting up tmpfiles.d entries ...
 [ ok ]
INIT: Entering runlevel: 3
 * Starting local
 [ ok ]

gentoo2 login: root (automatic login)
gentoo2 ~ #

無事コンテナにログインできる

net.eth0を作成する


この設定をやらないと、「sshdとかがnetが無い!」としかられて起動しませんでした
gentoo2 ~ # cd /etc/init.d/
gentoo2 init.d # ln -s net.lo net.eth0
...
...
gentoo2 ~ # /etc/init.d/sshd start
 * Starting sshd ...
 [ ok ]
gentoo2 ~ #

 

LXCにおけるゲスト側のIP、Gatewayなどの設定


Gentooでネットワークの設定は/etc/conf.d/netで設定するのが普通ですが、コンテナのネットワーク設定は基本的にホスト側のgentoo2.confへ書かれているので、得にコンテナ内の/etc/conf.d/netは編集しなくてもい良いらしいです

/opt/lxc-gentoo/gentoo2.conf抜粋

# set arch
lxc.arch = x86_64

# set the hostname
lxc.utsname = gentoo2

# network interface
lxc.network.type = veth
lxc.network.flags = up
# - name in host (max 15 chars; defaults to 'tun'+random)
lxc.network.veth.pair = gentoo2
# - name in guest
lxc.network.name = eth0
# enable for bridging
# (eg. 'brctl addbr br0; brctl setfd br0 0; brctl addif br0 eth0')
lxc.network.link = br0
lxc.network.ipv4 = 192.168.11.125/24
lxc.network.ipv4.gateway = 192.168.11.1
...
...

ホスト側に、コンテナのIPの設定が記載されています
  • lxc.network.ipv4
    • コンテナのIPアドレス
  • lxc.network.ipv4.gateway
    • コンテナのGateway
という感じになっています、ちなみにコンテナ内の/etc/conf.d/netは

gentoo2 ~ # cat /etc/conf.d/net
config_eth0="null"

となっていて、得に設定は必要無いようです、最後にresolv.confの設定を忘れないように...

まぁ適当にやる前に、しっかりドキュメント読めって言われそうだが....



GentooでPersistent-MySQLのebuildを作ってみた

Persistent-MySQLのebuildを作ってみたよ

Yesodをやっててどうも一番使いたいpersistent-mysqlのモジュールがhaskellのoverlayに無さげなので自分で作ってみました(もしあったらごめんなさい)
ghcのバージョンは7.6.1でやってますのでご注意下さい。

dev-haskell/persistent-mysqlのインストール 

手前みそのパッケージなので利用する方は自己責任でお願いします。
まず、laymanで私めのoverlayをインポートして下さい。

overlayを追加

karky7 ~ # layman -L | grep karky7
*karky7                    [Git       ] (git://github.com/karky7/karky7-ove...)

マスクを撤去

/etc/portage/package.keywordsへ以下を追加(ここは自分の設定に合わせて下さい)
#####################
# Persistent MySQL
#####################
dev-haskell/persistent-mysql ~amd64
dev-haskell/mysql ~amd64
dev-haskell/mysql-simple ~amd64
dev-haskell/pcre-light ~amd64

persistent-mysqlをemerge

karky7 ~ # emerge -pv persistent-mysql

These are the packages that would be merged, in order:

Calculating dependencies... done!
[ebuild  N    ~] dev-haskell/mysql-0.1.1.4::gentoo-haskell  USE="doc hoogle -hscolour -profile" 0 kB
[ebuild  N    ~] dev-haskell/mysql-simple-0.2.2.4::gentoo-haskell  USE="doc hoogle -hscolour -profile" 0 kB
[ebuild  N    ~] dev-haskell/persistent-mysql-1.1.0:0/1.1.0::karky7  USE="doc -hscolour -profile" 0 kB
karky7 ~ # emerge persistent-mysql

Yesodから利用する

テストプロジェクトの作成、MySQLを選択する
karky7 ~ # yesod init
Welcome to the Yesod scaffolder.
I'm going to be creating a skeleton Yesod project for you.

What do you want to call your project? We'll use this for the cabal name.

Project name: pstest   
Yesod uses Persistent for its (you guessed it) persistence layer.
This tool will build in either SQLite or PostgreSQL or MongoDB support for you.
We recommend starting with SQLite: it has no dependencies.

    s      = sqlite
    p      = postgresql
    mongo  = mongodb
    mysql  = MySQL
    simple = no database, no auth
    url    = Let me specify URL containing a site (advanced)

So, what'll it be? mysql
...
...

Developでyesodを起動してみる

karky7 pstest # yesod devel
Yesod devel server. Press ENTER to quit
Configuring pstest-0.0.0...
Warning: This package indirectly depends on multiple versions of the same
package. This is highly likely to cause a compile failure.
package ghc-7.6.1 requires Cabal-1.16.0
package bin-package-db-0.0.0.0 requires Cabal-1.16.0
package yesod-1.1.7 requires Cabal-1.16.0.3
Rebuilding application... (using Cabal library)
Starting development server...

on the commandline: Warning:
    -package-confdist/package.conf.inplace is deprecated: Use -package-db instead
Starting devel application
Devel application launched: http://localhost:3000
Migrating: CREATE TABLE `user`(`id` BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,`ident` TEXT CHARACTER SET utf8 NOT NULL,`password` TEXT CHARACTER SET utf8 NULL)
Migrating: ALTER TABLE `user` ADD CONSTRAINT `unique_user` UNIQUE(`ident`(200))
Migrating: CREATE TABLE `email`(`id` BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,`email` TEXT CHARACTER SET utf8 NOT NULL,`user` BIGINT NULL REFERENCES `user`,`verkey` TEXT CHARACTER SET utf8 NULL)
Migrating: ALTER TABLE `email` ADD CONSTRAINT `unique_email` UNIQUE(`email`(200))
Migrating: ALTER TABLE `email` ADD CONSTRAINT `email_user_fkey` FOREIGN KEY(`user`) REFERENCES `user`(`id`)


でMySQLへ接続しているっぽい、もうチョット調べてみます

2012年12月29日土曜日

GentooのLXC(Linux Container)をやってみた

LXCをインストールする

Solaris Zoneは結構お世話になっているコンテナベースの仮想化ですが最近のLinux界隈のコンテナ仮想化はOpenVZ以来ご無沙汰だったので、LXC(Container-based virtualization)を試してみました。

とりあえず色々細かい設定は置いといてコンテナを起動するまでを目標にインストールしてみる。

カーネルをコンテナ用にリビルドする

インストールカーネル
  • Linux karky7 3.6.5-gentoo #11 SMP x86_64 Intel(R) Core(TM) i7-2620M CPU @ 2.70GHz GenuineIntel GNU/Linux
cgroup関連を組み込む
General setup  --->
  --- Control Group support
  [*]   Example debug cgroup subsystem
  [*]   Freezer cgroup subsystem
  [*]   Device controller for cgroups
  [*]   Cpuset support
  [*]     Include legacy /proc/<pid>/cpuset file
  [*]   Simple CPU accounting cgroup subsystem
  [*]   Resource counters
  [*]     Memory Resource Controller for Control Groups
  [*]       Memory Resource Controller Swap Extension
  [*]         Memory Resource Controller Swap Extension enabled by default (NEW)
  [*]       Memory Resource Controller Kernel Memory accounting (EXPERIMENTAL)
  [*]   Enable perf_event per-cpu per-container group (cgroup) monitoring
  -*-   Group CPU scheduler  --->
  [*]   Block IO controller
  [*]     Enable Block IO controller debugging
  --- Group CPU scheduler
  -*-   Group scheduling for SCHED_OTHER
  [*]     CPU bandwidth provisioning for FAIR_GROUP_SCHED
  [*]   Group scheduling for SCHED_RR/FIFO
  [*] Namespaces support  --->
  --- Namespaces support
    [*]   UTS namespace (NEW)
    [*]   IPC namespace (NEW)
    [*]   PID Namespaces (NEW)
    [*]   Network namespace (NEW)
Networking support
  Networking options  --->
    <M> 802.1d Ethernet Bridging
    <*> 802.1Q VLAN Support
Device Drivers  --->
  Character devices  --->
    [*] Unix98 PTY support
    [*]   Support multiple instances of devpts
  
  -*- Network device support  --->
     <M>     MAC-VLAN support (EXPERIMENTAL)
     <M>     Virtual ethernet pair device
karky7 linux # make && make modules_install && make install
karky7 linux # reboot

LXCパッケージをインストール

マスクパッケージなのでマスクを外す
karky7 ~ # emerge -s lxc
Searching...    
[ Results for search key : lxc ]
[ Applications found : 2 ]

*  app-emulation/lxc [ Masked ]
      Latest version available: 0.8.0-r1
      Latest version installed: [ Not Installed ]
      Size of files: 305 kB
      Homepage:      http://lxc.sourceforge.net/
      Description:   LinuX Containers userspace utilities
      License:       LGPL-3
karky7 ~ # cat /etc/portage/package.keywords | grep lxc
app-emulation/lxc ~amd64
karky7 ~ # emerge -pv lxc

These are the packages that would be merged, in order:

Calculating dependencies... done!
[ebuild  N     ] virtual/awk-0  0 kB
[ebuild     U  ] sys-kernel/linux-headers-3.6 [2.6.39] 5,145 kB
[ebuild  N    ~] app-emulation/lxc-0.8.0-r1  USE="-examples" 306 kB
karky7 ~ # emerge lxc
/sys/fs/cgroupがマウントされていない場合、fstabにcgroupをマウントする設定を書いておく
cgroup       /sys/fs/cgroup  cgroup   rw       0 0
karky7 ~ # mount /sys/fs/cgroup

ホスト側へネットワークパッケージをインストールする

Bridge Utilsのインストール
karky7 ~ # emerge net-misc/bridge-utils
Bridgeの設定
karky7 ~ # cat /etc/conf.d/net
bridge_br0="eth0"
bridge_add_eth0="br0"
brctl_br0="setfd 0 sethello 0 stp off"

config_br0="192.168.xx.x/24"
routes_br0="default via 192.168.xx.x"

config_eth0="null"

lxc-gentooでgentooコンテナを作成

ゲスト側のOSのインストールもgentooで行う、(fedoraとかすんなり出来なかっただけの話ですが...笑)
Gentooならコマンド2発位で何とかなった

lcx-gentooのインストール

これは、ネットワークからgentooのstage3あたりのアーカイブを自動的にダウンロードしキャッシュまでやってくれる。キャッシュデータは/var/cache/lxcあたりへ展開される。 lxc-gentooプロジェクトからチェックアウトする
karky7 opt # cd /opt/
karky7 opt # git clone git clone git://github.com/globalcitizen/lxc-gentoo
好みでパスを通してください

Guest OSを作成する

先ほどチェックアウトしたlxc-gentooディレクトリにあるlxc-gentooコマンドを実行し必要なデータを先にcacheさせる。初回の実行時はキャッシュをダウンロードするためチョット時間がかかります。
以下の必要な入力を設定して終わり

  • コンテナ名
  • ホスト名
  • ネットワーク
  • アーキテクチャ(gentoo固有)
  • rootのパスワード

karky7 opt # cd /opt/lxc-gentoo
karky7 lxc-gentoo # ./lxc-gentoo create     
What is the name for the container (recommended &lt;=15 chars)? [gentoo]gentoo1
What hostname do you wish for this container ? [gentoo]gentoo1
What IP address do you wish for this container (enter 'dhcp' to use DHCP) ? [172.20.0.2/24]dhcp
Which gentoo architecture should we use in this container ? [amd64]
Architecture variant (usually '', 'hardened' or 'hardened+nomultilib') ? []
Type guest root password (enter for none):

Thanks! Now sit back and relax while your gentoo brews...


Checking for pre-existing cache in /var/cache/lxc/gentoo/amd64_amd64__rootfs...not found.
Determining path to latest gentoo amd64 stage3 archive...20121210/stage3-amd64-nomultilib-20121210.tar.bz2
Downloading (~130MB), please wait...complete.
Extracting stage3 archive...done.
Downloading gentoo portage (software database) snapshot...done.
Extracting...done.
Copying filesystem...done.
 - writing LXC guest configuration...done.
 - setting hostname...done.
 - setting guest root password..done.
All done!

You can run your container with the 'lxc-start -f gentoo1.conf -n gentoo1'
 - For host-side networking setup info, see ./gentoo1/etc/conf.d/net

Note that container startup will show some errors, these do not matter.

To enter your container for setup WITHOUT running it, try:
 # mount -t proc proc ./gentoo1/proc
 # mount -o bind /dev ./gentoo1/dev
 # chroot ./gentoo1 /bin/bash
 # export PS1=&quot;(gentoo1) $PS1&quot;
 (gentoo1) #   &lt;-- you are now in the guest
... or, start it on the current console with:
    'lxc-start -f gentoo1.conf -n gentoo1'
... or, start it elsewhere and use lxc-console -n gentoo1 to get a shell.

(Report bugs to https://github.com/globalcitizen/lxc-gentoo/issues )

コンテナを起動する

lxc-startコマンドで起動する。
その他にlxc-stopなど他のコマンドもありますので調べてください。
karky7 ~ # lxc-start -f /opt/lxc-gentoo/gentoo1.conf -n gentoo1
INIT: version 2.88 booting

   OpenRC 0.11.8 is starting up Gentoo Linux (x86_64) [LXC]

 * /proc is already mounted
 * /run/openrc: creating directory
 * /run/lock: creating directory
 * /run/lock: correcting owner
 * Caching service dependencies ...
Service `netmount' needs non existent service `net'
Service `pydoc-3.2' needs non existent service `net'
Service `sshd' needs non existent service `net'
 [ ok ]
 * Creating user login records ...
 [ ok ]
 * Cleaning /var/run ...
 [ ok ]
 * Wiping /tmp directory ...
 [ ok ]
 * Updating /etc/mtab ...
 [ ok ]
 * Bringing up interface lo
....
若干エラーが発生してる模様ですが、細かいところは後で調整する予定です。

とりあえず適当です、次回はfedoraとかdebianとかインストールしたり、cgroupでリソースを細かく設定したりしてみたいですな、では

2012年12月17日月曜日

Gentooでemacs+haskell環境を作る

三島Haskell無名関数の会 第一回目にて

「三島Haskell無名関数の会 第一回目」ということで静岡の富士市で行った勉強会の中で、@kzfmさんが「静岡のHaskellerはemacsを使う」というお題でemacsのhaskell環境を披露してもらった。

本題としてはemacsでhaskell環境を作るということで以下の環境を作成
  • virthualenv(Haskellの仮想環境)
  • hlint(コードチェック)
  • ghc-mod(Haskellコードの保管)
  • flymake(構文チェック)

この作業の中で感激した機能で
  • emacs-24で利用可能な「M-x list-package」というパッケージインストール機能
  • hlintでコードの書き方のチェック
  • flymakeでコード編集時の構文チェック
ということで実際に設定してみる


emacs-24のインストール

Gentooでのインストールになるので、ご注意ください、

「list-package」の機能がemacs-24からディフォルトで入っていると言うことなので、emacs-24をインストールする、自分はemacs-23だったのでemacsをアップデート
karky7 ~ # emerge -pv emacs
...
...
[ebuild   R    ] app-editors/emacs-24.2:24
karky7 ~ # emerge -u emacs

Gentooは複数のemacsを利用できるのでeselect-emacsをインストールしておく
karky7 ~ # emerge -pv app-admin/eselect-emacs

These are the packages that would be merged, in order:

Calculating dependencies... done!
[ebuild   R    ] app-admin/eselect-emacs-1.14
..
..
karky7 ~ # emerge app-admin/eselect-emacs

emacsを切り替える、emacs-24だけインストールされているなら必要ありません
karky7 ~ # eselect emacs list
Available Emacs symlink targets:
  [1]   emacs-23 *
  [2]   emacs-24

XEmacs is also installed
karky7 ~ # eselect emacs set 2
Switching emacs to emacs-24 ...
Switching ctags to ctags-emacs-24 ...
Switching etags to etags-emacs-24 ...
karky7 ~ # eselect emacs list
Available Emacs symlink targets:
  [1]   emacs-23
  [2]   emacs-24 *

XEmacs is also installed
karky7 ~ #

旧バージョンをインストールしている人は、emacsのパッケージをアップデートしておく
karky7 ~ # emacs-updater -a all
* Searching for byte-compiled elisp files ...
* Currently selected GNU Emacs version: 24.2.1
Found php-mode.elc (compiled by Emacs 24.2.1)
Found xcscope.elc (compiled by Emacs 24.2.1)
...
...


「list-packageを」をインストールする

ロードパスの設定とpackageのarchiveの設定
;;; ロードパスの追加
(setq load-path (append
           '("~/.emacs.d"
             "~/.emacs.d/packages/emacs-jedi"
             "~/.emacs.d/packages/json-mode"
             "~/.emacs.d/auto-install"
             "~/.emacs.d/custom"
             "~/.emacs.d/conf")
           load-path))

;;; packages.el
(require 'package)
(add-to-list 'package-archives '("melpa" . "http://melpa.milkbox.net/packages/") t)
(add-to-list 'package-archives '("marmalade" . "http://marmalade-repo.org/packages/"))
(package-initialize)

これで、melpaとmarmaladeからパッケージを落とせるようになる


「list-packageを」を使ってみる

「M-x list-package」でパッケージリストを開く、開けたらお好みのパッケージを入れる事が出きるようになる。






ghc-modのインストール

Gentooはghc-modパッケージがマスクされているのでマスクを解除してemergeする
karky7 ~ # emerge -pv app-emacs/ghc-mod

These are the packages that would be merged, in order:

Calculating dependencies... done!
[ebuild  N    ~] dev-haskell/io-choice-0.0.2::gentoo-haskell  USE="doc hoogle -hscolour -profile {-test}" 3 kB
[ebuild  N    ~] dev-haskell/ghc-syb-utils-0.2.1.1::gentoo-haskell  USE="doc hoogle -hscolour -profile" 4 kB
[ebuild  N    ~] dev-haskell/convertible-1.0.11.1::gentoo-haskell  USE="doc hoogle -hscolour -profile {-test}" 15 kB
[ebuild  N    ~] app-emacs/ghc-mod-1.11.2::gentoo-haskell  USE="-emacs" 20 kB

...
...

karky7 ~ # emerge app-emacs/ghc-mod

続いて、「list-package」を使ってghcをインストールする、インストール方法は「C-s」でghc辺りを検索してもらえればghcが見つかると思うので、「i」のキーを押してインストールしたいパッケージを選択する。その後「x」でインストールの実行をする
  • ghc
  • haskell-mode(ちなみにemergeでもあります)


  • 「i」でパッケージを選択
  • 「x」で指定したパッケージをインストール


flymakeのインストール

上の手順と同じで以下のパッケージをインストールしていく
  • flymake
  • flymake-cursor



ghc-modの設定

編集を楽にするようにキーをバインド

キーバインド

  • 「C-j」・・・ 「->」を出力
  • 「M-j」・・・ 「=>」を出力
  • 「C-l」・・・ 「<-」を出力
(autoload 'ghc-init "ghc" nil t)
(add-hook 'haskell-mode-hook '(lambda ()
(ghc-init)
        (local-set-key "\C-j" (lambda () (interactive)(insert " -> ")))
        (local-set-key "\M-j" (lambda () (interactive)(insert " => ")))
        (local-set-key "\C-l" (lambda ()(interactive)(insert " <- ")))
            ))

これがhaskellのコードを書いてると意外にだるいので、助かる


run-haskellの起動

コードをチェックする時にghciを起動するのですが毎回:lでコードをloadするのが面倒なので、ghciの起動とファイルの読み込みを「C-c C-l」で実行出来るようにしておく
(defadvice inferior-haskell-load-file (after change-focus-after-load)
  "Change focus to GHCi window after C-c C-l command"
  (other-window 1))
(ad-activate 'inferior-haskell-load-file)


flymakeの設定

;; haskell ghc-mod
;; https://github.com/kazu-yamamoto/ghc-mod
(autoload 'ghc-init "ghc" nil t)
(add-hook 'haskell-mode-hook (lambda () (ghc-init) (flymake-mode)))


hlintのインストール

hlintはGentooのパッケージがあったのでそれを利用する(Maskでした)
karky7 ~ # emerge -pv hlint

These are the packages that would be merged, in order:

Calculating dependencies... done!
[ebuild  N     ] dev-haskell/hscolour-1.19::gentoo-haskell  USE="doc -profile" 25 kB
[ebuild  N    ~] dev-haskell/haskell-src-exts-1.13.5:0/1.13.5::gentoo-haskell  USE="doc hoogle -hscolour -profile" 285 kB
[ebuild  N    ~] dev-haskell/uniplate-1.6.7::gentoo-haskell  USE="doc hoogle -hscolour -profile" 30 kB
[ebuild  N    ~] dev-haskell/hlint-1.8.35:0/1.8.35::gentoo-haskell  USE="doc hoogle -emacs -hscolour -profile" 62 kB

Total: 4 packages (4 new), Size of downloads: 401 kB
...
...

karky7 ~ # emerge hlint


haskell-modeの設定

;;; haskell-mode
(require 'haskell-mode)
(add-hook 'haskell-mode-hook 'turn-on-haskell-indentation)


flymake使ってみる

適当にtest.hsなどを開いて編集してみる

cuomo@karky7 ~ $ emacs test.hs

編集でシンタックスエラーを起こすと赤でエラー部分を表示してくれる




構文を直すと、今度は宣言が無いので警告を青で表示してくれる




hlintを使ってみる

「C-c C-c」でチェックをhlintに変えるすると「doがいらないよ」と赤く表示してくれる、要するに綺麗な書き方を指導してくれる。




これで、入力補完、構文チェックがコード編集時に可能になる、これなら逝けるんじゃないか?
PHP、Pythonもこれで生きましょう (笑)


元ネタ

「静岡のHaskellerはemacsを使う @kzfm」

HaskellのFunctorのおさらい

Functorってなに?

Functorとは「ある関数で値を写して新しい値を作る」型クラスらしい、数学的には「関手」とか言うらしいが、まぁ「写像」程度の理解度でいいのか。
ApplicativeやらMonadやらでつまずくので、Functorは理解したい、なので...

Functor調べる

とりあえず、Functorクラスの情報を調べてみる、Functorとは型クラスでfmapって言う関数が定義されている
Prelude> :i Functor
class Functor f where
  fmap :: (a -> b) -> f a -> f b
  (GHC.Base.<$) :: a -> f b -> f a
   -- Defined in `GHC.Base'
instance Functor Maybe -- Defined in `Data.Maybe'
instance Functor [] -- Defined in `GHC.Base'
instance Functor IO -- Defined in `GHC.Base'
Prelude>

そしての「Maybe」とか「[]」がFunctorのインスタンスになっているのがわかる


fmapの使い方

実際に使ってみる
Prelude> fmap (+10) [1,2,3,4,5]
[11,12,13,14,15]
Prelude> fmap (+10) (Just 20)
Just 30
Prelude> fmap (+10) Nothing
Nothing
Prelude>

簡単な使い方はこんな感じ、fmapの動作は
  • [] の場合、配列のそれぞれの要素に(+10)を適用して新しい配列[11,12,13,14,15]を返してくる
  • Maybeの場合、Just (20 +(10))、要するにfmapがJustの中身に(+10)を適用して返してくる
要するに、「fmap :: (a -> b) -> f a -> f b」を直訳すると

「型aから型bに変換する関数に、型aのファンクタ値を適用して、型bのファンクタ値を生成する」

ってことか


自分の型をFunctorクラスのインスタンスにしてみる

実際に自分の型を作成してFunctorクラスのインスタンスにしてみる。ThisTypeデータ型を宣言してGHCiに読み込ませてみる

FuncSample.hs
data ThisType a = ThisType a deriving(Eq, Show)

GHCiを起動してThisType型の動作を確認する
Prelude> :l FuncSample
[1 of 1] Compiling Main             ( FuncSample.hs, interpreted )
Ok, modules loaded: Main.
*Main> :i ThisType
data ThisType a = ThisType a  -- Defined at FuncSample.hs:1:6
instance Eq a => Eq (ThisType a) -- Defined at FuncSample.hs:1:37
instance Show a => Show (ThisType a)
  -- Defined at FuncSample.hs:1:41
*Main> :t ThisType
ThisType :: a -> ThisType a
*Main> ThisType 20
ThisType 20
*Main> ThisType "ABC"
ThisType "ABC"
*Main>

Functorとして使ってみると、まずThisType型がFunctor型クラスのインスタンスとして宣言されていないエラーと怒られる、なるほど、ではFunctorのインスタンスにしてみる
*Main> fmap (+10) (ThisType 20)

<interactive>:19:1:
    No instance for (Functor ThisType)
      arising from a use of `fmap'
    Possible fix: add an instance declaration for (Functor ThisType)
    In the expression: fmap (+ 10) (ThisType 20)
    In an equation for `it': it = fmap (+ 10) (ThisType 20)
*Main>

FuncSample.hsにinstanceを追加
data ThisType a = ThisType { getThisType :: a } deriving(Eq, Show)
instance Functor ThisType where
    fmap f (ThisType x) = ThisType (f x)

main = do
       let val1 = getThisType $ fmap (+10) (ThisType 20)
           val2 = getThisType $ fmap ("#A君"++) (ThisType "メリーゴーランドに乗る")
       putStrLn $ show(val1)
       putStrLn $ val2

もう一度同じ計算をやらせてみると
~ $ runhaskell FuncSample.hs
30
#A君メリーゴーランドに乗る
~ $

#A君もメリーゴーランドに乗れる


ThisTypeは型コンストラクタ

:k でThisTypeを調べてみると、ThisTypeは型引数を1つ取る型コンストラクタでMaybeとかと同じ事が分かります。Functor型クラスのインスタンスにしたい場合は型引数を1つ取る型コンストラクタでなければならないということ。
*Main>
*Main> :k ThisType
ThisType :: * -> *
*Main> :k Maybe
Maybe :: * -> *
*Main> :k []
[] :: * -> *
*Main>


ThisTypeはFunctor則を満たしてるのか?

これが正確かどうか分からないがThisType型がFunctor則を満たしているか確認する

以下のFunctor則の二つ
  • 第1法則 fmap id = id
  • 第2法則 fmap (f . g) x = fmap f (fmap g x)
Functor則を満たしているかは上の2式を満たしているかどうかで分かるらしい

第1法則 fmap id = id
fmap id = idを満たしているか確認する、多分これはカリー化されているので書き直すとこんな感じか
 fmap id (f a) = id (f a) これは
*Main> fmap id (ThisType 20) == id (ThisType 20)
True
*Main>
とりあえず満たしている

第2法則 fmap (f . g) x = fmap f (fmap g x)これは、関数fと関数gの合成関数とファンクター値にfmapを適用したものと、最初に関数gとfmapを適用し生成したファンクター値をさらに関数fでfmapしたファンクター値が等しくなればいいということ

f = (+10)、g = (+50)として試してみる
*Main> let f=(+10)
*Main> let g=(+50)
*Main> fmap (f . g) (ThisType 20) == fmap f (fmap g (ThisType 20))
True
*Main>

これも良さそう、これでThisTypeはFunctorでしょう(微妙か...)


Functorの定義

ちなみにこの書き方でもできました

FuncSample.h
{-# LANGUAGE DeriveFunctor #-}
data ThisType a = ThisType { getThisType :: a } deriving(Eq, Show, Functor)
  • ファイルの最初に{-# LANGUAGE DeriveFunctor #-}を書く
  • derivingにFunctorを追加する

実行してみると
*Main> fmap id (ThisType 20) == id (ThisType 20)
True
*Main> fmap ((+10) . (+50)) (ThisType 20) == fmap (+10) (fmap (+50) (ThisType 20))
True
*Main>

同じ結果となる、こういう理解でいいと思うが間違いがあったら指摘してください、ヨロピク

TemplateHaskellを調べてみた

TemplateHaskellでちょっと理解したことをメモ

ここんところTemplateHaskellでコケてしまったので忘れないうちにメモ

TemplateHaskellとは

Haskellのドキュメントには「Template Haskell is a GHC extension to Haskell that adds compile-time metaprogramming facilities.」ってかかれてて、GHCのextensionでコンパイルのメタプログラミングを出きるようにする機能らしいが何が何だか解らないので簡単なところで調べてみた
マクロみたいなもので抽象構文木(AST)として記述するとか説明があるけどよく解らない...笑


ghciから使ってみる

ghciを起動するときに-XTemplateHaskellってオプションをつけて起動するか、ghciを起動した後に:setで足してもいい、それからモジュールを読み込む

GHCi, version 7.4.1: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude>
Prelude> :set -XTemplateHaskell
Prelude> :m +Language.Haskell.TH
Prelude Language.Haskell.TH>


いきなり使ってみるが...Q Expがshowのinstanceでないので叱られる始末
Prelude Language.Haskell.TH> [e|1+1|]
<interactive>:15:1:
    No instance for (Show (Q Exp))
      arising from a use of `print'
    Possible fix: add an instance declaration for (Show (Q Exp))
    In a stmt of an interactive GHCi command: print it
Prelude Language.Haskell.TH>


とりあえずこいつの型を調べてみると、Q Expってなに?そもそもQってなに?
Prelude Language.Haskell.TH> :t [e|1+1|]
[e|1+1|] :: Q Exp
Prelude Language.Haskell.TH>


ここでとりあえずモジュール一覧を確認、見たところでほとんど解らない...何かQはnewtypeされててMonadクラスとFunctorのクラスのinstanceになってるらしい
Prelude Language.Haskell.TH> :browse
data Body = GuardedB [(Guard, Exp)] | NormalB Exp
type BodyQ = Q Body
data Callconv = CCall | StdCall
data Clause = Clause [Pat] Body [Dec]
type ClauseQ = Q Clause
data Con
  = NormalC Name [Language.Haskell.TH.Syntax.StrictType]
  | RecC Name [Language.Haskell.TH.Syntax.VarStrictType]

...
...

newtype Q a
  = Language.Haskell.TH.Syntax.Q {
       Language.Haskell.TH.Syntax.unQ :: forall (m :: * -> *).Language.Haskell.TH.Syntax.Quasi m => m a}
instance Monad Q -- Defined in `Language.Haskell.TH.Syntax'
instance Functor Q -- Defined in `Language.Haskell.TH.Syntax'
...
...
...


次にExpってなにか調べてみる
Prelude Language.Haskell.TH> :i Exp
data Exp
  = VarE Name
  | ConE Name
  | LitE Lit
  | AppE Exp Exp
  | InfixE (Maybe Exp) Exp (Maybe Exp)
  | UInfixE Exp Exp Exp
  | ParensE Exp
  | LamE [Pat] Exp
  | TupE [Exp]
  | UnboxedTupE [Exp]
  | CondE Exp Exp Exp
  | LetE [Dec] Exp
  | CaseE Exp [Match]
  | DoE [Stmt]
  | CompE [Stmt]
  | ArithSeqE Range
  | ListE [Exp]
  | SigE Exp Type
  | RecConE Name [FieldExp]
  | RecUpdE Exp [FieldExp]
      -- Defined in `Language.Haskell.TH.Syntax'
instance Eq Exp -- Defined in `Language.Haskell.TH.Syntax'
instance Show Exp -- Defined in `Language.Haskell.TH.Syntax'
instance Ppr Exp -- Defined in `Language.Haskell.TH.Ppr'
Prelude Language.Haskell.TH>

なるほどExpとはそんな感じなのね、って解らない、挫折寸前でこのサイトを見つける「Basic Tutorial of Template Haskell」そこには4つほどタイプがあって

  • Expression quotations
[e|1+2|]って式を書くパターン
  • Declaration quotations
[d|x = 5]って定義を書くパターン
  • Type quotations
[t|Int|]って型を書くパターン
  • Pattern quotations
[p|(x,y)]ってパターンを書くパターン...笑

パターンって2回言った...で使ってたのがExpression quotationってやつ、で調べている過程でrunQっていう関数を発見、こいつは上のquotationを展開してくれるっぽい


runQで色々やってみる

[e|1+1|]はQ Expでイケそうな気がする
Prelude Language.Haskell.TH> :i runQ
runQ :: Language.Haskell.TH.Syntax.Quasi m => Q a -> m a
      -- Defined in `Language.Haskell.TH.Syntax'
Prelude Language.Haskell.TH>
Prelude Language.Haskell.TH> runQ [e|1+1|]
Loading package array-0.4.0.0 ... linking ... done.
Loading package deepseq-1.3.0.0 ... linking ... done.
Loading package containers-0.4.2.1 ... linking ... done.
Loading package pretty-1.1.1.0 ... linking ... done.
Loading package template-haskell ... linking ... done.
InfixE (Just (LitE (IntegerL 1))) (VarE GHC.Num.+) (Just (LitE (IntegerL 1)))
Prelude Language.Haskell.TH>
Prelude Language.Haskell.TH> let ex = [e|1+1|]
Prelude Language.Haskell.TH> :t ex
ex :: Q Exp
Prelude Language.Haskell.TH>
Prelude Language.Haskell.TH> $(st)
2
Prelude Language.Haskell.TH>
Prelude Language.Haskell.TH> :t InfixE
InfixE :: Maybe Exp -> Exp -> Maybe Exp -> Exp
Prelude Language.Haskell.TH>
で$()で実行されるのか

もうちょいいじってみる
Prelude Language.Haskell.TH>
Prelude Language.Haskell.TH> $(return (InfixE (Just (LitE (IntegerL 1))) (VarE (mkName "+")) (Just (LitE (IntegerL 1)))))
2
Prelude Language.Haskell.TH>

Qモナド?辺りに包んで返せば同じ結果になる、要するにコンパイル時にソースコードに掛かれた[|expression|]を展開してくれる機能なのか、ちなみに[]は「オックスフォード角括弧」って言うらしい、覚えきれない、難しいのですが他のタイプも調べてみます。

btrfsを実際に触ってみた

最近話題のbtrfsを弄ってみました

btrfsをカーネルに組み込む

btrfsは現在EXPERIMENTALなので注意して利用してください、HDDを初期化しますのでご自分の責任において実行してください、責任はとれませんのでご注意を...

カーネルでbtrfsが使えるように設定する、実行環境はGentoo Linuxなので他のディストリビューションの方はその通りにやってください
Kernel: Linux karky7 3.6.5-gentoo #9 SMP
Arch:   Intel(R) Core(TM) i7-2620M CPU @ 2.70GHz GenuineIntel GNU/Linux

カーネルオプションを設定、カーネル組み込み、モジュールでもいいのでfilesystemのオプションを設定してカーネルをコンパイルしておく、rebootを忘れずに
File systems  --->
    <M> Btrfs filesystem (EXPERIMENTAL) Unstable disk format

カーネルオプション画像






モジュールで作成した場合は以下のようにmodprobeでカーネルに読み込んでおく
karky7 ~ # modprobe btrfs
karky7 ~ # lsmod | grep btrfs
btrfs                2061160  0
zlib_deflate           44485  1 btrfs
karky7 ~ # dmesg
...
...
Btrfs loaded
モジュールが読み込まれていることを確認


btrfsユーティリティプログラムをビルドする

btrfs関連のコマンドを利用するため以下のパッケージをインストールする
karky7 ~ # emerge -pv sys-fs/btrfs-progs
..
..
Calculating dependencies... done!
[ebuild   R    ] sys-fs/btrfs-progs-0.19.11  0 kB
...
...
karky7 ~ # emerge sys-fs/btrfs-progs

btrfsを構築する

まず、/dev/sdbをbtrfsに初期化する、オプションは

  • L: ラベル
  • m: metadataの保存アルゴリズムにraid10を使用
  • d: dataの保存アルゴリズムにraid10を使用


でメタデータとデータの冗長性を確保する、/dev/sdb1、/dev/sdb2、/dev/sdc1、/dev/sdc2、はそれぞれ100GBのスライスで作ってある
karky7 ~ # mkfs.btrfs -L bt1 -m raid10 -d raid10 /dev/sdb1 /dev/sdb2 /dev/sdc1 /dev/sdc2

WARNING! - Btrfs Btrfs v0.19 IS EXPERIMENTAL
WARNING! - see http://btrfs.wiki.kernel.org before using

adding device /dev/sdb2 id 2
adding device /dev/sdc1 id 3
adding device /dev/sdc2 id 4
fs created label bt1 on /dev/sdb1
        nodesize 4096 leafsize 4096 sectorsize 4096 size 400.00GB
Btrfs Btrfs v0.19
karky7 ~ #


btrfsの情報を見る

karky7 ~ # btrfs filesystem show --all-devices
Label: 'bt1'  uuid: 2dcc9b0a-f838-414b-aa38-069043e65709
        Total devices 4 FS bytes used 28.00KB
        devid    2 size 100.00GB used 2.01GB path /dev/sdb2
        devid    1 size 100.00GB used 2.03GB path /dev/sdb1
        devid    4 size 100.00GB used 2.01GB path /dev/sdc2
        devid    3 size 100.00GB used 2.01GB path /dev/sdc1

Btrfs Btrfs v0.19
karky7 ~ #

btrfsをマウントする

karky7 ~ # mkdir /mnt/btrfs
karky7 ~ # mount -t btrfs /dev/sdb1 /mnt/btrfs

subvolumeを作成

karky7 ~ # btrfs subvolume create /mnt/btrfs/dir1
Create subvolume '/mnt/btrfs/dir1'
karky7 ~ # btrfs subvolume create /mnt/btrfs/dir2
Create subvolume '/mnt/btrfs/dir2'
karky7 ~ # ls -l /mnt/btrfs/
total 0
drwxr-xr-x 1 root root 0 Nov  4 23:06 dir1
drwxr-xr-x 1 root root 0 Nov  4 23:06 dir2
karky7 ~ #
とりあえずディレクトリができるだけ


Snapshotをとってみる

ファイルを/mnt/btrfs/dir1に適当においてからスナップショットをとってみる、dir1のスナップがdir1_snapディレクトリに出来る
karky7 ~ # cp /etc/*.conf /mnt/btrfs/dir1/
karky7 ~ # ls /mnt/btrfs/dir1
GeoIP.conf            dhcpcd.conf         eix-sync.conf    gai.conf        host.conf    ltrace.conf  mdadm.conf   nsswitch.conf  rc.conf      rsyncd.conf   tmux.conf
ca-certificates.conf  dispatch-conf.conf  etc-update.conf  genkernel.conf  idmapd.conf  make.conf    mke2fs.conf  ntp.conf       redis.conf   sandbox.conf  whois.conf
colord.conf           e2fsck.conf         fuse.conf        gentwoo.conf    ld.so.conf   man.conf     nscd.conf    prelink.conf   resolv.conf  sysctl.conf
karky7 ~ #
karky7 ~ # btrfs subvolume snapshot /mnt/btrfs/dir1 /mnt/btrfs/dir1_snap
Create a snapshot of '/mnt/btrfs/dir1' in '/mnt/btrfs/dir1_snap'
karky7 ~ #
karky7 ~ # ls -l /mnt/btrfs/
total 0
drwxr-xr-x 1 root root 708 Nov  4 23:10 dir1
drwxr-xr-x 1 root root 708 Nov  4 23:10 dir1_snap
drwxr-xr-x 1 root root   0 Nov  4 23:06 dir2
karky7 ~ # ls /mnt/btrfs/dir1_snap/
GeoIP.conf            dhcpcd.conf         eix-sync.conf    gai.conf        host.conf    ltrace.conf  mdadm.conf   nsswitch.conf  rc.conf      rsyncd.conf   tmux.conf
ca-certificates.conf  dispatch-conf.conf  etc-update.conf  genkernel.conf  idmapd.conf  make.conf    mke2fs.conf  ntp.conf       redis.conf   sandbox.conf  whois.conf
colord.conf           e2fsck.conf         fuse.conf        gentwoo.conf    ld.so.conf   man.conf     nscd.conf    prelink.conf   resolv.conf  sysctl.conf
karky7 ~ #

ちなみにReadonlyなsnapshopもとれる
karky7 ~ # btrfs subvolume snapshot -r /mnt/btrfs/dir1 /mnt/btrfs/dir1_readonly_snap
Create a readonly snapshot of '/mnt/btrfs/dir1' in '/mnt/btrfs/dir1_readonly_snap'
karky7 ~ # echo 'Kakikomeruka?' > /mnt/btrfs/dir1_readonly_snap/kakiko.txt
-su: [f:id:cantimerny:20121105004411g:plain]/mnt/btrfs/dir1_readonly_snap/kakiko.txt: Read-only file system
karky7 ~ #

削除したファイルを戻す場合はcpやrsyncで行うらしい、zfs rollback的なコマンドがあればいいなとも思ったがzfsと若干扱いが違うので良とする
karky7 ~ # rm /mnt/btrfs/dir1/*
karky7 ~ # ls /mnt/btrfs/dir1/
karky7 ~ # ls /mnt/btrfs/dir1_readonly_snap/
GeoIP.conf            dhcpcd.conf         eix-sync.conf    gai.conf        host.conf    ltrace.conf  mdadm.conf   nsswitch.conf  rc.conf      rsyncd.conf   tmux.conf
ca-certificates.conf  dispatch-conf.conf  etc-update.conf  genkernel.conf  idmapd.conf  make.conf    mke2fs.conf  ntp.conf       redis.conf   sandbox.conf  whois.conf
colord.conf           e2fsck.conf         fuse.conf        gentwoo.conf    ld.so.conf   man.conf     nscd.conf    prelink.conf   resolv.conf  sysctl.conf
karky7 ~ # cp /mnt/btrfs/dir1_readonly_snap/* /mnt/btrfs/dir1/


サイズを確認する

karky7 ~ # btrfs file df /mnt/btrfs/
Data, RAID10: total=10.00GB, used=1.40MB
Data: total=8.00MB, used=0.00
System, RAID10: total=16.00MB, used=4.00KB
System: total=4.00MB, used=0.00
Metadata, RAID10: total=9.00GB, used=184.00KB
Metadata: total=8.00MB, used=0.00
karky7 ~ #
karky7 ~ # df -h
Filesystem      Size  Used Avail Use% Mounted on
rootfs          201G  133G   58G  70% /
/dev/root       201G  133G   58G  70% /
tmpfs           3.9G  288K  3.9G   1% /run
rc-svcdir       1.0M   88K  936K   9% /lib64/rc/init.d
cgroup_root      10M     0   10M   0% /sys/fs/cgroup
udev             10M     0   10M   0% /dev
shm             3.9G  136K  3.9G   1% /dev/shm
/dev/sdb1       400G  3.2M  382G   1% /mnt/btrfs
karky7 ~ #
btrfs file df /mnt/btrfs/とdf -hの出力が違う、そもそもtotal=10.00GBとかどこの領域をさしているのか分からない、あとで調べる


リサイズしてみる

減らす事はないと思うが一様やってみる、広げられればいいと思うが、出来ればsubvolumeに大して容量を設定したいような気がする...zfs create -V 2G rpool/dir1みたいな
karky7 ~ # df -h
Filesystem      Size  Used Avail Use% Mounted on
...
karky7 ~ # btrfs filesystem resize -10G /mnt/btrfs
Resize '/mnt/btrfs' of '-10G'
karky7 ~ # df -h
Filesystem      Size  Used Avail Use% Mounted on
...
/dev/sdb1       390G  3.7M  342G   1% /mnt/btrfs
karky7 ~ # btrfs filesystem resize max /mnt/btrfs
Resize '/mnt/btrfs' of 'max'
karky7 ~ # df -h
Filesystem      Size  Used Avail Use% Mounted on
...
/dev/sdb1       400G  3.7M  382G   1% /mnt/btrfs
karky7 ~ #


デバイスを外してみる

これがいかない、実行手順が悪いのか分からないが後で調べる
karky7 ~ # btrfs fi show
Label: 'bt1'  uuid: 2dcc9b0a-f838-414b-aa38-069043e65709
        Total devices 4 FS bytes used 1.83MB
        devid    4 size 100.00GB used 8.51GB path /dev/sdc2
        devid    3 size 100.00GB used 8.51GB path /dev/sdc1
        devid    2 size 100.00GB used 8.51GB path /dev/sdb2
        devid    1 size 100.00GB used 8.53GB path /dev/sdb1

Btrfs Btrfs v0.19
karky7 ~ #
karky7 ~ # btrfs device delete /dev/sdc1 /mnt/btrfs
ERROR: error removing the device '/dev/sdc1' - Invalid argument


基本的な機能を試してみました、やはりCOWやsnapshotなど結構ありがたい機能が揃っています。Stableのリリースまでには結構重宝しそうな機能になるとおもいます。
今度はbtrfsをrootファイルシステムにしてGentooをインストールしたいという、野望が...出来なかった機能は後で調べます

Gentoo + nginx + FastCGI PHP で高速PHP環境を構築する

FPM-PHPを設定したPHPをインストールする

FPM(FastCGI Process Manager)なPHPをインストールする、Gentooの場合はUSEフラグをセットしてください


USEフラグの確認、その他のディストリビューションの方はそのようにやってください
karky7 ~ # equery u dev-lang/php
...
...
 - - fpm                 : Enable the FastCGI Process Manager SAPI
...
...
 - - xsl                 : Check/Support flag for XSL library (version 1)
 + - zip                 : Enable ZIP file support
 + + zlib                : Adds support for zlib (de)compression
karky7 ~ #


FPMのUSEフラグを有効にしてPHPをインストール
karky7 ~ # USE="fpm" emerge php
...
>>> Emerging (1 of 1) dev-lang/php-5.4.6
...
...


FPMのPHPのバージョンを確認、もし複数ある場合はeselectでセットしてください
karky7 ~ # eselect php list fpm
[1]   php5.4 *
karky7 ~ #


FPM-PHPの設定をする、このあたりは後でお好みで調整してください
karky7 ~ # diff /etc/php/fpm-php5.4/php-fpm.conf /etc/php/fpm-php5.4/php-fpm.conf.ORG
99c99
< listen = 0.0.0.0:9000
---
> listen = 127.0.0.1:9000
160c160
< pm.start_servers = 20
---
> ;pm.start_servers = 20
karky7 ~ #


PHPの設定をする、とくに設定はいらないのですが、タイムゾーン系のエラーが出るので調整しておく、後はお好みで設定してください
karky7 ~ # cp /etc/php/fpm-php5.4/php.ini /etc/php/fpm-php5.4/php.ini.ORG
karky7 ~ # emasc /etc/php/fpm-php5.4/php.ini
-su: emasc: command not found
karky7 ~ # emacs /etc/php/fpm-php5.4/php.ini
karky7 ~ # diff /etc/php/fpm-php5.4/php.ini /etc/php/fpm-php5.4/php.ini.ORG
919c919
< date.timezone = Asia/Tokyo
---
> ;date.timezone =
karky7 ~ #


FPM-PHPをポート8989で動かす
karky7 ~ # /etc/init.d/php-fpm start
 * Starting PHP FastCGI Process Manager ...                         [ ok ]
karky7 ~ # netstat -l | grep 8989
tcp        0      0 *:8989                  *:*                     LISTEN
karky7 ~ #


nginxをインストールする

結構フラグがいっぱいあるので調べましょう、#A君は英語が読めないのでスルーします
karky7 ~ # emerge -pv nginx
...
...
[ebuild  N     ] dev-libs/geoip-1.4.8  USE="ipv6 -perl-geoipupdate -static-libs" 1,790 kB
[ebuild  N     ] www-servers/nginx-1.2.1  USE="http http-cache ipv6 pcre ssl -aio -debug -libatomic -pcre-jit (-selinux) -vim-syntax" NGINX_MODULES_HTTP="access auth_basic autoindex browser charset empty_gif fastcgi geo gzip limit_req limit_zone map memcached proxy referer rewrite scgi split_clients ssi upstream_ip_hash userid uwsgi -addition -cache_purge -dav -degradation -fancyindex -flv -geoip -gzip_static -headers_more -image_filter -mp4 -passenger -perl -push -random_index -realip -secure_link -slowfs_cache -stub_status -sub -upload -upload_progress -xslt" NGINX_MODULES_MAIL="-imap -pop3 -smtp" 702 kB
karky7 ~ #


nginxを設定する、fastcgi_passでバックグラウンドのFPM-PHPへ転送する、その他のパラメータはFPM-PHPへ渡すパラメータなどの設定になる
karky7 ~ # cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.ORG
karky7 ~ # emacs /etc/nginx/nginx.conf
karky7 ~ # diff /etc/nginx/nginx.conf /etc/nginx/nginx.conf.ORG
49c49
<               listen *;
---
>               listen 127.0.0.1;
51,57d50
<
<               location ~* \.php$ {
<                        fastcgi_pass 127.0.0.1:8989;
<                        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
<                        fastcgi_param PATH_INFO $fastcgi_script_name;
<                        include fastcgi_params;
<               }
karky7 ~ #


nginxを起動する、ポート80で動作していることを確認
karky7 ~ # /etc/init.d/nginx start
 * Checking nginx' configuration ...               [ ok ]
 * Starting nginx ...                              [ ok ]
karky7 ~ #
karky7 ~ # netstat -ln | grep 80
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN
karky7 ~ #


FPM-PHPが動作するか確認する

phpinfo()をDocumentRootへ配置、ブラウザからアクセスしてみる
karky7 ~ # echo '<?php phpinfo() ?>' > /var/www/localhost/htdocs/fpm-php.php
karky7 ~ #


「Server API」「FPM/FastCGI」になってるね



今度は動作検証とかApacheとどのくらい違うのか調べてみたい、Djangoもこれでイケるらしいのでもうちょっと調べてみるとする
まぁ、最後はYesodやりたいのだが...

2012年12月16日日曜日

Solaris11 Zoneマイグレーション

Solaris11からSolaros11.1へZoneを移設する

Solaris11.1がリリースされたついでにゾーンを新しい環境に移設したときの作業メモ、やりたいことは

  • 旧ホストghost1(Solaris11)で稼働中のゾーンzone1を、新ホストghost2(Solaris11.1)へ移設する

と言うことで実際にやってみる

Solaris11上のzone1をdetachする

旧サーバーにあるzone1ゾーンを取り外す、その際に以下の作業を行う
  • zone1(ゾーン)の停止
  • zone1のゾーン設定を保存
  • zone1をdetach
  • zone1のzfs領域のsnapshotをとる
  • snapshotからzfsのイメージを取得する
  • 取得したzfsイメージと、ゾーンの設定ファイルを新サーバーghost2へ転送する

zone1(ゾーン)の停止

ゾーンを確認し、zone1を停止する
ghost1 ~ # zoneadm list -vc
  ID NAME             STATUS     PATH                           BRAND    IP
   0 global           running    /                              solaris  shared
   3 zone1   running    /rpool/zones/zone1    solaris  shared
ghost1 ~ # zoneadm -z zone1 halt
ghost1 ~ #
ghost1 ~ #
ghost1 ~ # zoneadm list -vc
  ID NAME             STATUS     PATH                           BRAND    IP
   0 global           running    /                              solaris  shared
   - zone1   installed  /rpool/zones/zone1    solaris  shared
ghost1 ~ #

zone1のゾーン設定を保存

zonecfgのexportでファイルでzoneの設定を保存し場合によっては新サーバーの設定で修正を加える
ghost1 ~ # zonecfg -z zone1 export > zone1.cfg
ghost1 ~ # cat zone1.cfg
create -b
set zonepath=/rpool/zones/zone1
set brand=solaris
set autoboot=false
set ip-type=shared
add net
set address=192.168.254.123/24
set configure-allowed-address=true
set physical=net0
end
ghost1 ~ #

zone1をdetach

detachする、これでゾーンが切り離される、zone1のSTATUSはconfigureになる
ghost1 ~ # zoneadm -z zone1 detach
ghost1 ~ # zoneadm list -vc
  ID NAME             STATUS     PATH                           BRAND    IP
   0 global           running    /                              solaris  shared
   - zone1   configured /rpool/zones/zone1    solaris  shared
ghost1 ~ #

zone1のzfs領域のsnapshotをとる

これからzone1のディスクデータをイメージとして取得する
ghost1 ~ # zfs list | grep iichiko
rpool/zones/zone1                              38.4M  22.1G  35.5K  /rpool/zones/zone1
rpool/zones/zone1/rpool                        38.4M  22.1G    31K  /rpool
rpool/zones/zone1/rpool/ROOT                   38.3M  22.1G    31K  legacy
rpool/zones/zone1/rpool/ROOT/solaris-0         38.3M  22.1G   430M  /
rpool/zones/zone1/rpool/ROOT/solaris-0/var      420K  22.1G  24.6M  /var
rpool/zones/zone1/rpool/export                 71.5K  22.1G    32K  /export
rpool/zones/zone1/rpool/export/home            53.5K 
22.1G    32K  /export/home
rpool/zones/zone1/rpool/export/home/cuomo      32.5K  22.1G  32.5K  /export/home/cuomo
ghost1 ~ #
ghost1 ~ # zfs snapshot -r rpool/zones/zone1@25do

スナップショットの確認
ghost1 ~ # zfs list -t snapshot | grep 25do
rpool/zones/zone1@25do                                               0      -  35.5K  -
rpool/zones/zone1/rpool@25do                                         0      -    31K  -
rpool/zones/zone1/rpool/ROOT@25do                                    0      -    31K  -
rpool/zones/zone1/rpool/ROOT/solaris-0@25do                          0      -   430M  -
rpool/zones/zone1/rpool/ROOT/solaris-0/var@25do                      0      -  24.6M  -
rpool/zones/zone1/rpool/export@25do                                  0      -    32K  -
rpool/zones/zone1/rpool/export/home@25do                             0      -    32K  -
rpool/zones/zone1/rpool/export/home/cuomo@25do                       0      -  32.5K  -
ghost1 ~ #

snapshotからzfsのイメージを取得する

先ほど取得したスナップショットからzfsイメージを取得する
ghost1 ~ # zfs send -rc rpool/zones/zone1@25do | gzip > zone1.zfs.img.gz

取得したzfsイメージと、ゾーンの設定ファイルを新サーバーghost2へ転送する

以下の2ファイルをghost2サーバー(Solaris11.1)へ転送する、これは適当な方法でやってください
ghost1 ~ # ls -l | grep zone1
-rw-r--r-- 1 root root       203 2012-10-27 16:02 zone1.cfg
-rw-r--r-- 1 root root 235515745 2012-10-27 16:16 zone1.zfs.img.gz
ghost1 ~ #

ghost1サーバーでやることはおしまい、続いてghost2サーバーで作業をする

Solaris11.1上のzone1をattachする

ここからの作業はghost2(新サーバーSolaris11.1)で行う、zone1を起動するまでの作業は以下の順で行う
  • zone1のゾーン設定をファイルから作成する
  • zone1をattachする
  • zone1の起動

zone1のゾーン設定をファイルから作成する

zonecfgで設定ファイルを読み込ませゾーン設定を作成する、設定を修正する必要がある場合はここで修正する

ゾーンの確認、ない
ghost2 ~ # zoneadm list -vc
  ID NAME             STATUS     PATH                           BRAND    IP
   0 global           running    /                              solaris  shared
ghost2 ~ #

zone1の設定の読み込みと、ゾーンパスの作成
ghost2 ~ # zonecfg -z zone1 -f zone1.cfg
ghost2 ~ # zonecfg -z zone1 create -a /rpool/zone1
Zone zone1 already exists; create anyway (y/[n])? y
invalid path to detached zone
ghost2 ~ #

ゾーンの確認、configureになっている
ghost2 ~ # zoneadm list -vc
  ID NAME             STATUS     PATH                           BRAND    IP
   0 global           running    /                              solaris  shared
   - zone1   configured /rpool/zones/zone1    solaris  shared
ghost2 ~ #

zone1をattachする

zone1へアタッチする、同時にzone1をアップデートする
ghost2 ~ # zoneadm -z zone1 attach -u -a /root/zone1.zfs.img.gz
The following ZFS file system(s) have been created:
    rpool/zones
    rpool/zones/zone1
Warning: The -a and -d options to the attach subcommand may be removed in a
future release of Solaris.  Use of the install subcommand is recommended.
Progress being logged to /var/log/zones/zoneadm.20121027T073929Z.zone1.attach
    Installing: This may take several minutes...
      Zone BE root dataset: rpool/zones/zone1/rpool/ROOT/solaris-0
                     Cache: Using /var/pkg/publisher.
Updating image format
イメージ形式はすでに最新です。
  Updating non-global zone: Linking to image /.
処理中 linked: 1/1 done
  Updating non-global zone: Syncing packages (pass 1 of 2).
            削除するパッケージ:   1
インストールするパッケージ:  24
            更新するパッケージ: 165
         変更するメディエータ:   1
               変更するサービス:   5

ダウンロード                 パッケージ  ファイル  転送 (MB)  速度
完了                               190/190   14614/14614  219.2/219.2  1.4M/s

フェーズ                                  項目
古いアクションを削除しています   8129/8129
新しいアクションをインストールしています 10875/10875
変更されたアクションを更新しています   8829/8829
パッケージ状態データベースを更新しています      完了
パッケージキャッシュを更新しています     166/166
イメージ状態を更新しています      完了
スピード検索データベースを作成しています      完了
  Updating non-global zone: Syncing packages (pass 2 of 2).
このイメージは更新の必要はありません。

  Updating non-global zone: Zone updated.
                    Result: Attach Succeeded.
Log saved in non-global zone as /rpool/zones/zone1/root/var/log/zones/zoneadm.20121027T073929Z.zone1.attach
ghost2 ~ #

ゾーンの確認、zone1はinstalledです
ghost2 ~ # zoneadm list -vc
  ID NAME             STATUS     PATH                           BRAND    IP
   0 global           running    /                              solaris  shared
   - zone1   installed  /rpool/zones/zone1    solaris  shared
ghost2 ~ #

zone1の起動

めでたくzone1は起動、これで終了
ghost2 ~ # zoneadm -z zone1 boot
ghost2 ~ # zoneadm list -vc
  ID NAME             STATUS     PATH                           BRAND    IP
   0 global           running    /                              solaris  shared
   1 zone1   running    /rpool/zones/zone1    solaris  shared
ghost2 ~ #

まぁ、こんなに簡単にサーバーが移設出来てしまう
でももうチョットうまい具合に、簡単に移せたらいいかと思うが、Solaris先生にお願いしておこう....

Solaris11でzoneを立てるまで

Solaris11でZoneを立てるまでの19のTips


Solaris11のインストール

これはOracle Solaris11のダウンロードサイトからダウンロードしてください
以下の作業はVMware PlayerへインストールしたSolaris11へ行いました

ネットワーク設定 固定IP

Solaris11からはネットワーク設定を ネットワーク構成プロファイル(NCP)を使って設定するようになっているのでこれを固定IP用に設定する
インストールしたてはAutomatic NCPになっているのでDefaultFixed NCPに切り替える
ちなみに、Automatic NCPの場合は、「netcfg」や「netadm」で設定し、DefaultFixed NCPの場合は、「dladm」や「ipadm」あたりで設定する

Tip1 DefaultFixed NCPへ切り替える

root@sol11:~# netadm enable -p ncp DefaultFixed
Enabling ncp 'DefaultFixed'

Tip2 net0デバイスを有効化する

root@sol11:~# ipadm create-ip net0
root@sol11:~# ifconfig net0
net0: flags=1000842<BROADCAST,RUNNING,MULTICAST,IPv4> mtu 1500 index 3
      inet 0.0.0.0 netmask 0
      ether x:x:xx:x:xx:xx
root@sol11:~#

Tip3 Network Auto-Magic(NWAM)が停止していることを確認する

root@sol11:~# svcs -a | grep nwam
disabled       22:31:24 svc:/network/physical:nwam
root@sol11:~#

Tip4 dladmでDEVICEとLINKの確認をする

root@sol11:~# dladm show-phys
LINK        MEDIA         STATE   SPEED  DUPLEX    DEVICE
net0        Ethernet      up      1000   full      e1000g0
root@sol11:~#

Tip5 固定IPを割り当てる

root@sol11:~# ipadm create-addr -T static -a 192.168.254.5/24 net0/IPv4
root@sol11:~# ifconfig net0
net0: flags=1000843<UP,BROADCAST,RUNNING,MULTICAST,IPv4> mtu 1500 index 3
      inet 192.168.254.5 netmask ffffff00 broadcast 192.168.254.255
      ether x:x:xx:x:xx:xx
root@sol11:~#

Tip6 ディフォルトGatewayの設定

root@sol11:~# echo '192.168.254.1' > /etc/defaultrouter

Tip7 リゾルバの設定

root@sol11:~# svccfg -s name-service/switch setprop config/host = 'astring: "files dns"'
root@sol11:~# svcadm refresh name-service/switch
root@sol11:~# svccfg -s network/dns/client setprop config/nameserver = net_address: "(8.8.8.8 8.8.4.4)"
root@sol11:~# svcadm refresh dns/client

Tip8 ホスト名の変更、まず確認

root@sol11:~# svccfg -s svc:/system/identity:node listprop config
config           application       
config/nodename astring     sol11
config/loopback astring     sol11
root@sol11:~#

Tip9 ホスト名をghost1へ変更

root@sol11:~# svccfg -s svc:/system/identity:node setprop config/nodename=ghost1
root@sol11:~# svcadm refresh svc:/system/identity:node

Tip10 ネットワークの起動とエラーの確認、ここらでrebootした方がよろしいかと...

root@sol11:~# svcadm enable svc:/network/physical:default
root@sol11:~# svcs -xv

Tip11 Solaris Zoneでサーバーを立てる

もっとも基本的な簡単なZoneを立ててみる

現状の確認Zoneはなし、globalって実機のこと、ghost1です
root@sol11:~# zoneadm list -vc
  ID NAME         STATUS     PATH    BRAND    IP   
   0 global       running    /       solaris  shared
root@sol11:~#

Tip12 Zoneの設定を作成する

こんな感じで設定を作っておく、IPタイプはexclusiveが推奨ですが、今回はsharedで作成しておく
root@sol11:~# zonecfg -z zone1
zone1: No such zone configured
Use 'create' to begin configuring a new zone.
zonecfg:zone1> create -b
zonecfg:zone1> set zonepath=/zones/zone1
zonecfg:zone1> set autoboot=true
zonecfg:zone1> set ip-type=shared
zonecfg:zone1> add net
zonecfg:zone1:net> set address=192.168.254.123/24
zonecfg:zone1:net> set defrouter=192.168.254.1
zonecfg:zone1:net> set physical=net0
zonecfg:zone1:net> end
zonecfg:zone1> verify
zonecfg:zone1> commit
zonecfg:zone1> exit
root@sol11:~#

Tip13 Zoneの設定をファイルとしてExport出来る

root@sol11:~# zonecfg -z zone1 export > zone1.cfg
root@sol11:~# cat zone1.cfg
create -b
set zonepath=/zones/zone1
set brand=solaris
set autoboot=true
set ip-type=shared
add net
set address=192.168.254.123/24
set configure-allowed-address=true
set physical=net0
set defrouter=192.168.254.1
end
root@sol11:~#

Tip14 Zoneを確認する

zone1がconfigureである
root@sol11:~# zoneadm list -vc
  ID NAME       STATUS       PATH            BRAND    IP   
   0 global     running      /               solaris  shared
   - zone1      configured   /zones/zone1    solaris  shared
root@sol11:~#

Tip15 Zoneをインストールして使えるようにする

root@sol11:~# zoneadm -z zone1 install
A ZFS file system has been created for this zone.
Progress being logged to /var/log/zones/zoneadm.20121024T144800Z.zone1.install
       Image: Preparing at /zones/zone1/root.
...
...

インストールが完了するとSTATUSがinstalledに変わっている
root@sol11:~# zoneadm list -vc
  ID NAME        STATUS     PATH           BRAND    IP   
   0 global      running    /              solaris  shared
   - zone1       installed  /zones/zone1   solaris  shared
root@sol11:~#

Tip16 zone1をブートする

root@sol11:~# zoneadm -z zone1 boot

Tip17 最初だけzlogin -C でログインする

Zoneの設定をする
root@sol11:~# zlogin -C zone1
[Connected to zone 'zone1' console]

Zoneの設定は以下の画面のとおり












Tip18 ウザいメッセージを止める


ちなみに以下のメッセージターミナルに突然出てきてウザい場合は、/etc/hostsファイルに自分のホスト名を追加すると止まる
Oct 25 00:16:12 zone1 sendmail[5944]: unable to qualify my own domain name (zone1) -- using short name

/etc/hostsを修正
root@zone1:~# cat /etc/hosts
#
# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
# Use is subject to license terms.
#
# Internet host table
#
::1 zone1 localhost
127.0.0.1 zone1 zone1 localhost loghost
                ^^^^^ <- ここ追加

Tip19 zone1にログインする

root@ghost1:~# zlogin zone1
[Connected to zone 'zone1' pts/2]
Oracle Corporation SunOS 5.11     11.0 November 2011
root@zone1:~#

ここまで来たら設定完了、リゾルバとかの設定も今までと同じです、こんなに簡単にサーバーが作れちゃう
これだけ知ってるだけで、結構サーバーたてられて重宝します、このZoneの隔離性を体感してしまったら、もう止められません

Bootロゴをどうしても増やしてみた

BootLogoを増やす

【注意】
  実際のカーネルをビルド、インストールしますので、自己責任の上でお試しください
  VMでやった方がいいかもしれません

インストール環境

OS:    Gentoo Linux x86_64 AMG仕様
カーネル: Linux karky7 3.3.4-gentoo #3 SMP

Gentoo Linux以外のやり方はそれぞれのディストリビューションの方法でやって

カーネルのインストールと設定

カーネルをインストールする
karky7 ~ # emerge gentoo-sources

カーネルを設定する、主にFrame Bufferとロゴの出力するオプション(CONFIG_LOGO)をセット、ロゴが出るよぉ
karky7 ~ # cd /usr/src/linux
karky7 ~ # make menuconfig
...
...

Device Drivers  --->
    Graphics support  --->
        Console display driver support  --->
            [*] VGA text console
            [ ]   Enable Scrollback Buffer in System RAM
            <*> Framebuffer Console support
            [*] Select compiled-in fonts
            [*]   VGA 8x8 font
            -*-   VGA 8x16 font
...
...
        --- Bootup logo
        [ ]   Standard black and white Linux logo
        [ ]   Standard 16-color Linux logo
        [*]   Standard 224-color Linux logo


ソースコードを修正する

num_online_cpus()と言う関数がコア数を返してくるので、そこを表示したいペンギンの数へ修正する、ちなみに12個に設定
画面の横幅以上のペンギンを表示できないので、大きい数値を指定しても無駄です 笑
 ※ 実際はnum_online_cpus()はハミングウエイトを返すらしいのですがとりあえずコア数ということで...

diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 7ce6640..cdc992d 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -659,8 +659,8 @@ int fb_show_logo(struct fb_info *info, int rotate)
 {
        int y;

-       y = fb_show_logo_line(info, rotate, fb_logo.logo, 0,
-                             num_online_cpus());
+       y = fb_show_logo_line(info, rotate, fb_logo.logo, 0,
+                             12);
        y = fb_show_extra_logos(info, y, rotate);

        return y;


ビルドする

うまい具合に通ればOK #A君おめでとう...

karky7 linux # make
...
karky7 linux # make modules_install
  DEPMOD  3.3.4-gentoo+
karky7 linux # make install
sh /usr/src/linux-3.3.4-gentoo/arch/x86/boot/install.sh 3.3.4-gentoo+ arch/x86/boot/bzImage \
        System.map "/boot"
karky7 linux #

grubを設定する

grun.confを修正して、今できたへたれカーネルで起動できるようにする、もしペンギンが出ない場合、
bootオプションにvga=0x???のモードをしてすると出る場合があります、適当ですいません
default 3
timeout 30
splashimage=(hd0,4)/boot/grub/splash.xpm.gz

title Gentoo Linux 2.6.38-gentoo-r6
root (hd0,4)
kernel /boot/kernel-genkernel-x86_64-2.6.38-gentoo-r6 root=/dev/ram0 real_root=/dev/sda5 rootfstype=ext4
initrd /boot/initramfs-genkernel-x86_64-2.6.38-gentoo-r6

...
...
...

title Gentoo Linux-3.3.4-gentoo
root (hd0,4)
kernel /boot/vmlinuz-3.3.4-gentoo root=/dev/sda5

#
# これ追加
#
title Gentoo Linux-3.3.4-gentoo+
root (hd0,4)
kernel /boot/vmlinuz-3.3.4-gentoo+ root=/dev/sda5

...
...
...

# vim:ft=conf:

新しいカーネルでリブートする

karky7 ~ # reboot

先ほど作った、へたれカーネルで起動する




すると......おおおーーーーー!ペ、ペ、ペ、ペンギンが!12こもぉー...!




あまり役に立たないがチョット誰かを驚かせるにはいいかも