curl_multiの結果取得方法(HTTPエラーコードならびにL2〜L4でのエラー理由など)

cURLのマルチハンドルにおける、各ハンドルごとの通信内容の結果取得方法についてです。
データ本体ではなく、HTTPコードや通信時間、エラー理由(名前解決失敗やネットワーク接続失敗やconnection refusedなどといった、MACレイヤやTCP/IPレベルでの理由)の取得方法になります。

PHPの公式ドキュメントがクソわかりづらかったので、まとめました。

その1。
HTTPコードや通信時間などについては、curl_getinfo がそのまま使えます。
PHP: curl_getinfo – Manual

その2。
cURLが返すエラー理由については、curl_errorは使えません。curl_multi_infi_readの結果で取得できます。
PHP: curl_multi_info_read – Manual
参考:PHP: curl_error – Manual

なお、cURLのエラーコードについてはこちらに説明があります。
libcurl – Error Codes

curl_multiの使い方については以下のブログが詳しいのでそちらに説明を譲ります。
APIとの通信効率をよくする実装例(1) curl_multi – Yahoo! JAPAN Tech Blog

以下は実際に取得するためのサンプルコードです。
いろいろ端折ってます。

// make multi handle
$mh = curl_multi_init();

// make each handle (同時実行数分だけ行う)
$ch1 = curl_init() ;
curl_setopt( $ch1 , OPTION , VALUE ) ;         // option はここで設定
curl_multi_add_handle( $mh , $ch1 ) ;
$ch2 = curl_init() ;
curl_setopt( $ch2 , OPTION , VALUE ) ;         // option はここで設定
curl_multi_add_handle( $mh , $ch2 ) ;
$ch3 = curl_init() ;
curl_setopt( $ch3 , OPTION , VALUE ) ;         // option はここで設定
curl_multi_add_handle( $mh , $ch3 ) ;
    /* 途中省略 */
// ここまで each handle 分くりかえす
$mchary = array( $ch1 , $ch2 , $ch3 /* 中略 */ ) ;

// execute 
do {
    $mr = curl_multi_exec( $mh , $active ) ;
} while( $mr == CURLM_CALL_MULTI_PERFORM );

// get result 
$curlinfoary = array () ;
while( ( $cary = curl_multi_info_read( $mh ) ) != FALSE )   
{
    /* 1回の実行で1つのハンドル($chN)しか取得できないので注意 
     * $cary['handle'] ... curl_init で取得したハンドル 
     * $cary['result'] ... 結果コード
     */
    $curlinfoary[] = $cary ;

}

// get each handle results
foreach ( $mchary as $lch )
{
     /* content本体 */
     $content = curl_multi_getcontent($lch);
     /* info data */
     $infodata = curl_getinfo($c) ;     // curl single系のものをそのまま使えます
     /* どんな内容が得られるかは、 curl_getinfo のドキュメントを参照すべし */
     $httpconde = $infodata['http_code'] ;
     $tttime    = $infodata['total_time'] ;
     $ftime     = $infodata['filetime'] ; 
     /* 各ハンドルの result(エラーコード) 取得 */
     $rh = -1 ;
     foreach ( $curlinfoary as $cj )
     {
         if ( $cj['handle'] === $lch ) 
         {
              $rh = $cj['result'] ;
              break ; 
         }
     }
     /* $rh の値は、cURLのエラーコード(CURLE_*)になります。
        $rh に -1 が入ってるわけがないので、今回はそのまま強行します
       (念のためチェックはしたほうがいいかも?) 
      */
     curl_multi_remove_handle( $mh , $lch ) ;
}

L2〜L4で失敗した詳細の理由を欲しいとかいう場面は滅多にないと思いますが、どうしても原因がわからずに詰んでしまったときのデバッグのための手助けにはなると思います。

Fukuoka Perl Workshop #24 行ってきた(あと、自分の知ってる昔話)

行ってきました。
Fukuoka Perl Workshop #24 YAPC::Asia レポート 2013

そういえば、YAPC::Asiaをやるって知ったのが、ちょうど千葉に行くその日の朝だったんだよなあと。(笑)


YAPC::Asiaの話をきいて。
来年は是非都合付けて参加したいなと思いました。
と……その前に。


懇親会でみんなノリノリでありました。

