2014年12月31日水曜日

Yesod AuthのHashDB認証をやってみた

YesodのHashDBプラグインを利用した認証処理をやってみた

いま、最も熱いWeb FrameworkのYesod...って言いたいけど、最近、西のほうのPython遣いたちに追いやられている感はあるものの、でもやっぱYesodは最高ということで、

Yesodの認証処理を調べていて分かったことを忘れないうちにまとめてみました



Yesodの認証処理


Yesodの認証処理には複数のプラグインがありましてyesod-authというパッケージにまとめられています、主なプラグインは

  • OpenID認証
    • 試していません Orz...
     
  • BrowserID認証
    • 試していません Orz...
     
  • email認証
    • メールアドレスでアカウント発行、ログインまでを実装してあるプラグイン、アカウント新規発行時は確認メールを送信するため、サーバーでpostfixなんかのMTAを動かさなければならないのでチョット面倒、外部のメールサーバーにも出来る
     
  • Hash認証
    • 通常のアカウントとパスワードによる認証機構、仕組みを理解するのに簡単なので今回はこちらでお勉強 と言う感じで外部の認証機構をそのまま利用できる今時のプラグインが実装されている。 
 このうちHash認証でサンプルを構築してみました。

認証のサンプルを作成


とりあえずScaffoldサイトを構築する、MySQLを利用するのでその辺も起動しておく


Scaffoldの作成

cuomo@karky7 ~/Code $ 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: YesodAuthSample
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
    pf     = postgresql + Fay (experimental)
    mongo  = mongodb
    mysql  = MySQL
    simple = no database, no auth
    url    = Let me specify URL containing a site (advanced)

So, what'll it be? mysql
That's it! I'm creating your files now...
...
...

HashDB認証を構築


まず必要なパッケージをインストール
karky7 ~ # emerge -pv dev-haskell/yesod-auth-hashdb

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

Calculating dependencies... done!
[ebuild   R   ~] dev-haskell/yesod-auth-hashdb-1.4.1.1:0/1.4.1.1::karky7  USE="doc hscolour profile {-test}" 0 KiB

Total: 1 packages (1 reinstalls), Size of downloads: 0 KiB

 * IMPORTANT: 27 news items need reading for repository 'gentoo'.
 * Use eselect news to read news items.

karky7 ~ #
上のパッケージはgentoo-haskellへmergeしていただいたのでそちらでもインストール出きるはずです

データベースへの接続設定をする


Databaseへ接続するためsettings.ymlを修正
cuomo@karky7 ~/Code $ cd YesodAuthSample
~/Code/YesodAuthSample $ git diff
diff --git a/config/settings.yml b/config/settings.yml
index 4145c02..62a7dd4 100644
--- a/config/settings.yml
+++ b/config/settings.yml
@@ -16,9 +16,9 @@ ip-from-header: "_env:IP_FROM_HEADER:false"
 
 database:
   user:     "_env:MYSQL_USER:YesodAuthSample"
-  password: "_env:MYSQL_PASSWORD:YesodAuthSample"
+  password: "_env:MYSQL_PASSWORD:abc12345"
   host:     "_env:MYSQL_HOST:localhost"
-  port:     "_env:MYSQL_PORT:5432"
+  port:     "_env:MYSQL_PORT:3306"
   database: "_env:MYSQL_DATABASE:YesodAuthSample"
   poolsize: "_env:MYSQL_POOLSIZE:10"

~/Code/YesodAuthSample $ 

modelの作成


ログインアカウントを管理するUser型を作成、他のモデルは削除しても構いません
User
    email Text
    password Text
    UniqueUser email
    deriving Typeable

 -- By default this file is used in Model.hs (which is imported by Foundation.hs)

ルーティングを若干修正


HomeRのPOSTを利用しないので削除

/static StaticR Static appStatic
/auth   AuthR   Auth   getAuth

/favicon.ico FaviconR GET
/robots.txt RobotsR GET

/ HomeR GET

YesodAuthインスタンスを修正


ディフォルトだとBrowserIDの認証設定になっているので、ここをHashDBプラグインへ修正する、User型をHashDBUserクラスのインスタンスへすることも忘れずに。renderAuthMessageはログイン後に出力されるメッセージをカスタマイズするためにloginMessage関数へ差し替えています。詳しくはYesod.Auth.Messageモジュールを参照してみてください(japaneseMessageとかもあるよ)

instance YesodAuth App where
    type AuthId App = UserId

    -- ログイン後のリダイレクト先
    loginDest _ = HomeR
    -- ログアウト後のリダイレクト先
    logoutDest _ = HomeR
    -- Override the above two destinations when a Referer: header is present
    redirectToReferer _ = True

    -- UserIdを取得するための関数を設定、maybeAuthId系の関数が利用可能になる
    getAuthId creds = getAuthIdHashDB AuthR (Just . UniqueUser) creds

    -- プラグインをauthHashDBへ修正
    authPlugins _ = [authHashDB (Just . UniqueUser)]

    -- ログイン後のメッセージをディフォルトから修正
    renderAuthMessage _ _ = loginMessage

    -- authManagerはそのまま
    authHttpManager = getHttpManager

-- ログイン後に出力されるメッセージ
loginMessage :: AuthMessage -> Text
loginMessage _ = "乱入ではなくログインしました"

-- Userモデルを認証用としSha1のパスワードで認証するように HashDBUserのインスタンスに設定
instance HashDBUser User where
  userPasswordHash = Just . userPassword
  setPasswordHash h u = u { userPassword = h }

Home.hsを修正


ログイン、ログアウト後のリダイレクト先を作成、POSTは使わないので削除

module Handler.Home where

import Import

-- This is a handler function for the GET request method on the HomeR
-- resource pattern. All of your resource patterns are defined in
-- config/routes
--
-- The majority of the code you will write in Yesod lives in these handler
-- functions. You can spread them across multiple files if you are so
-- inclined, or create a single monolithic file.

getHomeR :: Handler Html
getHomeR = do
  maid <- maybeAuthId
  let handlerName = "getHomeR" :: Text
  defaultLayout $ do
    setTitle "HashDB認証サンプル"
    $(widgetFile "homepage")

テンプレート類の修正


色々削除してしまったので、不要な展開変数やタグを削除

homepage.hamlet

<h2>ログインサンプル
$maybe uid <- maid
    <p>#{show uid}
        <a href=@{AuthR LogoutR}>ログアウト
$nothing
    <p>
        <a href=@{AuthR LoginR}>ログイン画面へ
homepage.julius
全て削除
 
homepage.lucius
h1 {
    text-align: center
}
h2 {
    color: #990
}

cabalファイルに依存パッケージを追加


YesodAuthSample.cabalファイルを修正

~/Code/YesodAuthSample $ git diff YesodAuthSample.cabal
diff --git a/YesodAuthSample.cabal b/YesodAuthSample.cabal
index 0bc29ae..f196287 100644
--- a/YesodAuthSample.cabal
+++ b/YesodAuthSample.cabal
@@ -79,6 +79,7 @@ library
                  , containers
                  , vector
                  , time
+                 , yesod-auth-hashdb
 
 executable         YesodAuthSample
     if flag(library-only)
~/Code/YesodAuthSample $ 

スキーマを作成


yesod develを実行すればマイグレーションして自動でスキーマを作成してくれる

