michihide's blog

技術メモおよび雑感

phpdbgでコアダンプ

最近はもっぱら、CentOS 6.x/7.x では phpリポジトリとして https://webtatic.com/ を使わせてもらっています。ここは最新版への追随が早いので助かります。

ただ今回、phpdbg を使おうとしたらちょっとハマったのでメモ。 ちなみに OS は CentOS 7 です。

環境はこんな感じです。早速動かしてみました。

m-hotta@MYHOST:~$ rpm -qf /usr/bin/phpdbg
php56w-phpdbg-5.6.6-1.w7.x86_64
m-hotta@MYHOST:~$ phpdbg
[Welcome to phpdbg, the interactive PHP debugger, v0.4.0]
To get help using phpdbg type "help" and press enter
[Please report bugs to http://github.com/krakjoe/phpdbg/issues]
phpdbg> quit
Segmentation fault (コアダンプ)

コマンドに何を入れてもコアダンプ(詠み人知らず)。

しかたがないので、ソースを入れて探ってみます。

m-hotta@MYHOST:~$ sudo yum install php56w-debuginfo
m-hotta@MYHOST:~$ gdb -c core.26476
(gdb) bt
#0 0x00007faaf36437d1 in __strlen_sse2_pminub () from /lib64/libc.so.6
#1 0x00007faaf5b7bd76 in alloc_history_entry () from /lib64/libreadline.so.6
#2 0x00007faaf5b7bf7f in add_history () from /lib64/libreadline.so.6
#3 0x00007faaf6720102 in phpdbg_read_input (buffered=buffered@entry=0x0) at /usr/src/debug/php-5.6.6/sapi/phpdbg/phpdbg_cmd.c:773
#4 0x00007faaf6714252 in phpdbg_interactive () at /usr/src/debug/php-5.6.6/sapi/phpdbg/phpdbg_prompt.c:1003
#5 0x00007faaf64c4fab in main (argc=1, argv=0x7fff2540b3a8) at /usr/src/debug/php-5.6.6/sapi/phpdbg/phpdbg.c:1446
m-hotta@MYHOST:~$ sed -n '772,774p' /usr/src/debug/php-5.6.6/sapi/phpdbg/phpdbg_cmd.c
if (!(PHPDBG_G(flags) & PHPDBG_IS_REMOTE)) {
add_history(cmd);
}

readline 周りでおかしくなっているようです。 Github で issues をざっと見てみましたが、ピッタリ来るものはなさそう。 ただし以下の様なものがあるので、何らか readline がらみで因縁があるのかも。

github.com

諦めて phpdbg だけソースからビルドしてみることに。手順は以下のような感じ。

m-hotta@MYHOST:~$ > sudo yum groupinstall "Development Tools"
m-hotta@MYHOST:~$ > sudo yum install readline-devel libedit-devel libxml2-devel
m-hotta@MYHOST:~$ > cd /usr/local/src
m-hotta@MYHOST:/usr/local/src$ > tar xjf /tmp/php-5.6.6.tar.bz2
m-hotta@MYHOST:/usr/local/src$ > cd php-5.6.6/sapi
m-hotta@MYHOST:/usr/local/src/php-5.6.6/sapi$ > git clone https://github.com/krakjoe/phpdbg
m-hotta@MYHOST:/usr/local/src/php-5.6.6/sapi$ > cd ..
m-hotta@MYHOST:/usr/local/src/php-5.6.6$ > ./buildconf --force
m-hotta@MYHOST:/usr/local/src/php-5.6.6$ > ./configure --enable-phpdbg --with-libedit --with-readline
m-hotta@MYHOST:/usr/local/src/php-5.6.6$ > make -j8
m-hotta@MYHOST:/usr/local/src/php-5.6.6$ > sudo make install-phpdbg
m-hotta@MYHOST:/usr/local/src/php-5.6.6$ > sudo ln -s /etc/php.ini /usr/local/bin

ビルドに成功したら、/user/local/bin/phpdbg ができあがります。

m-hotta@MYHOST:~$ which phpdbg
/usr/local/bin/phpdbg
m-hotta@MYHOST:~$ phpdbg
prompt> help
phpdbg is a lightweight, powerful and easy to use debugging platform for PHP5.4+ It supports the following commands:(略)

これで落ちなくはなったけど、まだ readline が効いている気がしないので、ちょっと微妙。phpdbg の使い方はこれからです。

(2015.03.17 追記)

CentOS6 環境でやったところ、普通に
$ sudo yum install php56w-phpdbg
で入れた phpdbg でちゃんと動くし、readline も効いてます。
CentOS7 だけの問題なのかもしれません。
なお、phpdbg の簡単な使い方は こちらにまとめてあります。

鍼治療は痛くなくてオススメです。

うちの親父は、現役時代は盲学校高等部(高校に相当)の理療科教員として鍼灸マッサージを教えていました。理療科専門の教員免許としては、長崎県の第一号でした。当時長崎県内にあった鍼灸院は、そのほとんどが親父の教え子だったのではないでしょうか。鍼灸院は少なくとも当時、視力障害者にとって、およそ考えうるほぼ唯一の職業でした。 

退職後は、自宅を改造して鍼灸院をやっていました。喘息治療がうまいということで町医者から紹介されたりして、かなり遠方から患者さんが来ていたようです。1時間たっぷりやっても千円とか2千円くらいしか取らなくて半分ボランティアみたいなものでしたが、地元の農家の人は野菜をたくさん置いて行ってくれたりしました。またお中元やお歳暮の時期になると、贈り物が凄いことになっていました。

鍼灸には医療保険が適用されなかったので、自治体(町)に働きかけをして、補助金として1回500円の診療補助券制度を作ってもらったりしていたようです。 

私も小さい頃は、自分の小児喘息の治療のため鍼をしてもらっていたのですが、当時は鍼が痛くて泣いてました。その後、鍼もすごく細くなって、単に気持ちいいだけのものになりました。鍼はもともと大陸から伝わったものですが、その後、日本では細いものを使うようになったようです。 

うちの子どもたちがまだ小さかった時分、11か月違いの年子の体重増加に比例して私たち夫婦の肩こりや腰痛もひどくなっていったので、毎週のように実家に通って治療してもらっていました。親子なので無料でした。 

ただ親父が亡くなってからは、技術的に親父を超える鍼灸師をなかなか見つけることができず、最近は見つけることも諦めてもっぱらマッサージばっかりです。いったんよいサービス(しかも無料)を享受してしまうと、それに劣るサービスに対してそれ以上の対価を払うのはかなり抵抗があるものです。 

(オチはありません。TLで鍼治療のことを見たのでなんとなく)

PHP5.3以降ならこんな感じ?

hotta@sandbox:~$ cat to_wareki.php
<?php
//  西暦から和暦への変換
//
function to_wareki(Datetime $western) {
    $date = (int)$western->format('Ymd');

    if ($date >= 19890108) { //平成元年(1989年1月8日以降)
        $gengo = "h";
        $delta = new DateInterval('P1988Y');
    } else if ($date >= 19261225) { //昭和元年(1926年12月25日以降)
        $gengo = "s";
        $delta = new DateInterval('P1925Y');
    } else if ($date >= 19120730) { //大正元年(1912年7月30日以降)
        $gengo = "t";
        $delta = new DateInterval('P1911Y');
    } else if ($date >= 18680125) { //明治元年(1868年1月25日以降)
        $gengo = "m";
        $delta = new DateInterval('P1867Y');
    }
    $japanese = $western->sub($delta);
    return $gengo . '.' . $japanese->format('y/m/d');
}

$test = new DateTime('1868/09/01');
printf("西暦=%s, 和暦=%s\n", $test->format('Y/m/d'), to_wareki($test));
hotta@sandbox:~$ php to_wareki.php
西暦=1868/09/01, 和暦=m.01/09/01

Cent6でISOイメージ作成

Linux上でCDの中身をISOイメージ化した際のメモ。
OSはCentOS6で、vShere5上のVMとして動いているもの。

1.VMにクライアント側のCDを認識させる

  • vSphere Client>仮想マシン設定の編集>CD/DVDドライブ>クライアントデバイス>OK
  • vShere上部のCDボタンをクリック>CD/DVDドライブ1>D:に接続

2.マウントする

# mkdir /mnt/cdrom
# mount /dev/cdrom /mnt/cdrom

3.ISOイメージ化する

# yum install genisoimage
# mkisofs -o image.iso /mnt/cdrom
# ls -l image.iso
-rw-r--r-- 1 root root 541149184 6月 19 15:43 2012 image.iso

PHPでLM/NT Hash

Samba(+LDAP)でドメインログオンする場合、LDAP側にuserPassword以外にもNTPassowordとLMPasswordという属性を持たなければならない。
これらはmkntpwdというコマンドで生成することができるが、管理ツールを刷新する際、できればPHPで完結している方が望ましいので実装してみた。
環境設定

$ wget http://dist.justplayer.com/JPCRPM/CentOS/5/JPCRPM-php53.repo
$ sudo mv JPCRPM-php53.repo /etc/yum.repos.d
$ sudo yum install php-pear php-mcrypt
$ sudo pear install Crypt_CHAP

パスワードを生成するスクリプト

$ cat nthash.php
#!/usr/bin/php
<?php
require_once 'Crypt/CHAP.php';
$password = $argv[1];
$cr = new Crypt_CHAP_MSv1();
$nthash = strtoupper(bin2hex($cr->ntPasswordHash($password)));
printf("%s(NT Hash)\n", $nthash);
$lmhash = strtoupper(bin2hex($cr->lmPasswordHash($password)));
printf("%s(LM hash)\n", $lmhash);

mkntpwdコマンドの出力と合っていることを確認

$ ./mkntpwd -N test
0CB6948805F797BF2A82807973B89537
$ ./mkntpwd -L test
01FC5A6BE7BC6929AAD3B435B51404EE
$ ./nthash.php test
0CB6948805F797BF2A82807973B89537(NT Hash)
01FC5A6BE7BC6929AAD3B435B51404EE(LM hash)

Adobe Flash Player セキュリティ

Google Chrome for Windows を使っていて、
http://business.nikkeibp.co.jp/article/life/20110106/217826/
というURLを開こうとしたら(正確にはレンダリングが終わった後)

というダイアログが出た。

表示されている 2mdn.net というドメインwhois で引いたら
http://www.markmonitor.com/
という会社の持ち物らしい。サイトを見ると「ブランドを守る」ソリューションを提供している会社らしい。

http://answers.yahoo.com/question/index?qid=20100209054420AAY0zMs
ここに回答があったが、結局Flashベースで広告を配信するための仕組みらしい。
ブロックするのは別にChromeに限ったことでもなさそう。

AdBlock Extension
https://chrome.google.com/extensions/detail/gighmmpiobklfepjocnamgkkbiglidom?hl=ja
を入れたらダイアログは出なくなった。

ちなみにこの Extension をインストールすると、以下のように表示される。

I recently quit my job to devote full time to AdBlock! I now rely solely on your donations to support my family. Please donate to help pay our bills -- and prove that my wife and I (pictured) aren't crazy for trying this. Thanks :) - Michael

がんばっていただきたい。。。

CLI起動とcron起動の違い

$ cat _server.php
#!/usr/bin/php
<?php
print_r($_SERVER);

このようなPHPスクリプトで挙動を観察してみた。
まずはコマンドラインから起動。

$ ./_server.php
Array
(
    [HOSTNAME] => atlas.example.com
    [TERM] => xterm
    [SHELL] => /bin/bash
    [HISTSIZE] => 1000
    [NLS_LANG] => JAPANESE_JAPAN.AL32UTF8
    [SSH_CLIENT] => 10.28.1.30 62948 22
    [SSH_TTY] => /dev/pts/2
    [USER] => m-hotta
    [LS_COLORS] => no=00:fi=00:di=01;33:ln=01;36:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.gz=01;31:*.bz2=01;31:*.deb=01;31:*.rpm=01;31:*.jpg=01;35:*.png=01;35:*.gif=01;35:*.bmp=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.png=01;35:*.mpg=01;35:*.avi=01;35:*.fli=01;35:*.gl=01;35:*.dl=01;35:
    [MAIL] => /var/spool/mail/m-hotta
    [PATH] => /usr/kerberos/bin:/usr/local/bin:/bin:/usr/bin:/sbin
    [INPUTRC] => /etc/inputrc
    [PWD] => /home/m-hotta/lc_view/progs
    [LANG] => en_US.UTF-8
    [SSH_ASKPASS] => /usr/libexec/openssh/gnome-ssh-askpass
    [SHLVL] => 1
    [HOME] => /home/m-hotta
    [LOGNAME] => m-hotta
    [CVS_RSH] => ssh
    [SSH_CONNECTION] => 10.28.1.30 62948 10.27.4.26 22
    [LESSOPEN] => |/usr/bin/lesspipe.sh %s
    [G_BROKEN_FILENAMES] => 1
    [_] => ./_server.php
    [OLDPWD] => /home/m-hotta
    [ORACLE_HOME] => /usr/lib/oracle/10.2.0.3/client/lib
    [PHP_SELF] => ./_server.php
    [SCRIPT_NAME] => ./_server.php
    [SCRIPT_FILENAME] => ./_server.php
    [PATH_TRANSLATED] => ./_server.php
    [DOCUMENT_ROOT] =>
    [REQUEST_TIME] => 1291857301
    [argv] => Array
        (
            [0] => ./_server.php
        )

    [argc] => 1
)

次はこのようなcronを仕掛けて、

m-hotta@gtr:~$ crontab -l
MAILTO=hotta@example.com
HOME=/home/m-hotta
LANG=ja_JP.UTF-8
SUDO=/usr/bin/sudo
RM=/bin/rm
MV=/bin/mv
 */1 * * * * $HOME/lc_view/progs/_server.php

これで飛んできたメールの中身がこれ。

Array
(
   [SHELL] => /bin/sh
   [MAILTO] => hotta@example.com
   [USER] => m-hotta
   [RM] => /bin/rm
   [PATH] => /usr/bin:/bin
   [SUDO] => /usr/bin/sudo
   [PWD] => /home/m-hotta
   [MV] => /bin/mv
   [LANG] => ja_JP.UTF-8
   [SHLVL] => 1
   [HOME] => /home/m-hotta
   [LOGNAME] => m-hotta
   [_] => /home/m-hotta/lc_view/progs/_server.php
   [ORACLE_HOME] => /usr/lib/oracle/10.2.0.3/client/lib
   [PHP_SELF] => /home/m-hotta/lc_view/progs/_server.php
   [SCRIPT_NAME] => /home/m-hotta/lc_view/progs/_server.php
   [SCRIPT_FILENAME] => /home/m-hotta/lc_view/progs/_server.php
   [PATH_TRANSLATED] => /home/m-hotta/lc_view/progs/_server.php
   [DOCUMENT_ROOT] =>
   [REQUEST_TIME] => 1291857241
   [argv] => Array
       (
           [0] => /home/m-hotta/lc_view/progs/_server.php
       )

   [argc] => 1
)

コマンドラインでの実行に比べて、かなり情報が欠落しているのがわかる。
HOSTNAMEやSERVER_NAMEは、必要であればcrontabの中で設定してやる必要がありそう。