イベント参加して思ったこと。
Perl歴はアホみたいに長いのですが(たぶん1993〜4年あたりから…だから、20年近くいってるねwww。途中に若干ブランクはありますが…)、ひたすらレガシーなPerlしかいじってこなかったので、もっとモダンなPerlについて知らないとアカンなあ、ということでした。
次回までには時間作っていろいろやってみようかなと。

ちなみに。
CGIよりもfmlを使ったのが最初でしたね。
まだバージョン4だった頃だったよねと思ったらやっぱりそうでした。
Perlの歴史 Perl 1,2,3,4
このスライドを見ててなつかしくなっておりました。

第04回 福岡Debian勉強会 しゃべってきた ( #fukuoka_debian )

第04回 福岡Debian勉強会

というわけで今回はしゃべるほうでの参加となりました。

1番目、自分(爆)

しょっぱなでした(笑)
無線LANのおはなしですが、今回はカーネルまわりでのおはなしでした

無線LANデバイスについて(kernelレベル) from Yuki Uchikoba

mac80211とかnl80211とか、あとはWEとか、ドライバを野良ビルドするときの注意点とか。
そのへんの話をしてみました。

2番目の桜井さん、3番目の河合さんの、OpenBlocksのおはなし。

OpenBlocksは自分も欲しいなあと思っておったのですが、実際に実演してるのを見て、ますます興味がわきました。

4番目、下川さんの、zshのおはなし

zsh とわたし from Toshihiko Shimokawa

すごくよかった。というか濃かった。
ちなみに参加者の約半数がzsh使いでした。続いてbash、だったかな?
自分もzsh使っているわけですが(zsh + screen で使いやすいshell環境にしてみた。)、「こんなの知らないYo!」ってことばかりでしたね。

5番目、小室さんの、「大統一Debian勉強会」のレポート(写真)

6月29日に東京でありました、「大統一Debian勉強会」のお話でした。

そういえば私も参加してました。確かに面白かったねーと。
(参考:週末、千葉と東京に行ってた
あ、ブログ書くといいながら書いてなかった!うはーごめんなさいーー!

まとめると

濃かった。
なんというかレベルの高さが半端なかったです、はい。

主催の小室さん山田さん、そして参加したみなさん、おつかれさまでした&ありがとうございました!!

私のLinux環境がまともに動かないのはどう考えてもSELinuxが悪い!

インストールしたばっかりのCentOSで、特にWebまわりでな〜んか動きがおかしいぞ、ってときは、大抵、SELinuxの設定でおかしなことになっていたりします。

まず確認する

getenforce を実行してみて、SELinuxがどんな状態になってるかを確認する
ハマってるときは大抵 Enforced になっております。
setenforce で Permissive にしてあげて一度様子を見るか(使いたい場合)、/etc/selinux/config で、SELinux=の引数を「Disabled」にして再起動か(「お前に用はない!」ポリシーの場合)、いづれかをします。

ちなみに、「Enforced」「Permissive」「Disabled」の3つがありますが、それぞれ

  • Enforced … ポリシーを適用し、違反があったら拒否する
  • Permissive … ポリシーは適用するが、違反がログに残すだけで、見逃す
  • Disabled … ポリシー適用もしない(完全にオフ)

でも「切ったら負け」の場合

わかりやすい解説をしてるサイトがなかなかなくて。
いろいろ探してみたら、ここにたどりつきました。
第一人者がやさしく教える新SELinux入門 – 第一人者がやさしく教える新SELinux入門—目次:ITpro
ユーザー権限に加えて、「ドメイン」×「タイプ」×「許可アクセス」で制限するのね。

ls -lZ で、ファイル/ディレクトリに対して、どういうタイプが設定されているかを見ることが出来ます。
ls -lZの結果
これを確認したかったがために、久々にCentOSのVMを起動したのは内緒です。
ちなみにこのVM、Squidで透過proxyでいろいろやりたかったときに実験で作ったやつでした。
壁紙は、Squidだけにイカ娘です ;-)

まとめ

もう少し勉強しないとあかんなーってこと。
さきほどのサイトを読みつつ自分でいじればわかりそうな気がしてきました。

とりあえず。
「私のLinux環境がまともに動かないのはどう考えてもSELinux(をまともに設定してない自分)が悪い!」
ってことで。

もう少し理解できたら続編を書くかもしれません。

表題の元ネタ

ええ……「私がモテないのはどう考えてもお前らが悪い!」です。
いまアニメでやってますが1話までしか見てなかったり…
TVアニメ「私がモテないのはどう考えてもお前らが悪い!」 – ガンガンONLINE -SQUARE ENIX-

zsh + screen で使いやすいshell環境にしてみた。

いままではbashでしたが、zshにしたのは先日の福岡Debian勉強会で影響されたからです。(笑)

以下の要望を満たしたかったのでいろいろいじってみました。

  • いまいるホストとttyを把握(表示)したい
  • いま走ってるコマンドを表示したい(tail -f hogelog とか同時に走らせてわからなくなるので)
  • 走ってないとき(コマンド待ち)のときはそうとわかるようにしたい

結果、以下のようなかんじになりました。

.screenrc

escape ^Tt

#画面下部に起動ウィンドウ名を出す
shelltitle "$ |zsh"

hardstatus alwayslastline "%{= Gk}[%m/%d %02c]%{= Mw}%l%{= BW}%n:%H%{= Wb} %t"

#起動時にでるメッセージを表示させない
startup_message off 

# ビープを鳴らさない
vbell off 

shelltitleを設定するとことと、タイトルは %t で出すってことかな。
(ちなみにescape は Ctrl-Tに変更してあります)

.zshrc

PROMPT='%B%F{blue}%n(%m:%l)%F %F{yellow}%(3~|.../|)%2~%F{red} %# %b%f%k'  

case "${TERM}" in
screen*|ansi*)
        preexec()
        {
                echo -ne "\ek${1%% 2%% *}\e\\"
        }
        precmd()
        {
                echo -ne "\ek$(basename $SHELL) :::: waiting your command ... > (:3[___]\e\\"
        }
        ;;