cuomo@karky7 ~/Code $ cd YesodAuthSample
cuomo@karky7 ~/Code/YesodAuthSample $ mysqladmin -u root create YesodAuthSample
cuomo@karky7 ~/Code/YesodAuthSample $ yesod devel
Yesod devel server. Press ENTER to quit
Warning: The package list for \'hackage.haskell.org\' does not exist. Run \'cabal
update\' to download it.
Resolving dependencies...
Configuring YesodAuthSample-0.0.0...
Rebuilding application... (using cabal)
Starting development server...
Starting devel application
Migrating: CREATe TABLE `user`(`id` BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,`email` TEXT CHARACTER SET utf8 NOT NULL,`password` TEXT CHARACTER SET utf8 NOT NULL)
30/Dec/2014:12:00:06 +0900 [Debug#SQL] \"CREATe TABLE `user`(`id` BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,`email` TEXT CHARACTER SET utf8 NOT NULL,`password` TEXT CHARACTER SET utf8 NOT NULL)\" [] @(persistent-2.1.1:Database.Persist.Sql.Raw ./Database/Persist/Sql/Raw.hs:55:18)
Migrating: ALTER TABLE `user` ADD CONSTRAINT `unique_user` UNIQUE(`email`(200))
Devel application launched: http://localhost:3000
30/Dec/2014:12:00:06 +0900 [Debug#SQL] \"ALTER TABLE `user` ADD CONSTRAINT `unique_user` UNIQUE(`email`(200))\" [] @(persistent-2.1.1:Database.Persist.Sql.Raw ./Database/Persist/Sql/Raw.hs:55:18)
cuomo@karky7 ~/Code/YesodAuthSample $

ログインアカウントデータを挿入

sha1でhash化する

cuomo@karky7 ~/Code/YesodAuthSample $ mysql -u root YesodAuthSample
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 14
Server version: 5.6.21-log Source distribution
...
...
...
mysql> INSERT INTO user(email, password) VALUES('karky7@sample.jp', sha1('karky7'));
Query OK, 1 row affected (0.37 sec)

mysql> quit
Bye

動かしてみる

cuomo@karky7 ~/Code/YesodAuthSample $ yesod devel

初期画面

ログイン前はログイン画面へのリンクを表示する


ログイン画面

「http://localhost:3000/auth/login」というURLでログイン画面が出力される、先ほどINSERTした認証でログインを実行する


ログイン完了

見た目は悪いのですがログイン完了の画面、URLもHomeRへ戻り、getAuthIdで取得できた認証情報を表示している。User情報のIDを表示しているだけですが。


こんな感じで認証ができる、ログインフォームまで作ってくれるので楽です、細かい動作や出力の調整はクラスの関数をオリジナルのものへ修正すれば可能なので、基本的にディフォルトの動作は実装されています。

コードを書いているとほとんどの悪い箇所をコンパイラが拾ってくれるので凄く楽。Haskell+Yesodが今のところ、一番のお気に入りフレームワークかな。



2014年12月7日日曜日

PythonのGILについて簡単に調べてみました

PythonのGIL


Pythonで平行処理をやろうと思った時に、いろいろやり方があるのですがどの方法が一番効率的かどうか考えた時に、いつも
「GIL」様
が、お顔をお出しになって
「じゃぁ、どうやれって言うんだよ」
って感じになりますよね?

えっ?ならない...そうですか

世間ではあまりよく思われていない「GIL」だと思いますがでも私はPythonが好きなので頑張ってみました。 今回はサンプルコードとか作ってる時間がありませんでしたので、ほとんど説明だけですので、ごめんなさい。

GIL(Global Interpreter Lock)とは



全然違います、

Pythonインタープリターが内部で利用しているスレッドの同期プリミティブで、GILを取得できたスレッドがコードの実行を行うことができます、最初はスクリプトを実行したスレッドは1つ、mainスレッドだけなのでシングルスレッド動作させた場合はGILに対しての競合は起こらずスムーズに実行されます。

試してみる


以下のサンプルコードを実行した時間を計測してみる。シングルスレッド版は単純にcount関数を2回呼ぶだけの平凡なコード、2スレッド版はマルチコアなのでスレッドを2つ作成し平行に実行するように修正を加えたコード。
コードはCPUバンドなコードなので、I/Oの要素は含んでないことに注意。

def count(n):
    while n > 0:
        n -= 1

if __name__ == '__main__':
    count(100000000)
    count(100000000)
from threading import Thread

def count(n):
    while n > 0:
        n -= 1

if __name__ == '__main__':
    t1 = Thread(target=count, args=(100000000,))
    t1.start()
    t2 = Thread(target=count, args=(100000000,))
    t2.start()
    t1.join();
    t2.join();


* 実行結果

~/Code/lwl/Python/GIL $ time python sample1.py
18.181 secs
~/Code/lwl/Python/GIL $ time python sample2.py
30.090 secs
~/Code/lwl/Python/GIL $ 

Mac Book Air Core i5 1.6GHz 2Coreで実行しましたが、2スレッドの方が遅いではないですか。

どうなってるんだよ?!


私もGILを知るまで上のようなコードを書いていました、しっかり計測したことがなかったのですがこんな感じで遅くなっていたのでしょう、機械の無駄使いですね、すいませんでした。
同一プロセス内でスレッドを複数起動しても、GILの取得で内部競合を起こしてしまい遅くなってしまっている為です。

GILの取得方法


じゃぁ、GILがどういう風に取得されるか、これはそのスクリプトがCPUバンドなのかI/Oバンドなのかでちょっと違うようです。

* スクリプトがCPUバンドの場合

上のサンプルのようにCPU時間しか使わないようなプログラムの場合、一定期間にcheckが入ります、一定期間とはPythonインタープリターが内部で持っているticksという(単位時間ではない)カウンタを持っていてそのticksが100(適当...)を計測した際にGILの取得チェックが行われます。面白いのが、一定時間ではなく、一定のコードを実行したらticksが1カウントされるのです。さらに、その区間は割り込みさえ受け付けません。

poko-no-MacBook-Air:~ cuomo$ python
Python 2.7.8 (default, Oct  2 2014, 23:45:37)
[GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.51)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> nums = xrange(1000000000)
>>> -1 in nums
^C^C^C^C^C^CTraceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyboardInterrupt
>>>

Ctrl+Cを押してもticks区間の場合帰ってきません。なるほど


* スクリプトがI/Oバンドの場合

ブロッキングI/Oを多く発行するようなスクリプトの場合、I/O要求を出す前に、スレッドがGILをリリースしI/Oから戻った時にGILを取得するような動きをするので、最終的に、I/Oとticksのせめぎ合いのような感じになりますね、長いI/Oばかりの処理が多いとするといくらスレッドをI/O用に生成したところで戻って来るまで待つことになりますし、I/Oが早いとしてもCPUのticksで性能が出ないので、どちらにしても悪いような気がします

* あともう一つGILとシグナルについて

厄介な話として、シグナルがペンディングされた場合、シグナルハンドラーを処理できるスレッドがmainスレッドに限られてしまうこと。もしその時に複数のスレッドが実行されていた場合、それぞれのスレッドが1tick実行するたたびにcheckが実行され、そこでGILの取得と解放が検査されるようになってしまうこと、最終的にmainスレッドに制御が移るまでシグナルはペンディングされたままになってしまいます。 ようするに、シグナルが届いたからといって、優先的にmainスレッドにコンテキストスイッチしないということです。

まとめると

  • Pythonインタープリターはスレッドのスケジューラーを持っていない
  • GILを取得したスレッドに実行権限がある
  • CPUバンドの場合、一定期間のticks(コードの塊)でスレッドの実行がスイッチされる
  •  I/Oバンドの場合、I/Oの発行でGILのリリース、I/Oからの戻りでGILの取得が実行される
  • シグナルはmainスレッドしか実行できない
ちょっと簡単すぎますけどこんな感じのPythonだと思いますが、そもそも、同一プロセス(同一インタープリターといったほうがいいかな)内でThreadを生成しても性能がでないという結果に落ち着くと思いますが、皆さんは如何でしょうか?(笑)

でもmultiprocessingがあるじゃないですか


なので世のPythonistaの方達がmultiprocessingを使いなさいと教えてくれました。早い話が、forkを使った方法でGILの競合を無くしてしまえという方法です。

from multiprocessing import Process

def count(n):
    while n > 0:
        n -= 1

if __name__ == '__main__':
    p1 = Process(target=count, args=(100000000,))
    p2 = Process(target=count, args=(100000000,))
    p1.start()
    p2.start()
    p1.join()
    p2.join()


* 実行結果
~/Code/lwl/Python/GIL $ time python sample3.py
10.061 secs
~/Code/lwl/Python/GIL $ 

そこそこ性能が出てますね、1プロセス1スレッドにしてしまえばGILを取り放題ですね。 forkして、OSのスケジューラに任せた方が性能がでるってことです、スクリプトが遅い責任をカーネルのスケジューラのせいにできるのでなにかあった時に適当な言い訳を上司に言えますよ(笑)

複数プロセスにした場合、プロセス間でデータを共有するためにIPCを利用したりしなければならないので、ちょっとその辺りが面倒になりますが、ValueクラスとかArrayクラスなどを利用すれば共有メモリでデータの共有を簡単にしてくれるのでそんなに気にならないと感じます(自分は使ったことがありませんが...)。

デメリットとすればプロセステーブルを消費してしまうのと、プロセス生成のオーバーヘッド、メモリリソースの空間的な問題ですが、昨今のコンピュータなら気にすることないレベルですね。

いろいろ、グダグダ書いてしまいしたが、やり方を変えれば性能が出せることと、GILなんか怖くないよってはなし、しゃべりすぎました、間違ってたら指摘してください...

時間があったらもうちょっと突っ込んで調べます、お許しを...PHPやりたい


2014年11月25日火曜日

ラーメン伊駄天

静岡市にあるラーメン屋 伊駄天さんで食べました

せっかく静岡市にきましたので、旨いラーメンを食べようとしばらく探したところ、チョット良さげなお店を見つけました。

「てっぺん」というラーメンです




味は見ての通りあっさりです、麺がチョット緑色っぽかったのですが、味が分かりませんでした(お茶でも入ってんのか?..)、スープ、チャーシュウはおいしかったです。

このスープだったら、細麺にすれば良かったかな...

とりあえず、静岡市にいったらまた寄ろうと思います。



場所はこちら


2014年11月24日月曜日

OpenSolaris勉強会 静岡合宿に行ってきました - 2014年11月22日(土)

いつもお世話になっているOpenSolarisユーザーグループが企画する1泊2日の合宿が行われるため静岡まで行ってきました。
今回は、Solaris11.2で実装されたOpenStackと、以前からユーザー会で作成していたパッケージリポジトリの件の話し合いなどで集まりました。
OpenStackなんかまったくの素人で、触ったこともなかったので、この機会にどんなものなのかを知れればいいかなと思い、参加した次第であります。

OpenStackハンズオン



実は自分はOpenStackという言葉しか知らず、「AWSとかでゴリゴリ自動でサーバーとかが勝手に出来上がったりするやつ」程度の知識力で挑んできました。

今回のOpenSolaris勉強会OpenStackハンズオンでなんとかイけてるOpenStack野郎になるつもりでしたが結果は無惨なもので、インストール失敗という何とも情けない結果になりました。笑...
しかし、OpenStackのコンポーネントや、それぞれのコンポーネントが実装している機能などの概要が理解できただけでも良かったと思います。
Solaris11のOpenStackはSolaris11の機能に特化していてグローバルゾーンをまたいだSwitchを作成できるEVS(Elastic Virtual Switch)や、Unifiled Archiveなどのお話も聞けて内容はかなり勉強になりました。

まだまだOpenStackを理解するには時間がかかりそうですが(っていうかかかります)これからも追っかけていきたいと思います。

とくに有意義な情報がなくて申し訳ございません...


OpenSolarisユーザー会リポジトリがリリースされました


まずは、

「おめでとうございます」

前回の熱海合宿から2年ぐらい経ちましたでしょうか?
やっとOpenSolarisユーザー会のパッケージリポジトリがリリースされました。ぜひSolaris11.2を利用しているかた、これから利用していこうかなっていうユーザーのかた是非ご利用ください。これからモリモリパッケージが追加されていく事だとおもいます。 今後、自分もがんばってお手伝いさせて頂きますのでよろしくお願いします。

  • リポジトリ情報
    • http://pkg.opensolaris.gr.jp/solaris11/nightly/
* publisher追加方法
$ sudo pkg set-publisher -g http://pkg.opensolaris.gr.jp/solaris11/nightly/ jposug-nightly

懇親会

やっぱり、これがOpenSolarisユーザーグループには欠かせない行事ですね。
今回は「もとよし」さんという居酒屋で行いました。
中でも私が「これはっ!」と思ったのがこちら

桜海老の踊り食い



私も海の近くに住んでいるので、魚の生は結構食べるのですが、このエビは静岡のこの辺りでないとなかなか食べれないと思いました。
何しろまだ生きでいるエビを醤油で頂くという、贅沢なお刺身でした。


振り返って考えてみると、情報量が多すぎて自分が何を覚えてきたのか?とか、なんか新しい技術を習得したのか?言われれば、よく分からない状態で課題ばかりの合宿でした。まぁ朝方まで飲んだ事が原因かもしれませんが... 全ては自分の技術力のなさが原因なのですが...笑 んー、まだまだ足りないのですね。いろいろと...

この度は、OpenSolarisユーザーグループの皆さん、お疲れさまでした。


行った場所

* 居酒屋 もとよし

しかし、つまみは旨かった



2014年11月18日火曜日

支那そば福々亭でラーメン

支那そばの旨さを再認識してきました

食べる側から感じる、さっぱり系のラーメンの難しさは何といっても

「食った後の物足りなさ」

を感じるところではないでしょうか?

そうそう、例えて言うなら、具の無いポロイチを食った後の感じです! ... そ、そうですか違いますか...

でもね、その辺の難しさを克服しているさっぱりラーメンはやはり凄いと感じますよね。僕は支那そばの旨さを再確認してしまいました。

今日は 塩チャーシュー 850円 をいただきました、病んだ体にはこれが薬です...


文句なく旨いです、伊東に遊びに来たら是非どうぞ。



2014年11月17日月曜日

gentooをsystemd化する

最近、systemdが流行ってるのか


ここ最近、DVDが見たいがために(決してイヤらしいものではありません...)いろいろなディストリビューションのGUIな環境を試してみたものの全てダメで自分の技術力のなさに打ちひしがれていました。
しかし、どのディストリビューションもディフォルトでsystemd化されていて、

「色々な意見が見られますが、時代はsystemdへ行ってしまっているのかな?」

なんか感じてしまい、まぁ、cgroupとかgnome3なんか既にsystemdが必須と言われますし、LXCとか、dockerとか巷ではコンテナ仮想化とかやってないと、JKとかに人気ないとか、若手SEの糸に言われるので、gentooユーザーの私は

「是非、僕のgentooをsystemdにしたい」

と思いまして、面倒だったのですがやってみました。

systemdインストール開始


systemdが利用できるLinux kernelは2.6.39、gccも4.6以上を要求されるので先にupdateしておく
vkarimakubo ~ # emerge -pv gcc glibc

必要なもの

  • kernel 2.6.39以上
  • gcc 4.6以上
  • glibc 2.19以...曖昧
とにかく時間がかかる...
Linux vkarimakubo 2.6.36-gentoo-r8 #1 SMP Tue Jul 9 20:14:27 JST 2013 x86_64 Intel(R) Core(TM) i7-2620M CPU @ 2.70GHz GenuineIntel GNU/Linux
2.6.36ではダメダメです...
vkarimakubo ~ # emerge -pv gentoo-sources
sys-kernel/gentoo-sources-3.16.5:3.16.5 [2.6.36-r8:2.6.36-r8, 3.1.6:3.1.6] USE="-build -deblob -experimental -symlink" 78,854 kB
vkarimakubo ~ # emerge gentoo-sources

あとはカーネルを再度ビルドする、その時にカーネルの設定を一部しておく。

* systemd系オプション

このオプションを指定するとsystemd関連のカーネルオプションが有効になります...知りませんでしたw
Gentoo Linux  --->
     [*] Gentoo Linux support (NEW)
     [*]   Linux dynamic and persistent device naming (userspace devfs) support
         Support for init systems, system and service managers
             [*] OpenRC, runit and other script based systems and managers (NEW)
             [*] systemd

* 追加設定

cgroupの設定
General setup --->
    Control Group support
        [ ]   Example debug cgroup subsystem (NEW)
        [*]   Freezer cgroup subsystem
        [*]   Device controller for cgroups
        [*]   Cpuset support
        [*]   Include legacy /proc//cpuset file (NEW)
        [*]   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
        [ ]     HugeTLB Resource Controller for Control Groups (NEW)
        [ ]   Enable perf_event per-cpu per-container group (cgroup) monitoring (NEW)
        [*]   Group CPU scheduler  --->
        [*]   Block IO controller
        [ ]     Enable Block IO controller debugging (NEW)
    Namespaces support
        [*]   UTS namespace (NEW)
        [*]   IPC namespace (NEW)
        [*]   User namespace (NEW)
        [*]   PID Namespaces (NEW)
        -*-   Network namespace
* CONFIG_UEVENT_HELPER_PATHを空に設定

systemdパッケージをインストールするさイに以下のエラーが出る場合「path to uevent helper」を未設定にしておく
..

 * It's recommended to set an empty value to the following kernel config option:
 * CONFIG_UEVENT_HELPER_PATH="/sbin/udevadm"
なので
Device Drivers  --->
   Generic Driver Options  --->
     [*] Support for uevent helper (NEW)
       ()    path to uevent helper
これでカーネルをビルドし直しなおす。
vkarimakubo ~ # cd /usr/src/linux
vkarimakubo ~ # make -j6
vkarimakubo ~ # make_modules install
vkarimakubo ~ # make install

* grubの設定を忘れずに..

grub.confを書き換え、grub2もだいたい同じです
default 0
timeout 30
splashimage=(hd0,0)/boot/grub/splash.xpm.gz

title Gentoo Linux x86_64-2.6.36-gentoo-r8
root (hd0,0)
kernel /boot/kernel-genkernel-x86_64-2.6.36-gentoo-r8 root=/dev/ram0 real_root=/dev/sda1
initrd /boot/initramfs-genkernel-x86_64-2.6.36-gentoo-r8

title Gentoo Linux x86_64-3.16.5-gentoo-r8
root (hd0,0)
kernel /boot/vmlinuz-3.16.5-gentoo root=/dev/sda1

systemd化していく


make.confのUSEフラグへsystemdを追加
...
USE="mmx sse sse2 systemd -doc -X -qt -qt2 -qt3 -at4 -gtk -gtk2 -gtk3 -kde -gnome"
...
vkarimakubo ~ # emerge -pv systemd

 * IMPORTANT: config file '/etc/portage/repos.conf/gentoo.conf' needs updating.
 * See the CONFIGURATION FILES section of the emerge
 * man page to learn how to update config files.

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

Calculating dependencies... done!
[ebuild  N     ] dev-util/gperf-3.0.4  961 kB
[ebuild  N     ] sys-libs/libseccomp-2.1.1  USE="-static-libs" 111 kB
[ebuild     U  ] sys-devel/automake-wrapper-9 [7] 0 kB
[ebuild     U  ] sys-apps/kmod-18-r1 [13-r1] USE="tools zlib -debug -doc -lzma -python% -static-libs" PYTHON_TARGETS="python2_7%* python3_3%* (-python3_2) -python3_4%" 1,440 kB
[ebuild  NS    ] app-text/docbook-xml-dtd-4.4-r2:4.4 [4.3-r1:4.3] 94 kB
[ebuild  NS    ] app-text/docbook-xml-dtd-4.2-r2:4.2 [4.3-r1:4.3] 77 kB
[ebuild     U  ] sys-kernel/linux-headers-3.13 [2.6.39] 3,606 kB
[ebuild  N     ] dev-perl/XML-Parser-2.410.0-r2  233 kB
[ebuild  NS    ] sys-devel/automake-1.13.4:1.13 [1.11.1:1.11, 1.12.6:1.12] 1,416 kB
[ebuild  N     ] app-text/xmlto-0.0.25  USE="-latex" 114 kB
[ebuild     U  ] sys-apps/attr-2.4.47-r1 [2.4.46] USE="nls -static-libs" ABI_X86="(64%*) (-32) (-x32)" 336 kB
[ebuild  N     ] dev-util/intltool-0.50.2-r1  186 kB
[ebuild  N     ] sys-libs/libcap-2.22-r2  USE="pam" ABI_X86="(64) (-32) (-x32)" 59 kB
[ebuild  N     ] sys-apps/systemd-215-r3:0/2  USE="acl firmware-loader kmod pam seccomp -audit -cryptsetup -doc -elfutils -gcrypt -gudev -http -introspection (-kdbus) -lzma -policykit -python -qrcode (-selinux) (-ssl) {-test} -vanilla" ABI_X86="(64) (-32) (-x32)" PYTHON_SINGLE_TARGET="python2_7 (-python3_2) -python3_3 -python3_4" PYTHON_TARGETS="python2_7 python3_3 (-python3_2) -python3_4" 2,821 kB
[ebuild  N     ] sys-apps/gentoo-systemd-integration-4  52 kB
[ebuild  N     ] sys-apps/dbus-1.8.8  USE="systemd -X -debug -doc (-selinux) -static-libs {-test}" ABI_X86="(64) (-32) (-x32)" 1,822 kB
[ebuild     U  ] virtual/udev-215 [197-r3] USE="systemd%* (-gudev%) (-hwdb%) (-introspection%) (-keymap%) (-kmod%*) (-selinux%) (-static-libs%)" 0 kB
[ebuild  N     ] sys-apps/hwids-20141010  USE="net pci udev usb" 1,640 kB
[blocks B      ] sys-fs/udev ("sys-fs/udev" is blocking sys-apps/gentoo-systemd-integration-4, sys-apps/systemd-215-r3)
[blocks B      ] =sys-apps/systemd-208:0 required by (virtual/udev-215::gentoo, ebuild scheduled for merge)
    sys-apps/systemd:0= required by (sys-apps/dbus-1.8.8::gentoo, ebuild scheduled for merge)
    systemd
    >=sys-apps/systemd-207 required by (sys-apps/gentoo-systemd-integration-4::gentoo, ebuild scheduled for merge)

  (sys-apps/kmod-18-r1::gentoo, ebuild scheduled for merge) pulled in by
    sys-apps/kmod required by @selected
    sys-apps/kmod[tools] required by (virtual/modutils-0::gentoo, installed)
    >=sys-apps/kmod-15:0= required by (sys-apps/systemd-215-r3::gentoo, ebuild scheduled for merge)
    >=sys-apps/kmod-13 required by (sys-fs/udev-204::gentoo, installed)


For more information about Blocked Packages, please refer to the following
section of the Gentoo Linux x86 Handbook (architecture is irrelevant):

http://www.gentoo.org/doc/en/handbook/handbook-x86.xml?full=1#blocked

 * IMPORTANT: 17 news items need reading for repository 'gentoo'.
 * Use eselect news to read news items.

vkarimakubo ~ #

openrcとかudevまわりで、インストール順などで文句を言われるのでそれぞれで対応する、意外と焦るメッセージとか出してくるので何とか耐える 面倒なので一時的にudevなどを削除する、ここで再起動すると悲惨な事になるので注意。 面倒なのでこうしてます、起動しなくなる可能性がございますのでパッケージの削除は計画的に... (笑)
vkarimakubo ~ # emerge -C sys-fs/udev
 * This action can remove important packages! In order to be safer, use
 * `emerge -pv --depclean ` to check for reverse dependencies before
 * removing packages.


!!! 'sys-fs/udev' (virtual/dev-manager) is part of your system profile.
!!! Unmerging it may be damaging to your system.

>>> Waiting 10 seconds before starting...
>>> (Control-C to abort)...
Press Ctrl-C to Stop in: 10 9 8 7 6 5 4 3 2 1

 sys-fs/udev
    selected: 204
   protected: none
     omitted: none

All selected packages: sys-fs/udev-204

>>> 'Selected' packages are slated for removal.
>>> 'Protected' and 'omitted' packages will not be removed.

>>> Waiting 5 seconds before starting...
>>> (Control-C to abort)...
>>> Unmerging in: 5 4 3 2 1
>>> Unmerging (1 of 1) sys-fs/udev-204...
<<< !needed  sym /lib64/libkmod.so.2
<<< !needed  obj /lib64/libkmod.so.2.2.3

 * GNU info directory index is up-to-date.

 * IMPORTANT: 3 config files in '/etc' need updating.
 * See the CONFIGURATION FILES section of the emerge
 * man page to learn how to update config files.

 * IMPORTANT: 17 news items need reading for repository 'gentoo'.
 * Use eselect news to read news items.

vkarimakubo ~ #
* ちなみにその他一時削除したパッケージは... あぶない!
vkarimakubo ~ # emerge -C sys-apps/kmod virtual/modutils
これでsystemをビルドする
vkarimakubo ~ # emerge systemd

* grubの設定

再起動する前に、grub.confのカーネルパラメータを若干修正する、「init=/usr/lib/systemd/systemd」を追加
# This is a sample grub.conf for use with Genkernel, per the Gentoo handbook
# http://www.gentoo.org/doc/en/handbook/handbook-x86.xml?part=1&chap=10#doc_chap2
# If you are not using Genkernel and you need help creating this file, you
# should consult the handbook. Alternatively, consult the grub.conf.sample that
# is included with the Grub documentation.

default 0
timeout 30
splashimage=(hd0,0)/boot/grub/splash.xpm.gz

title Gentoo Linux x86_64-2.6.36-gentoo-r8
root (hd0,0)
kernel /boot/kernel-genkernel-x86_64-2.6.36-gentoo-r8 root=/dev/ram0 real_root=/dev/sda1
initrd /boot/initramfs-genkernel-x86_64-2.6.36-gentoo-r8

title Gentoo Linux x86_64-3.16.5-gentoo-r8
root (hd0,0)
kernel /boot/vmlinuz-3.16.5-gentoo root=/dev/sda1 init=/usr/lib/systemd/systemd
# vim:ft=conf:

iproute2をいれておく


ifconfigでもいいのですがipコマンドなどを後で利用するので入れておく
vkarimakubo ~ # emerge -pv sys-apps/iproute2

 * IMPORTANT: config file '/etc/portage/repos.conf/gentoo.conf' needs updating.
 * See the CONFIGURATION FILES section of the emerge
 * man page to learn how to update config files.

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

Calculating dependencies... done!
[ebuild  N     ] net-firewall/iptables-1.4.21-r1  USE="ipv6 -netlink -static-libs" 535 kB
[ebuild  N     ] sys-apps/iproute2-3.8.0  USE="berkdb iptables ipv6 -atm -minimal" 399 kB

Total: 2 packages (2 new), Size of downloads: 933 kB

 * IMPORTANT: 20 news items need reading for repository 'gentoo'.
 * Use eselect news to read news items.

vkarimakubo ~ # emerge sys-apps/iproute2
rebootする
vkarimakubo ~ # reboot

ネットワークを設定する


とりあえず手動で設定しておく
vkarimakubo ~ # ip link set dev enp2s1 up
vkarimakubo ~ # ip addr add 192.168.254.77/24 broadcast 192.168.254.255 dev enp2s1
vkarimakubo ~ # ip route add default via 192.168.254.1
とりあえず必要なものをsystemd対応にしておく
vkarimakubo ~ # emerge net-misc/openssh
vkarimakubo ~ # emerge app-admin/syslog-ng
vkarimakubo ~ # systemctl enable sshd
Created symlink from /etc/systemd/system/multi-user.target.wants/sshd.service to /usr/lib64/systemd/system/sshd.service.
vkarimakubo ~ # systemctl start sshd
vkarimakubo ~ #  systemctl enable syslog-ng
Created symlink from /etc/systemd/system/syslog.service to /usr/lib64/systemd/system/syslog-ng.service.
Created symlink from /etc/systemd/system/multi-user.target.wants/syslog-ng.service to /usr/lib64/systemd/system/syslog-ng.service.
vkarimakubo ~ #  systemctl start syslog-ng

起動時にネットワークIPが有効になるように設定


systemdのUNITを作成
* network@.serviceファイル
[Unit]
Description=Network connect (%i)
Wants=Network.target
Before=Network.target
BindsTo=sys-subsystem-net-devices-%i.device
After=sys-subsystem-net-devices-%i.device

[Service]
Type=oneshot
RemainAfterExit=yes
EnvironmentFile=/etc/conf.d/network@%i

ExecStart=/bin/ip link set dev %i up
ExecStart=/bin/ip addr add ${address}/${netmask} broadcast ${broadcast} dev %i
ExecStart=/bin/sh -c 'test -n ${gateway} && /bin/ip route add default via ${gateway}'

ExecStop=/bin/ip addr flush dev %i
ExecStop=/bin/ip link set dev %i down

[Install]
WantedBy=multi-user.target

* network@enp2s1ファイル 「enp2s1」の部分は実際のデバイス名にしてください
address=192.168.254.77
netmask=24
broadcast=192.168.254.255
gateway=192.168.254.1

* IP有効化
vkarimakubo ~ # systemctl enable network@enp2s1
vkarimakubo ~ # systemctl start network@enp2s1

その他の設定

* ロケールとキーボード設定
vkarimakubo ~ # localectl set-locale LANG=ja_JP.utf-8
vkarimakubo ~ # localectl set-keymap jp106
vkarimakubo ~ # localectl
   System Locale: LANG=ja_JP.utf-8
       VC Keymap: jp106
      X11 Layout: jp
       X11 Model: jp106
     X11 Options: terminate:ctrl_alt_bksp
vkarimakubo ~ # 
* ホスト名設定
vkarimakubo ~ # hostnamectl set-hostname vkari
とりあえずここでreboot
vkarimakubo ~ # reboot
こんな感じでsystemdへ移行できます、結構面倒くさい、なので素直にRedhatとかCentOSとかを使いましょう。笑...

2014年11月11日火曜日

熱海のAtamixなんてあったなんて、アンビリーバボー

電車の乗り換えが悪かったので熱海で降りてみた


夜業明けで午前中に仕事を終え早上がりで帰宅していたのですが、熱海で電車の乗り継ぎが悪く、ベンチに座ってgentooもいけてないので、マックでも行ってやるかと駅を降りてみたのですが、目の前になんと「Atamix」 なんて建物が目に入ってしまったので、無意識にはいってしまいました。


 おしゃれでしょ?いい感じです、まぁ入ると外側とはまるで違ったちょっとレトロな感じの建物ではないですか! 

お土産から、衣料品まで取り揃えている、大型スーパーバリではないですか。
かまぼことか ひものとかケーキとか、第一不動産とか。。。不動産まで取り揃えてんのかっ!


非常に賑やかでした、さらに奥に進みます.... そこにはなんと!

サテンです、そう喫茶店です、「コーヒーサロンアート」ってどういうこと?、ヤバい!ここならgentooできるじゃないですか!

「だめよぉー、ダメダメ」


 やりすぎました、すいません、Orz...

話戻します、ぜひWifiを完備していただきたい!、Wifiがあれば熱いじゃないですか! 
今日は時間の都合上、コーヒーは飲めませんでしたが、次回はコーヒーをいただきたいと思います。

さらに地下に潜ります...

まじかっ! のみ屋さんがあるじゃないですか!


ランチは500円で食べれそうです。いいですねぇ、
中はお座敷もあり、いい感じの飲み屋さんです、今から飲みたい気もしますが、電車に乗り遅れてしまいそうなので必死に我慢しました。

お隣は、つけ麺屋さんです


「温泉つけ麺」って温泉で麺を茹でてるのか?! 気になります、食べたかったのですが電車に乗り遅れると困るので今日はあきらめました。次回はぜひ食べてみたいと思います。

その他にも、お刺身を食べれるおみせとか、その他2店ありましたが、興奮しすぎて写真を撮り忘れました。

もう、大繁盛!!!

そして最後


靴屋さん


「クック」さん、おしゃれな名前じゃないですか!一発で靴屋ってわかるよね!

ちょっと覗いたつもりが、かなりハマってしまった、気づいたらgentooしてないし

熱海駅前、アタミックス。。。や・ば・イ ぜ!

お店紹介

  • 和風レストラン たしろ
  • お好み定食 まるに食堂
  • 500円定食の店 熱海まぐろや
  • 地魚料理の店 さくら
  • 温泉つけ麺 維新 熱海本店

熱海に降りたときは、ぜひどうぞ


2014年11月4日火曜日

ピカチュウとアル中

ピカチュウなんか知るわけがない

ピカチュウとは黄色いかわいらしい動物らしく



調べてみたら、かわいいじゃないか

で、アル中


これはアルコール中毒の事で、あまりよろしくない、画像なんかかわいくないので載せられない。

今日はFirefoxのアップデート中.....


2014年10月12日日曜日

デスクトップ環境をgnome3からXfce4にしました

gnome3からXfce4


最近までgnome3を利用していましたが、いまいちシックリこないので、Xfce4に変更してしまいました。 gnome3は見た目が奇麗でいいのですが、いざ使ってみると、gnome2の時のキー設定とは全くちがい、戸惑いました。 つまらないことのなのですが、ちょっとした違いについていけない思考回路になってしまっているようなので、あきらめました…笑




Xfce4を使った感想

シンプルなのが一番いいですね、 これでいいのです、ほぼgnome2の時と見た目も使い勝手もおなじで、使いやすいです。
やりたいことがすぐできる環境のほうが大事ですね、

「ウインドウズキーからアプリケーションアイコンをクリクリ」

とかいりません。



 同じことをするなら、早い方がいいし、覚えることが少ない方がいいと思います。
 一番いいことは、選択できる自由ですよね、気に入らなければ自分の好きなデスクトップ環境を選べるところです、

gentoo Linux はすばらしい…、gnome3も綺麗なので、併用して使うかな..

2014年9月21日日曜日

Stateモナドを利用して、gifヘッダの解析をやってみた

Stateモナドで状態を引き回す


とりあえず暇だったので、GIF画像のヘッダ情報を解析するコードをHaskellで書いてみました。

GIFヘッダは

  • Gif Header
  • Image Block
  • Graphic Control Extension
  • Comment Extention
  • Plain Text Extention
  • Application Extention

というように、分かれていますが、今回は「Gif Header」だけに限って解析してみました。

まずperlのgifcat.plを利用して情報を見てみる


あの有名なperlスクリプト、gifcat.plスクリプトを利用してヘッダ情報を確認してみる、
こんな感じのラッパースクリプトを作成して確認。
もちろん、gifcat.plは別途用意してください。
#!/usr/bin/perl

require "gifcat.pl";
@files = ("ai.gif");          # 解析したいGIF画像
print &gifcat'gifcat(@files);
このスクリプトを実行しますと、この様にヘッダ情報が確認できます。
cuomo@karky7 ~ $ perl checkGifHead.pl
=====================================
GifHeader
=====================================
Signature:                     GIF
Version:                       89a
Logical Screen Width:          300
Logical Screen Height:         423
Global Color Table Flag:       1
Color Resolution:              7
Sort Flag:                     0
Size of Global Color Table:    256 * 3
Background Color Index:        255
Pixel Aspect Ratio:            0
Global Color Table:
  10 0F 04 1B 15 05 24 15 06 32 18 0C 33 16 1F 26
  1E 0C 2E 1E 0D 39 1D 09 52 14 19 27 20 28 26 20
  2F 35 20 09 2E 23 08 32 22 09 6E 13 1D 2C 26 33
  4E 1D 2E 33 28 11 33 29 0A 39 27 0E 27 2A 33 4E
  22 12 2C 28 3C 65 18 36 3A 28 18 41 26 1B 39 26
  35 44 27 12 4B 25 12 49 29 0C 3A 2B 2B 41 2D 0C
  40 2D 13 3B 2F 10 46 2D 06 4D 25 45 56 2D 12 55
  2D 1A 62 2A 14 59 2C 1B 44 34 12 5C 2D 16 39 34
  40 50 31 1A 49 34 1A 43 36 19 53 32 15 4D 34 14
  4F 32 26 35 36 50 48 35 2B 96 21 27 4A 3A 17 A3
  1F 1E 8A 29 34 9C 23 3B 52 3F 16 5A 3D 1C 50 41
  1E 89 2C 48 6B 3A 17 54 40 20 50 40 2C 6F 38 20
  62 3C 1F 75 37 1F 69 3B 20 61 3D 26 67 3B 29 5C
  40 2E 5C 41 26 82 31 58 C5 24 2E 56 47 23 6A 3D
  4F 62 45 24 5C 47 24 5A 47 2C 5F 40 63 50 44 72
  43 4A 63 4E 49 51 7D 43 19 5C 4A 44 88 41 2B 62
  4D 2A C7 2D 40 3F 50 76 7F 45 2B 84 44 2A 6B 4C
  2B 7B 48 24 73 4B 2C 7A 49 2D 74 4D 1C 78 4A 37
  6F 4D 34 BA 37 3E 6D 4E 3D 63 52 3C C7 33 52 BA
  3D 52 BB 3B 65 92 50 35 8E 52 38 99 4F 36 8D 56
  32 8A 58 3C 88 58 44 82 5B 3A A8 4C 6A AE 4D 4F
  80 5C 42 7C 5D 4B A9 56 31 93 5E 2F B3 55 30 4F
  69 93 A2 5B 32 8F 5C 6F 7A 60 88 5E 69 82 75 68
  66 A2 5E 45 96 63 47 AA 5E 45 9F 64 40 E2 4E 5D
  93 6A 49 8C 6B 59 99 68 52 91 6B 51 9F 6A 4D D0
  66 3B D4 63 66 A5 74 57 B8 70 51 C3 6F 46 E1 61
  7C AD 74 5C B5 74 47 AB 77 54 D1 69 7B 9E 7B 5F
  9E 7D 51 A7 79 61 C8 74 3B C6 72 68 C0 72 94 C5
  73 7D AE 7D 5F 67 8A B3 8D 88 7F A5 83 74 B2 83
  4F B9 7D 79 A6 83 8C 81 8D A4 B3 85 6D C4 80 6D
  B6 85 66 CC 81 62 CE 82 58 BE 85 6D BC 87 63 B2
  8B 62 C7 86 57 B4 8E 6F BD 8C 6D AA 8C AB BC 8E
  74 E1 89 57 D9 8A 68 E8 84 7E D6 8D 79 C2 95 74
  E0 90 4F C9 93 79 DC 8F 73 C3 96 7C D2 94 68 D4
  92 7B DA 94 5F CF 96 73 EB 8C 95 C1 9A 8C CA 9B
  74 D4 9A 63 D2 9B 80 CA 9E 84 CD 9E 7D E5 96 AD
  E6 9D 8B CF A7 75 9C AE C8 B1 AC AB D1 A2 B0 DB
  A4 86 DF A5 77 DF A3 8B D1 A7 8D D9 A6 80 EA A3
  6D F0 A3 65 F3 A3 60 D6 A9 87 DC A7 8F C7 AD 9B
  E6 AA 72 D3 AC 9C CF B0 90 D9 AF 94 EA B2 95 F0
  B4 7F E6 B6 98 F8 B4 77 ED B3 B0 DE B9 A2 E1 BA
  9B E5 B8 A4 EA BB 93 DA BD B0 D5 C2 9A E3 C0 85
  EF B9 CA D7 C3 AE B9 C8 D9 F6 BE 89 E6 C2 A9 E4
  C4 B0 F5 C3 95 E7 CB 96 E4 C6 D1 FA C6 91 CD D0
  D5 F7 C9 A0 F3 CC A9 EF CD B3 EA D0 AB ED CE B9
  EF CD C3 FA C9 CB F3 CD CB EA D3 BB EF D3 C4 EB
  D7 C6 E4 D9 C8 F4 DE CD F6 E0 B8 F5 E3 D8 F3 E6
  D2 DF EC E5 F4 EA DD FE F2 E5 F8 F4 E4 F5 F7 EF
...
...
...
cuomo@karky7 ~ $

今度は、haskellでやってみる

まずは、解析したいGIF画像を選ぶのですが、私は「篠崎愛ちゃん」のファンでしたが、最近は心境の変化により若干趣味思考が変わってきたのでサヨナラの意味も込めて、「篠崎愛ちゃん」のGIFヘッダを解析して、心の区切りをつけようと思います。

デスから、画像はこれ、



これをGIFに変換したものを利用します。
で、コードはこちら、Stateモナドを利用してGIFのバイトデータを1バイトづつ解析しています。
{-# LANGUAGE OverloadedStrings #-}

import qualified Data.ByteString.Lazy.Char8 as L8
import qualified Data.ByteString.Lazy as L
import System.Environment (getArgs)
import Control.Applicative ((<$>))
import Control.Monad.State
import Data.Bits ((.&.), shiftR)
import Data.Int
import Data.Word
import Data.Char
import Text.Printf


data GifHeader = GifHeader {
  signature        :: L8.ByteString,     -- GIF for 3bytes
  version          :: L8.ByteString,     -- Version 3bytes
  log_sc_width     :: Word16,            -- Logical Screen width 2bytes
  log_sc_height    :: Word16,            -- Logical Screen height 2bytes
  packfeild        :: Word8,             -- Image info 1byte
  bgcol_idx        :: Word8,             -- Background color index 1byte
  pix_asp_ratio    :: Word8,
  global_col_tbl   :: L8.ByteString      -- Global Color table
} deriving (Show)


data StateBuffer = StateBuffer {
  buffer :: L8.ByteString,
  offset :: Int64
} deriving(Show)


type StateBuff a = State StateBuffer a


parseBytes :: Int64 -> StateBuff L.ByteString
parseBytes n = get >>= \st ->
  case L.splitAt n (buffer st) of
    (bs, remainder) -> put new_state >>= \_ -> return bs
      where new_state = StateBuffer { buffer = remainder,
                                  offset = new_offset }
            new_offset = offset st + n


settpl :: L.ByteString -> [(Word8, Int)]
settpl v = zip v' [1 .. length v']
           where v' = L.unpack v


toWord8 :: (Enum a) => a -> Word8
toWord8 = toEnum . fromEnum


toWord16 :: (Enum a) => a -> Word16
toWord16 = toEnum . fromEnum


sumWord8 :: Enum a => (a, Int) -> Word16 -> Word16
sumWord8 (w, v) b = (toWord16 w) * (toWord16 v ^ 8) + b


getWord :: Int64 -> StateBuff [(Word8, Int)]
getWord n = settpl <$> parseBytes n


parseW8 :: StateBuff Word8
parseW8 = head . L.unpack <$> parseBytes 1


parseW16toInt :: StateBuff Word16
parseW16toInt = foldr sumWord8 0 <$> getWord 2


sizeOfGCT :: Word8 -> Int64
sizeOfGCT feild
  | (f /= 0) = 3 * 2 ^ ((feild .&. 0x07) + 1)
  | otherwise = 0
  where f = (feild .&. 0x80)


sizeOfSGCT :: Word8 -> Int
sizeOfSGCT bf = 2 ^ ((bf .&. 0x07) + 1)


readGifHeader :: StateBuff GifHeader
readGifHeader = parseBytes 3 >>= \sig ->
  parseBytes 3 >>= \ver ->
  parseW16toInt >>= \lw ->
  parseW16toInt >>= \lh ->
  parseW8       >>= \pf ->
  parseW8       >>= \bgi ->
  parseW8       >>= \pixar ->
  parseBytes (sizeOfGCT pf) >>= \gct ->
  return GifHeader { signature = sig,
                     version = ver,
                     log_sc_width = lw,
                     log_sc_height = lh,
                     packfeild = pf,
                     bgcol_idx = bgi,
                     pix_asp_ratio = pixar,
                     global_col_tbl = gct }


readGifFile :: FilePath -> IO L.ByteString
readGifFile filename = L.readFile filename


wordToChar :: Word8 -> Char
wordToChar = chr . fromIntegral


toWordsToChar :: L.ByteString -> [Char]
toWordsToChar = (map wordToChar) . L.unpack


isColTableFlag :: Word8 -> Int
isColTableFlag bf
  | f /= 0 = 1
  | otherwise = 0
     where f = bf .&. 0x80


getColResolusion :: Word8 -> Word8
getColResolusion bf = (bf `shiftR` 4) .&. 0x07 + 1


getSortFlag :: Word8 -> Word8
getSortFlag bf = (bf `shiftR` 3) .&. 0x01


putGifHeader :: GifHeader -> IO ()
putGifHeader v = do
    putStr $ "====================\n" ++
           "GifHeader \n" ++
           "====================\n" ++
           "Signature:                     " ++ toWordsToChar (signature v) ++ "\n" ++ 
           "Version:                       " ++ toWordsToChar (version v) ++ "\n" ++
           "Logical Screen Width:          " ++ show (log_sc_width v) ++ "\n" ++
           "Logical Screen Height:         " ++ show (log_sc_height v) ++ "\n" ++
           "Global Color Table Flag:       " ++ show (packfeild v) ++ "(" ++ show (isColTableFlag $ packfeild v) ++ ")" ++ "\n" ++
           "Color Resolution:              " ++ show (getColResolusion $ packfeild v) ++ "\n" ++
           "Sort Flag:                     " ++ show (getSortFlag $ packfeild v) ++ "\n" ++
           "Size of Global Color Table:    " ++ show (sizeOfGCT $ packfeild v) ++ "(" ++ show (sizeOfSGCT (packfeild v)) ++ " * 3)" ++ "\n" ++
           "Background Color Index:        " ++ show (bgcol_idx v) ++ "\n" ++
           "Pixel Aspect Ratio:            " ++ show (pix_asp_ratio v) ++ "\n" ++
           "Global Color Table:             \n"
    putStr $ dump (L.unpack $ global_col_tbl v)


printByte :: Word8 -> String
printByte = printf "%02X "


dump ::  [Word8] -> String
dump = dump' 0


dump' :: Int64 -> [Word8] -> String
dump' _ [] = "\n"
dump' i (b:xs)
  | (i `mod` 16 == 0) = "  " ++ printByte b ++ dump' (i+1) xs
  | (i `mod` 16 == 15) = printByte b ++ "\n" ++ dump' (i+1) xs
  | otherwise = printByte b ++ dump' (i+1) xs


putRemainState :: StateBuffer -> IO ()
putRemainState s = do
    let buff = buffer s
        off = offset s
    putStr $ "-------------------\n" ++
           "StateBuffer \n" ++
           "-------------------\n" ++
           "offset:      " ++ show(off) ++ "\n" ++
           "Remain buffer:\n"
    putStr $ dump (L.unpack buff)


initStateBuffer :: L8.ByteString -> StateBuffer
initStateBuffer buff = StateBuffer { buffer = buff, offset = 0 }


main :: IO()
main = do
  args <- getArgs
  buff <- readGifFile $ head args
  let (h, s) = runState readGifHeader $ initStateBuffer buff
  putGifHeader h
  putRemainState s
実行してみると、
cuomo@karky7 ~ $ runghc gifcat2.hs ai.gif
====================
GifHeader
====================
Signature:                     GIF
Version:                       89a
Logical Screen Width:          300
Logical Screen Height:         423
Global Color Table Flag:       231(1)
Color Resolution:              7
Sort Flag:                     0
Size of Global Color Table:    768(256 * 3)
Background Color Index:        255
Pixel Aspect Ratio:            0
Global Color Table:
  10 0F 04 1B 15 05 24 15 06 32 18 0C 33 16 1F 26
  1E 0C 2E 1E 0D 39 1D 09 52 14 19 27 20 28 26 20
  2F 35 20 09 2E 23 08 32 22 09 6E 13 1D 2C 26 33
  4E 1D 2E 33 28 11 33 29 0A 39 27 0E 27 2A 33 4E
  22 12 2C 28 3C 65 18 36 3A 28 18 41 26 1B 39 26
  35 44 27 12 4B 25 12 49 29 0C 3A 2B 2B 41 2D 0C
  40 2D 13 3B 2F 10 46 2D 06 4D 25 45 56 2D 12 55
  2D 1A 62 2A 14 59 2C 1B 44 34 12 5C 2D 16 39 34
  40 50 31 1A 49 34 1A 43 36 19 53 32 15 4D 34 14
  4F 32 26 35 36 50 48 35 2B 96 21 27 4A 3A 17 A3
  1F 1E 8A 29 34 9C 23 3B 52 3F 16 5A 3D 1C 50 41
  1E 89 2C 48 6B 3A 17 54 40 20 50 40 2C 6F 38 20
  62 3C 1F 75 37 1F 69 3B 20 61 3D 26 67 3B 29 5C
  40 2E 5C 41 26 82 31 58 C5 24 2E 56 47 23 6A 3D
  4F 62 45 24 5C 47 24 5A 47 2C 5F 40 63 50 44 72
  43 4A 63 4E 49 51 7D 43 19 5C 4A 44 88 41 2B 62
  4D 2A C7 2D 40 3F 50 76 7F 45 2B 84 44 2A 6B 4C
  2B 7B 48 24 73 4B 2C 7A 49 2D 74 4D 1C 78 4A 37
  6F 4D 34 BA 37 3E 6D 4E 3D 63 52 3C C7 33 52 BA
  3D 52 BB 3B 65 92 50 35 8E 52 38 99 4F 36 8D 56
  32 8A 58 3C 88 58 44 82 5B 3A A8 4C 6A AE 4D 4F
  80 5C 42 7C 5D 4B A9 56 31 93 5E 2F B3 55 30 4F
  69 93 A2 5B 32 8F 5C 6F 7A 60 88 5E 69 82 75 68
  66 A2 5E 45 96 63 47 AA 5E 45 9F 64 40 E2 4E 5D
  93 6A 49 8C 6B 59 99 68 52 91 6B 51 9F 6A 4D D0
  66 3B D4 63 66 A5 74 57 B8 70 51 C3 6F 46 E1 61
  7C AD 74 5C B5 74 47 AB 77 54 D1 69 7B 9E 7B 5F
  9E 7D 51 A7 79 61 C8 74 3B C6 72 68 C0 72 94 C5
  73 7D AE 7D 5F 67 8A B3 8D 88 7F A5 83 74 B2 83
  4F B9 7D 79 A6 83 8C 81 8D A4 B3 85 6D C4 80 6D
  B6 85 66 CC 81 62 CE 82 58 BE 85 6D BC 87 63 B2
  8B 62 C7 86 57 B4 8E 6F BD 8C 6D AA 8C AB BC 8E
  74 E1 89 57 D9 8A 68 E8 84 7E D6 8D 79 C2 95 74
  E0 90 4F C9 93 79 DC 8F 73 C3 96 7C D2 94 68 D4
  92 7B DA 94 5F CF 96 73 EB 8C 95 C1 9A 8C CA 9B
  74 D4 9A 63 D2 9B 80 CA 9E 84 CD 9E 7D E5 96 AD
  E6 9D 8B CF A7 75 9C AE C8 B1 AC AB D1 A2 B0 DB
  A4 86 DF A5 77 DF A3 8B D1 A7 8D D9 A6 80 EA A3
  6D F0 A3 65 F3 A3 60 D6 A9 87 DC A7 8F C7 AD 9B
  E6 AA 72 D3 AC 9C CF B0 90 D9 AF 94 EA B2 95 F0
  B4 7F E6 B6 98 F8 B4 77 ED B3 B0 DE B9 A2 E1 BA
  9B E5 B8 A4 EA BB 93 DA BD B0 D5 C2 9A E3 C0 85
  EF B9 CA D7 C3 AE B9 C8 D9 F6 BE 89 E6 C2 A9 E4
  C4 B0 F5 C3 95 E7 CB 96 E4 C6 D1 FA C6 91 CD D0
  D5 F7 C9 A0 F3 CC A9 EF CD B3 EA D0 AB ED CE B9
  EF CD C3 FA C9 CB F3 CD CB EA D3 BB EF D3 C4 EB
  D7 C6 E4 D9 C8 F4 DE CD F6 E0 B8 F5 E3 D8 F3 E6
  D2 DF EC E5 F4 EA DD FE F2 E5 F8 F4 E4 F5 F7 EF

-------------------
StateBuffer
-------------------
offset:      781
Remain buffer:
  21 FE 11 43 72 65 61 74 65 64 20 77 69 74 68 20
  47 49 4D 50 00 2C 00 00 00 00 2C 01 A7 01 00 08
  FE 00 B5 B1 1B 48 90 1D 37 2F 2E 56 28 64 C1 62
  C5 86 87 10 1F 82 58 40 71 82 C5 09 11 22 48 08
  C1 31 84 84 8F 12 22 30 10 C9 60 64 49 92 23 51
  96 5C C9 B2 A5 4B 06 05 5E 96 04 39 73 A6 04 06
  0D 24 34 D8 C9 12 E4 C7 10 20 72 B8 68 E3 02 0C
  18 17 42 81 2C 21 E1 A2 83 C3 40 07 38 38 3C 70
  60 81 01 01 02 00 68 D5 1A 20 00 06 01 18 AE 1A
  28 00 A0 EB D6 B2 01 B8 16 28 90 F6 AC DB B7 70
  E3 CA 95 DB 16 2D DA AE 6B 33 5A 04 C1 B7 2F DF
  10 2D 5A A0 08 8C A2 30 C7 16 1D 13 2B F6 B9 B1
  E3 CD 8C 1A 43 92 6C B0 F6 AA 00 81 05 07 72 23
  BA 90 61 43 85 11 1F 52 5C 70 11 A3 46 C5 1E 21
  AB 26 29 92 B5 CC D7 2F D7 CA 64 CC E0 E6 47 9C
  3A 79 D6 66 0C 94 45 8E 36 6D 80 18 75 01 A4 B8
  8B A6 2E 86 04 82 B1 02 48 07 AA 03 BE 66 AD 5B
  36 82 81 B0 60 B3 0A A0 BE 35 C0 5A B3 DC E7 FE
  8A 1F 4F FE EE 5D EF 05 22 EC 9C E0 B7 2F E0 C0
  82 0B A3 08 31 FF 30 6A C7 1E 41 7A 4C 0D F9 A3
  46 92 6B 61 25 00 39 99 0D B4 0E 24 09 AD E0 D9
  67 A1 89 56 D1 45 19 6D 24 A1 4F AD AD 94 91 85
  26 C1 A6 21 4B 31 CD 56 DB 4A 37 D5 96 D3 4E 39
  D9 A6 5F 0B 20 14 91 C3 20 5A 14 05 06 17 4B B8
  40 02 10 4C 81 21 06 1C 1C 0C D1 D4 06 03 64 80
  15 77 E9 C9 80 9D 0C 58 B1 D5 5D 5B 02 7C C7 55
  79 4C 36 39 57 5A 5D 45 99 9E 7A EC B5 07 02 7D
  82 11 56 1F 7D F7 DD 37 E1 7E 92 45 28 52 48 38
  05 88 15 66 99 1D ...
  ....
これで、「愛ちゃん」ヘッダ情報があらわになりました、StateBufferの項目は、まだ解析されていない残りのgifデータが格納されています...裸も同然です

haskellでやる良さ


だいたい手続き型の言語でバッファのデータを消費していくようなコードを書くと、バッファにインデックスでアクセスしていくようなループ処理になると思いますが、機能別に関数に分けたりすると、関数別にインデックスを進めるような感じのコードになりがちで、いまいち綺麗じゃありませんよね。まぁもうちょい頭を使えば綺麗にはなるとは思いますが...適当に書くとこんな感じかと。 適当に考えたコード
main()
{
    int cnt;
    Byte buff = read("ai.gif");
    cnt = func1(&buff, 0);
    cnt = func2(&buff, cnt);
    ...
    ...
}

int func1(Byte *buff, int start_index)
{
 int cnt = 0;
 ...
 // 消費したバイト数をかえす
 return start_index + cnt;
}

int func2(Byte *buff, int start_index)
{
 int cnt = 0;
 ...
 return start_index + cnt;
}
...
...
haskell版のコードの場合、その辺の細々した詳細をStateモナドが隠してくれているので、実際のヘッダ解析の処理にバッファのインデックスを操作する処理が見えないところが、余計な事を考えず処理を書くことに集中させてくれます。
さらに、parseBytesの引数に与えた取得したいバイト数しか、インデックスが進む事がないので、間違いが起こりにくい所なんかいいんではないでしょうか。
もし間違いがあるとすれば、readGifHeader関数で(>>=)で繋いでる関数に問題があるのがほぼ確定的に分かります。
それと、状態関数を走らせた後の結果に、直接別の関数を適用させる、ファンクターのfmapなんかすごくコードをシンプルしてくれます。

Stateモナドは、状態を持ち回る関数をコンビネータとしてつないで書いといて、初期状態を与えることによってつないである関数を走らせる、という難解なもののうちの1種だと私は思いますが、理解すると「これだ!」って感じにさせてくれるのが、私にとってのhaskellで、止められません...

「大人の表情(かお)をしたキミに、鼓動が高鳴る」とか言われたらアウトでしょ....


2014年9月12日金曜日

gentoo+pandoc+google-html5-slide でクールな美人スライドを作る

HTMLで作る、スライド


皆さんはもう知っているかも知れませんが、最近、美人なAPIを最近見つけてしまい、

「これは、APIで画像提供してくれているならば、是非私もいただきたい。」

とおもいまして、頑張って収集スクリプトを作って見ました。

しかし、やっぱり私は後々テキストファイルで編集するような事がしたいので

「markdownとかで編集してスライドを作るようなもんねぇーかなー...」


など思っていたところ、なんと、hackageにgoogle-html5-slideな素晴らしいパッケージがアルではないですか! @tanakhさんがgithubに上げてくださっていましたのでそちらを利用させていただき、gentooのebuilを作成しました。


最初にgoogle-html5-slideをインストールする


これは、私のgentooがローリングインストールになっているので、haskellのパッケージが色々腐った部分が発生していて、オリジナルのリポジトリからのemergeが失敗してしまうのでforkさせていただき、パッチ的なアレを適用してありますので、ご利用は計画的にお願いします。

現リビジョンで出来ないことは

  • divタグの処理が出来ない
  • spanタグの処理が出来てない
  • 色が出ない(これは致命的)

と言う感じになっています、今後修理していきます....ということでインストール


karky7 ~ # layman -a karky7
karky7 ~ # emerge -pv dev-haskell/google-html5-slide

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

Calculating dependencies... done!
[ebuild  N    ~] dev-haskell/google-html5-slide-9999:0/9999::karky7  0 kB

Total: 1 package (1 new), Size of downloads: 0 kB

 * IMPORTANT: 25 news items need reading for repository 'gentoo'.
 * Use eselect news to read news items.

karky7 ~ # emerge dev-haskell/google-html5-slide


cuomo@karky7 ~ $ /usr/bin/google-html5-slide --help
The html5slide program

html5slide [OPTIONS] FILE

Common flags:
     --script-url=URL         URL of Google HTML5 slide script
     --slide-class=CLASSNAME  CSS class name of slide
     --style-css=FILE         Style CSS file
     --syntax-css=FILE        Syntax CSS file
     --poll                   Poll filesystem for changes
  -? --help                   Display help message
  -V --version                Print version information
cuomo@karky7 ~ $

これで/usr/binにgoogle-html5-slideコマンドが入るはずです!

美人の画像を収集してmarkdownのファイルを作成する

さぁ、画像を集める時間です、今回利用したのは、Bjin.Meっていうサイトの画像ですが、APIを提供していますのでそちらを利用して画像を取得します、でも待って!
人力で収集しなくてもいいんです、秘密のスクリプトがあるんです、他の人には内緒ですよ。

画像取得、markdownファイル作成

以下のファイルで画像を収集して、markdownファイルを作成する
このスクリプトはどこかディレクトリを掘ってそこへ設置してください。
{-# LANGUAGE OverloadedStrings #-}

import qualified Filesystem as F
import qualified Filesystem.Path as P
import Network.HTTP
import Data.Aeson
import qualified Data.Text as T
import Data.List.Split
import qualified Data.Attoparsec as AP (parseOnly)
import qualified Data.Attoparsec.Number as N (Number(I,D))
import Control.Applicative ((<$>),(<*>))
import Control.Monad
import qualified Data.ByteString.Lazy.Char8 as L8
import qualified Data.ByteString.Internal as I
import Data.Either.Utils (forceEither)

data Format = Xml | Json deriving(Show)
data RType = RRand | RNone deriving(Show)

data Req = Req {
  format :: Format,
  cnt :: Int,
  rtype :: RType
} deriving(Show)

data Vlist = Vlist {
  obj :: [Res]
} deriving(Show)

data Res = Res {
  cid :: Int,         -- コンテンID
  category :: String, -- 特定されている場合は人物の名
  thumb :: String,    -- thumnail
  link :: String,     -- Bjin.Mの表示リン
  pubDate :: String   -- このデータが発行された日
} deriving(Show)

instance FromJSON Res where
  parseJSON (Object val) = Res
                           <$> val .: "id"
                           <*> val .: "category"
                           <*> val .: "thumb"
                           <*> val .: "link"
                           <*> val .: "pubDate"
  parseJSON _            = mzero

req2url :: Req -> String
req2url r = bjnUrl ++ "type=" ++ (getrtype r) ++ "&count=" ++ show(cnt r) ++ "&format=" ++ (getfmttype r)
  where getrtype r = case rtype r of
                      RRand -> "rand"
                      RNone -> ""
        getfmttype r = case format r of
                         Xml -> "xml"
                         Json -> "json"

bjnUrl :: String
bjnUrl = "http://bjin.me/api/?"

bjnImgUrl :: String
bjnImgUrl = "http://bjin.me/images/"

getReq :: Req
getReq = Req { format = Json, cnt = 10, rtype = RRand }

getBjins :: String -> IO String
getBjins url = simpleHTTP (getRequest url) >>= getResponseBody

getRes :: Value -> [Res]
getRes res = do
  case fromJSON res of
    Success r -> r
    _ -> []

detailPics :: [Res] -> [String]
detailPics res = map (\r -> (bjnImgUrl ++ "pic" ++ show(cid r) ++ ".jpg")) res

storePics :: [String] -> IO ()
storePics [] = return ()
storePics (url:xs) = getBjins url >>= writePic file >> (putStrLn $ url ++ "...done") >> storePics xs
                       where file = last $ splitOn "/" url

mdFile :: P.FilePath
mdFile = "tammannai.md"

writePic :: String -> String -> IO ()
writePic file pic = L8.writeFile file (L8.pack pic) >> F.appendTextFile mdFile (createMd file)

createMd :: String -> T.Text
createMd file = T.replace (T.pack "<--PIC-->") (T.pack file) (T.pack center)
  where fill = "## pic1\n\n<article class='fill'>\n\n<img src='<--PIC-->'>\n\n</article>\n\n"
        center = "## pic\n\n<img  class='centered' src='<--PIC-->'>\n\n"

setHeader :: IO ()
setHeader = F.readTextFile mdFile >>= \t -> F.writeTextFile mdFile (T.pack h `T.append` t)
  where h = "% たまんない/gentoo <br>Majide Yabea ee.ee\n% @karky7\n% Sep 11, 2014\n\n君だけの思い出を創るんだっ!\n\nThere is more pictures just beautiful!.\n\n"

setFooter :: IO ()
setFooter = F.appendTextFile  mdFile (T.pack s)
  where s = "## Thank you!\n\n* [karky7.com](http://www.karky7.com)\n"

main :: IO ()
main = do
  res <- I.packChars <$> getBjins (req2url getReq)
  let vlist = getRes $ forceEither (AP.parseOnly json res)
  storePics $ detailPics vlist
  setHeader
  putStrLn "OK complete..."


そしてスライドを作成する 

後は実行するだけ、ランダムに画像を取得する仕組みになっていますが、画像がでかすぎたりするとうまく表示出来ない場合がありますので、その際はmarkdownファイルを修正してください。
実行したら、markdownファイルが作成されますので、google-html5-slideコマンドでhtmlファイルを作成してください。

最後に出来上がるのは、tamannnai,html(たまんない.html)です


cuomo@karky7 ~ $ mkdir ~/bjin
cuomo@karky7 ~ $ cd bjin/
cuomo@karky7 ~/bjin $ runghc bjin.hs 
http://bjin.me/images/pic20952.jpg...done
http://bjin.me/images/pic13645.jpg...done
http://bjin.me/images/pic248832.jpg...done
OK complete...
cuomo@karky7 ~/bjin $ google-html5-slide tammannai.md

さぁ、tamannai.htmlをブラウザで見てご覧

ぬぉぉ、これは、たまんない!でも綺麗につくれます、こんな感じになります


こんなに綺麗に簡単にスライドが作れるなら、PowerPointいらなくね?って感じになりますが...だがしかし、必要です

gentooとhaskellなら、無限の可能性を引き出せる感じがして、たまりません


いま、ドトールで書いているのデスが、隣のおねぇーさんが、こちらをみて不審そうな顔でぇ.....では

2014年8月24日日曜日

ikea港北へ行ってきました

ご冗談でしょ、ikeaさん


最近、ikeaへ行ってきました、大変色々な家具が売っていまして驚いた次第です。
でもね、色々ありすぎるのも困ります、私はいろんなものを見すぎて嫌になっちゃいました。

結局、飲むだけですよ!

ダメですね、家具とか、覚えてません。

でもね、ikeaオリジナルのビールはおいしかったです、ロースとビーフも980円で食べれます、で、JAZZとか店内で流れてて、結構楽しいですよ、家族できてる方も多いです。



15年前、設備屋だった、私としては、キッチンとか、オリジナル感だしたいような方は、結構、いいデザインのものがあったような気がしますが...記憶にございません

ビールうまい。



2014年8月21日木曜日

奥さん...Solaris11のNFSとautofsで自動マウントする

NFSのサーバー設定


Solaris11のNFSサーバー設定はエラく簡単、
kari7 ~ # zfs destroy rpool/backups
kari7 ~ # zfs create -o mountpoint=/backups rpool/backups
kari7 ~ # zfs set share=name=nfs_backups,path=/backups,prot=nfs,sec=sys,rw=*,public rpool/backups
name=nfs_backups,path=/backups,prot=nfs,public=true,sec=sys,rw=*
kari7 ~ # zfs set sharenfs=on rpool/backups
kari7 ~ # chown nobody:nobody /backups
kari7 ~ # share -A
nfs_backups     /backups        nfs     public,sec=sys,rw
kari7 ~ #
kari7 ~ # svcs -a | grep nfs
disabled       22:46:18 svc:/network/nfs/cbd:default
disabled       22:46:18 svc:/network/nfs/client:default
online         22:46:37 svc:/network/nfs/fedfs-client:default
online         22:52:29 svc:/network/nfs/status:default
online         22:52:29 svc:/network/nfs/rquota:default
online         22:52:29 svc:/network/nfs/mapid:default
online         22:52:29 svc:/network/nfs/nlockmgr:default
online         22:52:32 svc:/network/nfs/server:default
kari7 ~ # 
これだけ、サーバー設定が終了

NFSクライアントの設定


手動でマウントする場合は、
tsubane7 ~ # mount -F nfs 192.168.11.9:/backups /mnt/backups
これでマウント終了、/mnt/backupsは任意でディレクトリを作成しておいてください

autofsで必要なときにマウント出きるようにしておく


毎回、手動でマウントはダルい、そんな時...そうです「奥さんautofsですよ」 で、設定する。
autofsを設定しておくと、指定のディレクトリを触ったときに、自動でマウントしてくれる。

マスターマップの修正


エディタで/etc/auto_masterファイルを修正し、最後の行を追加
#
# Copyright (c) 1992, 2011, Oracle and/or its affiliates. All rights reserved.
#
# Master map for automounter
#
+auto_master
/net            -hosts          -nosuid,nobrowse
/home           auto_home       -nobrowse
/nfs4           -fedfs          -ro,nosuid,nobrowse
/mnt            auto_nfs_backups
さらに、/etc/auto_nfs_backupsファイルを追加し、NFSサーバーの記述を追加
#
# share directory map for automounter
#
backups          192.168.11.9:/backupst
最後に、クライアント側の、autofsサービスの再起動
tsubane7 ~ # svcadm restart svc:/system/filesystem/autofs:default
で、クライアント側の/mnt/backupディレクトリへアクセスすると、自動でマウントされますよぉ
tsubane7 ~ # cd /mnt/backups
tsubane7 ~ # touch a.txt
こんな感じで設定できます。

奥さん...

2014年5月10日土曜日

伊豆高原でご飯を食べるなら「和風 Dining 山良」で

いつもお世話になっている山良で同級会をやってきました


昭和47年生まれの仲間と山吉で飲んで着ました、相変わらず酒飲みと暇人ばかりでどうしようもない人たちばかりでした。
アルコールDrivenといっていいほど酒が入ってないと正常に喋れない人たちばかりで困ります。

だいたいいつも下らない話で盛り上がっているかどうか分からないのですが、あまり覚えていません、次の日はほぼ二日酔いです(脳をやられてますね)。

で、そんなことはどうでもいいのですが、伊豆高原って意外と港街でもあって、海岸に近い所は海の幸を頂けます。
そこでおすすめする食事処が山良さんです。


活きのいい魚なんかリーズナブルに食べれますよ


全部旨いのですが、イカのワタ付きの刺身がたまらないですね。


それからやはり酒ですよね、


もはや止まりませんね。

奥も座敷がありますので、家族できても問題ありません、伊豆高原に来た時は寄ってみるのもいいかもしれません。

ぜひどうぞ





2014年4月23日水曜日

アナと雪の女王とgentoo

アナと雪の女王を見てきました


gentooの次にディズニー映画が好きな僕ですが、最近、よく映画を見るようになったのですが、どれもつまらない映画ばかりで損した気分になるところを、やはりこの映画は問題なく面白かったです。

ミュージカル的なノリで最後まで飽きずに見る事ができました。
松たかこの歌がいいですねぇ、すごい歌唱力だなと感心しました。



私もカラオケで歌えるように練習しようと思っています。

やはりディズニー映画はワールドを感じますね、子供も大人も楽しめる映画を作れるというのはそう簡単にできる事ではありませんよね。

で、gentooとどこが関係あるのって言われそうですが、ただいいたいだけです。

でも、是非みにいってみてください。

すこしも寒くはないわ/gentoo

...


2014年4月20日日曜日

消費税8%問題とceil関数の罠

1円が合わないのはなぜ? 


最近、消費税が8%に上がり、お買い物が楽しくなった今日この頃。チョット気になる問題が僕を襲いました。なんとceil関数の罠にドップリはまり、2、3日、酒浸りになりました。

ことの発端が、この計算
<?php
$v = ceil(15000 * 1.08);
print($v . "\n");
?>
cuomo@localhost ~ $ php sample.php 
16201
ちょ、まて、俺が望んでるのは、16200だぞ!

これに気づきませんでした...

「1円!違ってるけどどうなってんのっ!、いっぱい1円違うじゃないのぉーーー (怒)」

言われるはずです、早速直して対応したのですが、なんで?って思いますよね...
調べましょう、Gentooで......


そもそもの間違い


ceilのせいでは....ないんですよ、ceilはドキュメントに書いてあるとおりに動作しています、手で計算した結果を鵜呑みにして、さらに和をかけて思いこみの沙汰が酷過ぎ、単なる浅はかさがこの事態を生んだ模様です 笑...。

調査開始


まずPHPのceil関数をしらべてみたら、ext/standard/math.cでceil関数を呼んでいる、ceil関数はgentooですとglibcパッケージ(libm)に入っていますので、そちらを確認してみましょう。

<pre>
PHP_FUNCTION(ceil)
{
    zval **value;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &value) == FAILURE) {
        return;
    }
    convert_scalar_to_number_ex(value);

    if (Z_TYPE_PP(value) == IS_DOUBLE) {
        RETURN_DOUBLE(ceil(Z_DVAL_PP(value))); /* ceil関数を呼び出し */
    } else if (Z_TYPE_PP(value) == IS_LONG) {
        convert_to_double_ex(value);
        RETURN_DOUBLE(Z_DVAL_PP(value));
    }
    RETURN_FALSE;
}
</pre>


ですね、これを元にceilを利用したサンプル関数を作ってみる

実際はどんなことしてるんだ


glibcのコードをソースコードレベルで解析したいので、面倒ですがglibcをdebug版でコンパイルしなおす。まぁ、emergeするだけなので楽勝ですが、出きるまでビールでも呑んでましょう。
サンプルコードとgdbを利用して、libmのceil関数へブレークポイントを仕掛けて、実行してみる。


#include <stdio.h>
#include <math.h>

double subceil(int);

int main(void)
{
  double v;
  v = subceil(15000);
  printf("%f\n", v);
  return 0;
}

double subceil(int v)
{
  return ceil(v * 1.08);
}
cuomo@localhost ~ $  gcc -g ceil.c -L/usr/lib64/debug/lib64 -lm -lc -O0 -o c.out
これを、gdbで止めてみると../sysdeps/x86_64/fpu/multiarch/s_ceil.S:37で停止するのですがSSE4のroundsd命令で 一撃でやられちゃってよくわからないので(自分がSSEをよくわかってない...笑)、正確ではないのですが違う関数ceillで再度確認。
Breakpoint 1, __ceil_sse41 () at ../sysdeps/x86_64/fpu/multiarch/s_ceil.S:37
37              roundsd $2, %xmm0, %xmm0
(gdb) l
32      END(__ceil)
33      weak_alias (__ceil, ceil)
34
35
36      ENTRY(__ceil_sse41)
37              roundsd $2, %xmm0, %xmm0 /* xmm0レジスタ一撃ですわ */
38              ret
39      END(__ceil_sse41)

自分的にわかりにくかったので、ceillでもう一度
#include <stdio.h>
#include <math.h>

double subceil(int);

int main(void)
{
  double v;
  v = subceil(15000);
  printf("%f\n", v);
  return 0;
}

double subceil(int v)
{
  return ceill(v * 1.08); /* ceil()をceill()に修正 */
}

もう一度、ビルドし直し、gdbでブレークしてみる

cuomo@localhost ~/Code/binaries/CProgs/ceil $ gdb ./c.out
GNU gdb (Gentoo 7.6.2 p1) 7.6.2
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-pc-linux-gnu".
For bug reporting instructions, please see:
<http://bugs.gentoo.org/>...
Reading symbols from /home/cuomo/Code/binaries/CProgs/ceil/c.out...done.
(gdb) b ceill
Breakpoint 1 at 0x400520
(gdb) r
Starting program: /home/cuomo/Code/binaries/CProgs/ceil/./c.out
warning: no loadable sections found in added symbol-file system-supplied DSO at 0x7ffff7ffa000
warning: Could not load shared library symbols for linux-vdso.so.1.
Do you need "set solib-search-path" or "set sysroot"?

Breakpoint 1, ceill () at ../sysdeps/x86_64/fpu/s_ceill.S:12
7
8       #include <machine/asm.h>
9
10
11      ENTRY(__ceill)
12              fldt    8(%rsp)                 /*Floating Point Load */ 
13
14              fstcw   -4(%rsp)                /* store fpu control word */
15
16              /* We use here %edx although only the low 1 bits are defined.
17                 But none of the operations should care and they are faster
18                 than the 16 bit operations.  */
19              movl    $0x0800,%edx            /* コントロールレジスタのRCフィールドを切り上げにセット */
20              orl     -4(%rsp),%edx
21              andl    $0xfbff,%edx
22              movl    %edx,-8(%rsp)
23              fldcw   -8(%rsp)                /* コントロールレジスタを設定 */
24
25              frndint                         /* 切上処理の実行 */
26
27              fldcw   -4(%rsp)                /* コントロールレジスタを元に戻す */
28
29              ret
30      END (__ceill)
31      weak_alias (__ceill, ceill)
(gdb)
多分こちらはx87の浮動小数点計算処理でSSE命令より余計な部分が多いのですが、何をやっているのかわかりやすいのでこちらで確認。 x87の細かい使い方は専門の方へお願いするとして、数バイトstep実行させた後のST(0)の値、ここへ15000*1.08の計算結果が格納されている。この時点でお分かりですよね、そう小数点の部分が0ではないのです、これをfrndintでやってしまえばそれはそうなりますよって話 笑...
(gdb) info all-reg
...
st0            16200.000000000001818989403545856476 (raw 0x400cfd20000000000800)
...

ここからはつまらない話


x86拡張倍精度で80bitの形式で保存されていて、16進数で0x400cfd20000000000800という値を保存している、で、さらにこれを2進数80bitで表現すると...
0 100000000001100 1 111110100100000000000000000000000000000000000000000100000000000


  • 符号部(s) 0(1bit)
  • 指数部(e) 100000000001100(15bit バイアス値 16383)
  • 整数部(p) 1(1bit)
  • 仮数部(f)  111110100100000000000000000000000000000000000000000100000000000(64bit)
でわけられ、下の式で計算される
(-1)^s * 2^(e-16383) * p.f
※fは2進数を小数に変換したもの
これに習って計算してみると
8192 * 1.9775390625 ~= 16200.00000000000181... ※1.9775390625 ~= 1 + (1/2 + 1/4 + 1/8 + 1/16 + 1/32 + 1/128 + 1/1024 + 1/4503599627370496) こういうことに内部的になっているため、frndintを実行した場合に1を加えた数値になります。
実際の計算を終えた後の、浮動小数点レジスタの値はこの様な感じになってました。
st(0)の値がしっかり16201になってますね。
(gdb) info all-reg
...
...
es             0x0      0
fs             0x0      0
gs             0x0      0
st0            16201    (raw 0x400cfd24000000000000)
st1            0        (raw 0x00000000000000000000)
st2            0        (raw 0x00000000000000000000)
st3            0        (raw 0x00000000000000000000)
st4            0        (raw 0x00000000000000000000)
st5            0        (raw 0x00000000000000000000)
st6            0        (raw 0x00000000000000000000)
st7            0        (raw 0x00000000000000000000)
fctrl          0xb7f    2943
fstat          0x3a20   14880
ftag           0x3fff   16383
fiseg          0x7fff   32767
fioff          0xf7b5b610       -139086320
...
...

まとめると


通常の計算結果で端数が出ない浮動小数点の計算でも、機械の内部ではぴったり収まらないケースがあるということ。小数点は意外とムズカシイ... なので、解決方法として
  • 仕様としてなるべく切捨てを採用するよう上司に涙ながらに訴える
  • ceil(round($v, x))で小数点以下のどこで切り上げるか明確にする
  • 切上げの場合は、安易に掛け算とceilを利用しないで、足し算、引き算などで頑張る(やり方は分かりません)
  • Haskellのような分数と遅延評価を使える言語で頑張る(みんなにいやがられる)

ちなみにHaskell
Prelude> 15000 + (15000 * 8/100 :: Rational)
16200 % 1

みなさんceil関数をこんな感じで使ってる所ってない?..なんか気持ち悪いですね....ヒヤリハットです

最後に、消費税をもう今後上げない...無理でしょうけど

2014年4月14日月曜日

weakシンボルに時間をとられた

waekシンボル

ceil関数からを調べていたら
cuomo@karky7 ~ $ nm -D /lib64/libm-2.17.so | grep ceil
000000000001a810 i ceil
0000000000030220 i ceilf
0000000000039a70 W ceill
cuomo@karky7 ~ $
ceil関数を調べていてnmコマンドのWをみて、「これ何だっけ?」と半分忘れかかっていたので脱線...
weakシンボルとは書き換え可能な変数、または関数名(関数のエントリアドレス)で、同名称が非weakシンボルで名前解決される場合はそちらが利用される位しか覚えていませんがあってるかどうかわからない。 でこんな感じ、
int main ()
{
  test();
  return 0;
}
#include 
#include 
extern long double ceill(long double x) __attribute__ ((weak));

void test(void)
{
  if (ceill) {
    printf("%Lf\n", ceill(15000 * 1.08));
  } else {
    printf("ceillなんて実装してねぇし\n");
  }
}

ビルド方法


ceil.so共有ライブラリを作成し、それをmain.cへリンクさせる
cuomo@karky7 ~ $ gcc -fPIC -shared -o ceil.so ceil.c
cuomo@karky7 ~ $ gcc main.c ./ceil.so
これを普通に実行してみると
cuomo@karky7 ~ $ ./a.out
ceillなんて実装してねぇし
cuomo@karky7 ~ $
これはceill関数にリンクできていないから呼び出ない、これをこうすると
cuomo@karky7 ~ $ LD_PRELOAD=/lib64/libm.so.6 ./a.out
16201.000000
cuomo@karky7 ~ $
LD_PRELOADでlibmをしてするとちゃんとceillがリンクされて実行できる。

まとめると


GCC GNU拡張のアトリビュート__attribute__でweekを使うと、リンク時に-lmを指定しなくてもリンクできるようになる。
extern long double ceill(long double x) __attribute__ ((weak));
もしこれを書かないと、-lmで明示的にリンクが必要になる
cuomo@karky7 ~ $ gcc -fPIC -shared -lm -o ceil.so ceil.c
さらに、実行時に名前解決できない場合、そのシンボルが0で初期化されて、コード(a.out)自体は実行が可能になる、そうじゃないと実行時のリンクエラーで、コード(a.out)の実行ができない。 という、よくわからない説明ですが、そういう風になっていると思います。

2014年4月9日水曜日

gitでsshの公開鍵認証でハマる

公開鍵認証でSSH越しのgit cloneにハマる


意外とやってみてチョットハマったのでメモ、SSHの鍵認証を利用した時のgitでcloneしようと試したのですが、色々試したものの以下のメッセージがでてcloneできない


まず、普通の鍵認証でsshしリモートのサーバーへログインできることが前提です
cuomo@karky7 ~ $ ssh -i ~/.ssh/identkey user@123.456.789.999
Enter passphrase for key '/home/localuser/.ssh/prikey':
user@host ~ $

「Permission denied (publickey).」公開鍵が違うじゃねぇーか的なメッセージでてcloneできない
cuomo@karky7 ~ $ git clone ssh://user@123.456.789.999/home/user/mou_muridesu.git
Cloning into 'mou_muridesu'...
Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
cuomo@karky7 ~ $

ssh越しにgitが出きるように設定する


どうやらgitでsshを利用する際に特定の秘密鍵をしてする方法があるらしく.sshディレクトリ以下のconfigファイルをおくというもの
cuomo@karky7 ~ $ pwd
/home/user
cuomo@karky7 ~ $ cat .ssh/config
Host remotehost
    HostName  123.456.789.999
    Port      22
    User      user
    IdentityFile  ~/.ssh/prikey
cuomo@karky7 ~ $
ここで注意することは、ファイルとディレクトリのパーミッション

  • .ssh ・・・ 0700
  • config ・・・ 0600

にしておいてください、Hostはエイリアスなので自分のわかりやすい接続名をつけてください、あとはわかりますよね。

git cloneしてみる


設定ファイルを置いたらcloneしてみる、ここでホストの部分はエイリアス名を指定する。
cuomo@karky7 ~ $ git clone ssh://remotehost/home/user/mou_muridesu.git
Cloning into 'mou_muridesu'...
Enter passphrase for key '/home/user/.ssh/identkey':
remote: Counting objects: 294, done.
remote: Compressing objects: 100% (224/224), done.
remote: Total 294 (delta 121), reused 160 (delta 59)
Receiving objects: 100% (294/294), 3.02 MiB | 584.00 KiB/s, done.
Resolving deltas: 100% (121/121), done.
Checking connectivity... done
cuomo@karky7 ~ $
cloneできました、configファイルを置くとその他のssh接続に影響がある場合がございますのでご注意ください、その他、環境変数 GIT_SSHなるものがありますが調べておりません。

案外面倒...

2014年4月8日火曜日

Gentoo勉強会に行ってきました - 2014年4月5日(土)

はじめてGentoo関係の勉強会に参加しました

2014年4月5日の土曜日に、芝エクセージビルディング5階のミラクルリナックスの会場にてGentoo勉強会が開かれるとのことで楽しみにしていました。

第1土曜日は Gentoo bug day という設定になっているというコンセプトのもと定期的に開催していくとのことで、まったく知りませんでした、今後も参加していきたいと思います。




発表内容

@matsuu さんの発表

Gentoo界隈では知らない人はいないと思いますが @matsuu さんの発表は、「Gentooプリインストールなノートパソコンの話」ということで、最近ハワイに行って買ってきたChromebookをネタにした発表で、ChromebookがGentooベースでできていて、emergeがうてるというおもしろい発表でした。

まず、
  • Chromebookはsamsungがいいらしい
  • ChromebookはGentooベース
  • Developer modeからubuntuを入れられる
など、おもしろい情報でした、developer modeにするにはchromeウエブストアからcrosh windowをインストールし、何やらコンソールからshellと入力すると、いつものGentooカラーのターミナルが起動し、emergeコマンドが実行できパッケージが入れられるようになります。チョットビックリでしたね、しかし、注意が必要でemerge出きるのはgoogle提供のバイナリパッケージだけらしいです。
自分は、Chromebookを持っていないので実際に試せないのですが、持っている方は是非お試しください。





@naota さんの発表

Gentoo developerで有名な @naota さんの発表で、あのみんなが利用するGenTwooシステムの gentooinstallbattle の生い立ちなどの発表でした。GenTwooとはemergeしたユーザーのパッケージ情報をtwitterに自動的に流すという斬新なソーシャルコンパイルシステムです。このビックデータを解析すれば、今後のパッケージのトレンドなんかを評価できたりと、非常に多方面に渡って期待できるシステムです。

皆さんもGentooをいれて、GenTwooを一緒にやりましょう。

GenTwoo: Social Compiling はこちらです


@aliceinwire さんの発表


Gentooのパッケージングシステムebuildとoverlayについてのお話でした。各コマンドのお話や外部リポジトリを簡単に取り込むことができるoverlayのlaymanなどの使い方のお話など、自分自身もSLOTについて質問させて頂いたりと、有益な情報を頂きました。僕も意外と知らなかったのですが、enalyzeコマンドなるものがありまして、こんな感じで実行しますと指定されたUSEフラグを使用しているパッケージリストが取得できます、USEフラグからパッケージを検索できます、これは便利で知りませんでした


karky7 ~ # enalyze analyze -v use
 Flag                                 System  #pkgs   cat/pkg-ver
+24bpp .............................. .......     1 net-libs/libvncserver-0.9.9-r1
+X .................................. default    80 app-editors/emacs-24.3-r2
                                                    app-editors/xemacs-21.4.22-r2
                                                    app-i18n/ibus-1.5.2
...
...
                                                    www-client/links-2.8-r1
                                                    x11-libs/libpciaccess-0.13.2
-zlib ............................... .......     1 sys-apps/pciutils-3.2.0
===================================================
Total number of flags in report = 455
Total number of installed ebuilds = 1918

karky7 ~ #
意外と使ってるけど知らない部分があったりと発見が多かった気がします、Gentooは奥が深いデスですね、さらにお勉強になりました。


最後に


最後に--mooです

karky7 ~ # emerge --moo
これは、是非インストールして自分で確かめてみてください 笑...