esac

実行されるときにpreexec()、戻ってくるときにprecmd()が呼ばれますのでそれをひっかけます。
echo -ne “¥ek〜¥e¥¥” でウインドウタイトルの変更。
ポイントはこんなところでしょうか。

ただ。
{1%% 2%% *}であってるのか自信がない…。

screenを起動するとこんなかんじ。
2013022501

コマンドを実行中はコマンドを表示(例では top コマンド)
2013022502

引数もちゃんと表示されます。sudoしてもちゃんと出る。
2013022503

コマンドが終わって戻ってきたらちゃんと待機表示に変わります
2013022504

以下サイトを参考にしました。

福岡Debian勉強会(2回目)行ってきた ( #fukuoka_debian )

そんなわけで、行ってきました。
福岡Debian勉強会 2回目 on Zusaar

実際に人に会って、いろいろと話をきいたりツッコミ入れたりwってやっぱり大事だなと改めて思ったり。
いろいろと自分の知らなかった肝心なところを知ることをできたりと、とても有意義でした。
初心者から中級者まで幅広く話題に参加できることでもすごく有意義だったのではと思います。

あと、今回の参加ルールで、

乾燥系お菓子を一つ持ってくる事。

ということで、先週鹿児島に(用事あって)帰省してたので「これは、(博多駅あたりで買えそうなメジャーどこじゃなくて)地元でしか買えないようなマイナーなお土産を持って行くしか!」ということで、地元限定のものを買ってもっていきました。
結果。
2013012614
面白いことになりました。
まさか「かすたどん」がくるとは思いませんでしたw
こういうルールも面白いよねと改めて思いました。これは是非やるべきw
(ただ、持ち込みすぎて余るリスクをどうするか…ですね!)

帰宅して、(今回の勉強会を受けて)自分のMacBook Proに入れてあるDebian(squeeze)をいろいろ弄り始めましたw
2013012611

あ、ホスト名(自宅サーバならびに仮想サーバなど含め全部)の命名ルールですが、ここ数年は「鉄道の特急・急行・新幹線の名前」であわせてます。
Debian走らせてるVMの「tsubame」は、九州新幹線の「つばめ」からとっております。
2013012612

最後に謝辞。
主催者・参加者のみなさん、ならびに会場提供してくださいましたpaperboy&co.福岡支社様、本当にありがとうございました!

RADIUSサーバをたててみた…ときのひっかかったポイント

FreeRADIUSを使って立てたので、個人的メモ。
設定のやりかたとかは他に書いてあるのでそっちを見てね

最終目的は、EAP-PEAP/EAP-TTLSで認証通すとこ。

(証明書作成、FreeRADIUSをインストールしてとりあえずユーザー作ったよーというレベルまで)

1.ローカルでの接続テスト

radtestを使います。

radtest rikka@chu2byo.example.com jyaoushingan localhost 0 testing123

テストするとこんなかんじに結果が出てきます。

Sending Access-Request of id 123 to localhost port 1812
	User-Name = "rikka@chu2byo.example.com"
	User-Password = "jyaoushingan"
	NAS-IP-Address = xxx.xxx.xxx.xxx
	NAS-Port = 1812
	Message-Authenticator = 0x00000000000000000000000000000000
rad_recv: Access-Accept packet from host localhost port 1812, id=123, length=20

正しいパスワードを入れてAccess-Acceptになれば、usersとproxy.confの設定は問題なし。
念のため間違ったパスワードを入れると

radtest rikka@chu2byo.example.com darkflamemaster localhost 0 testing123

こんなかんじにRejectになる。

rad_recv: Access-Reject packet from host localhost port 1812, id=244, length=20

間違ったパスワードできちんとRejectされれば問題なし。

だが、正しいパスワードでAccess-Rejectになれば、user@realmとpasswordが一致してないので、そのへんを調べてみるべし。

2.リモートからのテスト

localhostを相手ホストにするだけ。

radtest rikka@chu2byo.example.com jyaoushingan remotehost 1812 testing123

出てくる結果は同じなので省略
Access-AcceptになればOK、Access-Rejectになればどっかおかしい。
たぶんcients.confのclientの設定がおかしい。

3.EAPをテストする

radtest/radclientではEAPが使えないので、WPA supplicantにあるeapol_testを使います。
この時点で、Linux限定になっちゃいます。
WPA supplicantを普通にmakeしても生成されないので注意。
CONFIG_EAPOL_TEST=y にして make eapol_test する。
参考:Deploying RADIUS: EAP Testing
なお、「/usr/bin/ld : cannot find -lnl」と出る場合は、libnlを入れてから再度 make eapol_test。

$ aptitude install libnl2 libnl2-dev

eapol_test と同じディレクトリに eapoltest.conf を作成

network={
    key_mgmt=WPA-EAP
    eap=PEAP
    identity="rikka@chu2byo.example.com"
    password="jyaoushingan"
    phase2="auth=MSCHAPV2"
    eap_workaround=0
}

設定ファイルを書いたら、

$ ./eapol_test -a [remote] -p 1812 -s [client secret] -A [local IP] -M [local MAC] -n -c ./eapoltest.conf

通信の詳細が一気に表示されます。
TLSトンネリングなのか、eap.conf内の設定の問題かが、ほぼわかると思います。
これでわからなければ、RADIUSサーバをdebugモードで起動。

# freeradius -X

なお、Windowsで接続した場合「EAP session for state 0x******* did not finish! Please read 〜」とメッセージが出る場合、オレオレ証明書を使ってる場合だと思いますので、「保護されたEAPのプロパティ」で「サーバの証明書を検証する」をオフにします(またはオレオレルート証明書等のインストールが必要)

参考にしたもの

iptablesのログフォーマットと内容について

iptablesで -j LOG でsyslogに出力した時のそれぞれのフィールドについてわからないことが多かったので調べました。
どこにも詳しい説明がなかったので、最終的にLinuxのカーネルソースで確認しました。
kernel versionは、2.6.34.13 で確認しています。
net/ipv4/netfilter/ipt_LOG.c で生成しています。

今回は –log-ip-options , –log-tcp-options をつけたものについては省略してます。
(ソース見れば書いてあるのでわかるだろうってことで)

Oct 30 12:34:56 hoge kernel: [xxxxx.xxxxx] IPTLOG_FW : IN=eth1 OUT=eth0 MAC=aa:bb:cc:dd:ee:ff:11:22:33:44:55:66:08:00 SRC=192.168.201.1 DST=172.16.101.30 LEN=118 TOS=0×00 PREC=0×00 TTL=254 ID=3120 DF PROTO=TCP SPT=3300 DPT=80 WINDOW=1460 RES=0×00 ACK PSH URGP=0

4つのパートにわかれています。

一番目

Oct 30 12:34:56 hoge kernel: [xxxxx.xxxxx] IPTLOG_FW :

syslogの先頭領域(共通)。
‘IPTLOG_FW’ の部分は、iptablesの引数 –log-prefix で指定できます。

二番目

IN=eth1 OUT=eth0 MAC=aa:bb:cc:dd:ee:ff:11:22:33:44:55:66:08:00

MACレイヤ(L2)。
MACアドレスは先頭6octetがethポート(つまり、宛先の)MACアドレス、次の6octetが送信元MACアドレス、次の2octetはイーサネットタイプです。IPの場合0800になります(RFC1340のpage 53「ETHERNET NUMBERS OF INTEREST」に記載あり)。
この値は、skb_mac_header ( ) が返したものをそのまま出しています。

include/linux/skbuff.h

#ifdef NET_SKBUFF_DATA_USES_OFFSET
typedef unsigned int sk_buff_data_t;
#else
typedef unsigned char *sk_buff_data_t;
#endif

struct sk_buff {
   /* 中略 */
        sk_buff_data_t          mac_header;
   /* 中略 */
        unsigned char           *head,
}

static inline unsigned char *skb_mac_header(const struct sk_buff *skb)
{
        return skb->head + skb->mac_header;
}

参考:連載:詳説 TCP/IPプロトコル 第7回 イーサネット(その2) イーサネットのフレーム構造 — 3.イーサネットのフレーム・フォーマット

三番目

SRC=192.168.201.1 DST=172.16.101.30 LEN=118 TOS=0×00 PREC=0×00 TTL=254 ID=3120 DF PROTO=TCP

IPレイヤ(L3)。
IPについては詳しくはRFC791を参照されたし。

  • SRC : ソースIPアドレス
  • DST : デスティネーションIPアドレス
  • LEN : IPパケット長
  • TOS : IPヘッダ TOSフィールドの値
  • PREC : IPヘッダ TOSフィールド内、PRECEDENCEの値
  • TTL : IPヘッダ TTLの値
  • ID : IPヘッダ IDの値
  • DF : IPヘッダ Flag の DFビット(Don’t Fragment)が立っている場合
  • PROTO : プロトコル(TCP,UDPなど)

該当ソースは下記のようになっております。(後半、省略してます)

        /* Important fields:
         * TOS, len, DF/MF, fragment offset, TTL, src, dst, options. */
        /* Max length: 40 "SRC=255.255.255.255 DST=255.255.255.255 " */
        printk("SRC=%pI4 DST=%pI4 ",
               &ih->saddr, &ih->daddr);

        /* Max length: 46 "LEN=65535 TOS=0xFF PREC=0xFF TTL=255 ID=65535 " */
        printk("LEN=%u TOS=0x%02X PREC=0x%02X TTL=%u ID=%u ",
               ntohs(ih->tot_len), ih->tos & IPTOS_TOS_MASK,
               ih->tos & IPTOS_PREC_MASK, ih->ttl, ntohs(ih->id));

        /* Max length: 6 "CE DF MF " */
        if (ntohs(ih->frag_off) & IP_CE)
                printk("CE ");
        if (ntohs(ih->frag_off) & IP_DF)
                printk("DF ");
        if (ntohs(ih->frag_off) & IP_MF)
                printk("MF ");

四番目

SPT=3300 DPT=80 WINDOW=1460 RES=0×00 ACK PSH URGP=0

TCPレイヤ(L4)。
TCPについては詳しくはRFC793を参照されたし。

  • SPT : ソースポート番号
  • DPT : デスティネーションポート番号
  • WINDOW : TCP Window
  • RES : Reservedの値
  • ACK , PSH , RST , SYN . FIN : Control Bitsのそれぞれに対応
  • URGP : Urgent Pointerの値

該当箇所のソースは下記の通りになってます。(一部省略)

                /* Max length: 20 "SPT=65535 DPT=65535 " */
                printk("SPT=%u DPT=%u ",
                       ntohs(th->source), ntohs(th->dest));
/* 中略 */
                /* Max length: 13 "WINDOW=65535 " */
                printk("WINDOW=%u ", ntohs(th->window));
                /* Max length: 9 "RES=0x3F " */
                printk("RES=0x%02x ", (u8)(ntohl(tcp_flag_word(th) & TCP_RESERVED_BITS) >> 22));
                /* Max length: 32 "CWR ECE URG ACK PSH RST SYN FIN " */
                if (th->cwr)
                        printk("CWR ");
                if (th->ece)
                        printk("ECE ");
                if (th->urg)
                        printk("URG ");
                if (th->ack)
                        printk("ACK ");
                if (th->psh)
                        printk("PSH ");
                if (th->rst)
                        printk("RST ");
                if (th->syn)
                        printk("SYN ");
                if (th->fin)
                        printk("FIN ");
                /* Max length: 11 "URGP=65535 " */
                printk("URGP=%u ", ntohs(th->urg_ptr));

perlでのsignal処理

$SIG で対応。

ループをCtrl-Cで抜ける場合、SIGINTが送られますので、$SIG{INT} に無名サブルーチンをセットすればOK。

プログラムは、こんなかんじになります。

#!/usr/bin/perl

@nonosirare = ( 
                "くず",
                "ばーか",
                "すけべ",
                "ばか",
                "しんじらんない",
                "あ゛ん?",
                "おたんこなす",
                "だいっきらい",
                "いいかげんにしたら",
                "モジモジしてキモイねー",
                "はげろ",
                "なにえらそうなこといってんの",
                "でてって",
                "くず",
                "むしんけー",
                "は?",
    );

local $SIG{INT} = sub { $l = 0; };         # localはなくても大丈夫?

$c = 0 ;
$l = 1 ;
while($l)
{
    $j = $nonosirare[ int(rand($#nonosirare + 1)) ] ;
    print $j ;
    $c ++ ;
}

print "\n\n" ;
printf( "%d回罵られました。ありがとうございます。\n" , $c);

実行し、Ctrl-CしてSIGINTを送ったり、kill -INT (pid) してSIGINTを送ったりすると、ループから抜けてループを回した回数が表示されます。
一番下に回数が出てる

Windows Server 2012 評価版をVMwareに入れてみることにした(挫折編)

Windows Server 2012の評価版が出たのでダウンロードして、ちょっと遊んでみることにしました。
Windows Server 2012 | マイクロソフト サーバー & クラウド プラットフォーム

そんなわけで、VMware Fusion 3に入れてみます。(4に更新忘れてた、そして今は5が出てる)
:(
:(
……はい、青画面です。

メッセージを見ると、

If you’d like to know more , you can search online later for this error: HAL_INITIALIZATION_FAILED

「HAL_INITIALIZATION_FAILED」絡みで検索かけてみたら結構出るなー
Windows8でも出る現象のようですね。

まあ、VMware Fusionのバージョンが古いからぼちぼち5にあげてみるかなーというかんじです。
(話はそれからだ状態)

VMware Fusionの3自体が既にサポート終了らしいので、その点も問題かもしれません。
解決策わかりましたら新たに記事を書きます。

今日のクソコード

FizzBuzzはこれまで不要だったとしてもこれからは必要 – きしだのはてなを受けて。

いままでだと確かにFizzBuzzが「具体的に」SIの現場でどう役に立つかっていう話をしたがるよねえと。そんなことよりも金利計算とかそういった実務直結のプログラムが書ければいいんだし(実際、汎用機で使われてる言語だとFizzBuzzの書き方を知らなくてもそういうのが書けた記憶がある)。

そしてそんなこと考えてたりしたら、きっとこういうコード書いてくる人も出てくるんだろうなあと頭に浮かんでしまい(苦笑)、実際に書いてみたら…

<?php
$i = 1 ;
while(1)
{
  echo $i ."¥n" ; $i++ ;        //  1 + 15n
  echo $i ."¥n" ; $i++ ;        //  2 + 15n
  echo "fizz¥n" ; $i++ ;        //  3 + 15n
  echo $i ."¥n" ; $i++ ;        //  4 + 15n
  echo "buzz¥n" ; $i++ ;        //  5 + 15n
  echo "fizz¥n" ; $i++ ;        //  6 + 15n
  echo $i ."¥n" ; $i++ ;        //  7 + 15n
  echo $i ."¥n" ; $i++ ;        //  8 + 15n
  echo "fizz¥n" ; $i++ ;        //  9 + 15n
  echo "buzz¥n" ; $i++ ;        // 10 + 15n
    if ( $i == 100 ) break ;    // 10 + 15*6 = 100 なのでここで終了
  echo $i ."¥n" ; $i ++ ;       // 11 + 15n
  echo "fizz¥n" ; $i ++ ;       // 12 + 15n
  echo $i ."¥n" ; $i ++ ;       // 13 + 15n
  echo $i ."¥n" ; $i ++ ;       // 14 + 15n
  echo "fizzbuzz¥n" ; $i ++ ;   // 15 + 15n
}
?>

クソというよりはSAN値直葬のほうがふさわしいか。
というか、書いてる本人が既にSAN値直葬されかけたし。(笑)
着眼点は決して悪くはないけど、そこは人間じゃなくてプログラムがやってくれるべきとこだってこと。

そして。
ここまで書いていて、このやりかたが何か似てることに気づいたのですが、
それの正体が「Excel方眼紙」だったのは、内緒にしておきます :D

そして最後に気に入ってるサイトを紹介して終了。
ウンコード・マニア

Windows XP SP3適用済みブートCDの作成について

Windows XPで、どうしてもキーボードがきかなくなる事象が発生。
症状としてはこう。

  • 電源投入〜BIOS画面ではちゃんとキーボードがきく(ちゃんと反応する)
  • Windowsが起動したら全くキーボードがきかない(全く反応がこない)
  • セーフモードで起動しても全くキーボードがきかない
    • F8連打〜セーフモード選択は全く問題なし

Windows XPではありがちな症状らしい。
Windows XP 回復コンソール: Automatic

しかたないからWindows XPのCD-ROMを押し入れからひっぱり出してきて、早速ブートしてみると…
青画面Σ( ̄□ ̄;;;;)

STOP: 0X0000007E (0XC0000005, 0XF748E0BF, 0XF78DA208, 0XF78D9F08)
pci.sys – Address F748E0BF base at F7487000, Datestamp 3b7d855c

なんでや?と思って検索したら、同じ症状・全く同じメッセージでこけた事例が。

using an xp pro sp1 disk made it work… before i was using just xp pro no sp1… tricky

「XP Professional SP1適用したやつでブートしな!」というわけで、
早速作ることに。

作り方はWell-Knownだと思うけどやったことなかったので一応書いておく。

  1. Windows XPのCD-ROMをCD-ROMドライブに入れる
  2. 適当なフォルダを1個作って、内容を「全部」コピーする(完了してもまだ取り出さない)
  3. Windows XP Service Pack 3(IT プロフェッショナルおよび開発者用 ネットワーク インストール パッケージ)をダウンロードしてくる
  4. 「コマンドプロンプト」から、WindowsXP-KB936929-SP3-x86-JPN.exe /xを実行し、ファイルのみ展開
  5. コマンドプロンプトで、SP3を展開したディレクトリへ移動し、i386¥update¥update.exe -s:《CD-ROMの内容をコピーしたディレクトリ》 を実行。『統合インストールが正常に完了しました』と出れば成功。
  6. CDRWIN(というシェアウェア。レジストしてなくても問題なし)を起動し、「ディスクイメージ+Cue Sheet」を選び、Windows XPのCD-ROMのイメージを読み込む。「なんとか.iso」と「なんとか.cue」というファイルができる。
  7. CDmage(というフリーソフト)を使ってブートイメージを吸い出す。boot.imgというファイルに保存。
  8. CDRWINでISOイメージを作成する。
    • 《CD-ROMの内容をコピーしたディレクトリ》をファイルバックアップ・リストへ
    • ファイルシステムは「ISO9660」を指定
    • 「隠しファイルを含む」「ロングファイル名」「システムファイルを含む」にチェックを入れる。
    • 拡張オプション指定の「Bootable Disc」で、Make Bootable Discをチェックし、イメージファイルを選択、Developer Nameは「MicrosoftCorporation」、Load Sector Countに「4」を指定。
    • 拡張オプション設定の「ISO9660」で、以下にチェックする「Generate Joliet compatible data structures」「ISO Level 1」「STANDARD」「Allow Directory depth of more than 8 levels」「Allow more than 64 characters in Joliet names」「Do not add “:1″ version number to filenames」 ※ここ重要。ここをミスすると「CDBOOT: couldn’t find NTLDR」と怒られ起動しない。
  9. できあがったISOイメージをVMに食わせてブートするか確認してみる

VM使うのは、いちいち焼かなくてもチェックできるから。便利なものです。

参考:

おまけ。今回は使わなかったけど今後使えそう。

MySQL Casual Talks @gumi福岡、いってきた( #mysqlcf )

先月下旬にありましたが、記事に書くのは今頃になってしまいました。ごめんなしあ〜〜〜!
(今回は聞くだけ側でしたw)

twitterに投げた内容は、以下にまとめておきました。
MySQL Casual Talks @gumi福岡 個人的記録まとめ。 – Togetter

特に気になった話や記憶に残ったとこはこんなところかな

  • collationのはなし。→collationはutf8mb4にしましょう
  • HandlerSocketしゅごい
  • MySQLのバックアップについてあれこれ。ちゃんとリストアのテストも忘れずに!
  • パーティショニング
  • CVE-2012-2122を実際にやってみた
  • perl+MySQL使いいないの〜〜〜?(;_;)
  • もつ鍋_(゚ཀ゚」∠ )_ウマー

スライドのまとめはこちら(主催者さんとこ)にあります。
MySQL Casual Talks @gumi福岡を主催 & Talkしてきました – CubicLouve

そして。
主催の会場提供してくださったgumi様、ありがとうございました!

VirtualBoxのNATのIPアドレスを変更したい

VirtualBoxというVMを使うことになって。
ネットワーク設定で、衝突することがあったんですよね。
こんなケース。
(1)ネットワークインターフェイスを2つ以上使う
(2)かたっぽはNATで外に出て行きたい(10.0.2.0/24が割り当てられます)
(3)ローカルでは、10.0.0.0/8 を使いたい

はい、(2)に書いたとおり、VirtualBoxのNATは、10.0.2.0/24 を割り当ててくれます。
ですから、(3)の条件でぶつかってしまいます。

…うん。
『あのぉ、10.0.0.0〜10.255.255.255は、わたしが使っている IP アドレスですので勝手に使わないでください。』
ってやつですね :D

普通なら「(3)をなんとかしろ」なんですが、そうもいかないケースも多々ありまして。
ご心配なく。(2)を変更すればいいんです。

どうすれば変更できるか、ぐぐっても出てこなかったのですが、documentにちゃんと書いてありました。
VirtualBoxの、doc/UserManual.pdf の 9.11.1 に書いてあります。
NATのネットワークアドレスを、 172.24.0.0/24 にした場合、

VBoxManage modifyvm "VM名" --natnet1 "172.24.0/24" 

これでOKです。

PHP:cURLのコールバック

curl_setopt()の「CURLOPT_HEADERFUNCTION」と「CURLOPT_WRITEFUNCTION」の説明がわかりづらくて、かつどこにも説明してるサイトがなかったので自分でまとめてみました。

CURLOPT_HEADERFUNCTIONは、「ヘッダが読まれたときにコールバックする関数」を指定し、
CURLOPT_WRITEFUNCTIONは、「コンテンツが読み込まれた時に逐次コールバックされる関数」を指定します。
全部読み込んで一気に処理するのではなく、戻ってきた分を逐次処理して返す場合に有効。

<?php
set_time_limit(0);

$c = curl_init() ;
curl_setopt( $c , CURLOPT_URL , $url ) ;
curl_setopt( $c , CURLOPT_USERAGENT , $useragent ) ;
curl_setopt( $c , CURLOPT_COOKIE , $cookies );

// curl_setopt( $c , CURLOPT_RETURNTRANSFER , TRUE ) ; // 不要

curl_setopt( $c , CURLOPT_HTTPHEADER , $headers ) ;
curl_setopt( $c , CURLOPT_HEADERFUNCTION , hdcallback ) ;
curl_setopt( $c , CURLOPT_WRITEFUNCTION , wrcallback ) ;

$r = curl_exec( $c ) ;
curl_close( $c );

////////////////////////////// callback function

function hdcallback( $res , $response )
{
    $h1 = explode( "\r\n" , $response ) ;

    foreach( $h1 as $hout )
    {
        if ( $hout == "Transfer-Encoding: chunked" ) continue ;
        header( $hout ) ;
    }
    return strlen( $response ) ;
}

function wrcallback( $res , $response )
{
        echo $response ;
        ob_flush() ;
        return strlen( $response ) ;
}

まず、PHPじゃこういう使い方しませんものね。(偏見)

《追記》CURLOPT_RETURNTRANSFERを指定すると変なことになっちゃいましたので外しました。