2012年12月

いざという時に待機系サーバーが動くかどうかを定期的にチェックしよう

ErogameScapeの現用系サーバーは、ここ1年ほど障害がなく動いていたため、待機系サーバーがトラヒックをさばくことはありませんでした。
待機系サーバーの動作チェックといえば、HDDが壊れるかもしれませんので、毎日muninのグラフを眺めたり、待機系サーバーにアクセスしてもちゃんとコンテンツが表示されることを確認したりするくらいでした。

さて、12月23日の15時頃、現用系のサーバーが温度異常で落ちました。
待機系サーバーに切り替わったまではよかったのですが、想定ですがErogameScapeにアクセスしても応答がない、または応答が著しく遅い状態になりました。

当時の/var/log/httpd/error.logです。
/var/log/httpd/error_log
[Sat Dec 22 15:10:34 2012] [error] server reached MaxClients setting, consider raising the MaxClients setting
[Sat Dec 22 15:10:48 2012] [error] [client 49.251.60.176] PHP Warning:  pg_connect(): Unable to connect to PostgreSQL server: could not connect to server: Connection refused
Is the server running on host "localhost" and accepting
TCP/IP connections on port 9999?


(1) server reached MaxClients settingについて

ErogameScaeのApacheはprefork MPMで動かしています。

※何かのドキュメントを読んだ結果、prefork MPMより、worker MPMの方がよさそうだな…と思った記憶があるのですが、そのままでも問題なく動いているので、何も検討せずprefork MPMで動かしています。

prefork MPMには、 MaxClientsという設定があります。
MaxClientsは同時接続数の上限を決める値で、ErogameScapeでは200としています。
この上限を超えた接続があると、ErogameScapeの場合、ユーザーさんから見て応答がなくなります。
Apacheの再起動をしないと回復しません。

第2回 コネクション受付制御のパラメータ | Think ITApacheのMaxClientsの設定とその挙動をまとめてみた | SUEKICHI.orgを読むと、待っていればキューにたまっているものは処理され、キューを超えた接続はRejectされ、Apacheからずっと応答が返ってこないことはなさそうなのですが、Apacheの再起動をしないと回復しません。topコマンドの出力を眺めていると、最初はLoad Averageが異様に高いのですが、server reached MaxClients setting, consider raising the MaxClients settingのメッセージを吐いた後は、だんだんとLoad Averageが少なくなっていき、0以下になるけども、いつまでたってもApacheは応答を返してくれないという状況です。
多分、Apacheとpgpoolの間のやりとりがつまっているからだと想定するのですがよくわかりません。


(2) Unable to connect to PostgreSQL serverについて

ErogameScapeはPostgreSQLを使用しています。またApacheとPostgreSQLの間にpgpool-IIを使用しています。pgpoolにも同時接続数の上限を設定できるパラメータとしてnum_init_childrenがあります。
ErogameScapeでは、num_init_childrenを100に設定しています。

num_init_childrenの説明は以下の通りです。
preforkするpgpool-IIのサーバプロセスの数です。デフォルト値は32になっています。 これが、pgpool-IIに対してクライアントが同時に接続できる上限の数になります。 これを超えた場合は、そのクライアントは、pgpool-IIのどれからのプロセスへのフロントエンドの接続が終了するまで 待たされます(PostgreSQLと違ってエラーになりません)。 待たされる数の上限は、2 * num_init_children です。

ApacheのMaxClientsが200なので、最大で200の要求がpgpoolにきますが、Apacheはキャッシュを返すことが多いのと、実際200の接続も来ない(下図参照、Apacheのbusy serversは100以下におさまっています。)ので、num_init_childrenを100で問題ありませんでした。

無題
 
が… Unable to connect to PostgreSQL serverというメッセージが出たということは、接続上限の100を超えた接続が継続した結果、pgpoolに接続できなかったということです。

さて…

MaxClients setting, consider raising the MaxClients settingが出た理由はなんだろう?と思って、待機系のサーバーの当時のApacheのprocessのmuninのグラフを見たら
ネタ4
となっていました。赤丸の部分が現用のサーバーが落ちた時刻です。
MaxClientsの設定が今までなぜか100になっていました。
サーバーを設定するためのテキストファイルを見たら、確かに100と書いてありました…
設定ミスです。100でも平常時は足りるのですが、サーバーを再起動したり、サーバーが長時間落ちていて復旧させると、ユーザーさんがいっせいにアクセスして一時的に100を超えることがあります。
この設定を修正しました。
※ちなみに1年以上前から設定をミスっていました…

修正後の値はなんとなくで400にしました。
というのは、もともとの設定は200なのですが、一時的なアクセスが200を超えて、Apacheの応答がなくなって再起動が必要なことがときどきあるので、ざっくり400にしておくかーと思ったからでした。

PHP Warning:  pg_connect(): Unable to connect to PostgreSQL server: could not connect to server: Connection refused
Is the server running on host "localhost" and accepting
TCP/IP connections on port 9999?
については、 この時点でどうしてpgpool(ポートは9999)に接続できないかさっぱりわかりませんでした。
PostgrsqlSQLに必要なmax_connections(同時接続数)は、
 pgpoolに接続するユーザーの数 × IPアドレス × pgpoolのnum_init_children
で計算できます。
現用系サーバーだけが動いている場合、権限が違う3つのユーザー × 2アドレス ×  100 = 600 となります。
PostgrsqlSQLのmax_connectionsは1000に設定しているので問題ないと思っていました。


待機系サーバーに切り替わったときにProcessが200ほど増えました。
ネタ8

これを見て、当時の自分は「現用系サーバーのApacheからpgpoolへの接続が持ちきっていて解放できていなくて、これに待機系サーバーのApacheからpgpooへlの接続(600くらい)が加わって800程度になったのかな」と勘違いしました。その結果、PostgrsqlSQLのmax_connectionsは1000だけど、一時的に1000を超えた接続があって、結果、Unable to connect to PostgreSQL serverになったのかなと思いました。
※pgpool (ポート9999)への接続ができていなかったので、PostgrsqlSQLのmax_connectionsは関係ないのですが…

その後、勘違いに気がついて、pgpoolのnum_init_childrenを倍にして、待機系サーバーに再度首をふった結果が以下のグラフの赤丸の部分です。

ネタ7

待機系サーバーで
tail -f /var/log/httpd/error_log
を実行しておきつつ、現用系サーバーでkeepalivedを停止して待機系サーバーに首をふりました。
数分もしないうちに、
server reached MaxClients setting
Unable to connect to PostgreSQL server
を吐いて応答がなくなりました…

その後、MaxClients settingを1000まで増やしてみて、首をふりましたが、同じように数分で応答がなくなりました。
ネタa


MaxClients settingを400にした際のApache Server Statusを抜粋します。

ネタ9

みるみるうちにrequestsが400に、はりつきます。
Apache Server Statusを見てあれ?と思ったのが、トップページへのアクセス「/~ap2/ero/toukei_kaiseki/」のRequestが多くて(多いのは確かにそうなのですが)"W" Sending Replyの状態だということでした。

ネタb

トップページはDBに接続しますが、ほとんどキャッシュなので二桁ms単位で応答を返すはずでした。
下に現在のトップページの応答時間の画像を示します。
ネタc


画像を保存するのを忘れてはれないのですが、当時、待機系サーバーのトップページの応答時間は秒単位で話にならないレベルでした。
考えられる原因は「キャッシュがきいてない」です。

ErogameScapeでは、キャッシュにpearのCache_Liteを使っています。
キャッシュの保存先は/tmpです。 ← 問題1
また、待機系サーバーはいつもはアクセスがないので、キャッシュを生成しないことから、現用系サーバーから待機系サーバーにキャッシュをrsyncでコピーしています。  ← 問題2

トップページ系のキャッシュなら/tmp/index、game.php系のキャッシュなら/tmp/gameのようにディレクトリを作って、キャッシュを格納しています。

※ディレクトリをわけているのは、game.php更新して実は不具合があってキャッシュを消したいといった場合に便利だからです。キャッシュされるファィル名はハッシュ値なので、ファィル名からどのスクリプトが生成したキャッシュかを判別するのが困難です。
ちなみにキャッシュファイル名は以下のような感じです。

[ap2@erogamescape14 sp]$ ls
cache_c21f969b5f03d33d43e04f8f136e7682_4b718b3868bd9361022eec6491d5c02d
cache_c21f969b5f03d33d43e04f8f136e7682_5943dbe6e144efe5d2b21e5f882df3ec
cache_c21f969b5f03d33d43e04f8f136e7682_6d05f0548144b97eb2f926aea9e4d0e7
cache_c21f969b5f03d33d43e04f8f136e7682_b07d4fb600552c8660de41e194707769
cache_c21f969b5f03d33d43e04f8f136e7682_b1fab48509ba289b67257d0572effbe3
cache_c21f969b5f03d33d43e04f8f136e7682_bdce208ad887e2ca02902c416e2bb0ba

待機系サーバーの/tmpを確認すると、/tmp/indexがありませんでした。
また、/tmp/gameもありませんでした。
/tmp/creater(creater.php系のキャッシュを格納するディレクトリ)はありました。

さて…なんでこんなことになるのか…と思って、現用系サーバーのcronで定期的に実行している現用系サーバーから待機系サーバーへの/tmp配下のrsyncを見たら、/tmp/createrはrsyncしていますが、/tmp/indexや/tmp/gameはrsyncしていませんでした。

そういえば、/tmpの配下のファイルって消えるんだっけ、でもいつ消えるんだっけ?ということでgoogle先生に聞くと、@IT:/tmpのファイルがいつの間にか消えてしまうということで、tmpwatchに書いてあるとのことです。
CentOS6のtmpwatchは以下の通りでした。
#! /bin/sh
flags=-umc
/usr/sbin/tmpwatch "$flags" -x /tmp/.X11-unix -x /tmp/.XIM-unix \
        -x /tmp/.font-unix -x /tmp/.ICE-unix -x /tmp/.Test-unix \
        -X '/tmp/hsperfdata_*' 10d /tmp
/usr/sbin/tmpwatch "$flags" 30d /var/tmp
for d in /var/{cache/man,catman}/{cat?,X11R6/cat?,local/cat?}; do
    if [ -d "$d" ]; then
        /usr/sbin/tmpwatch "$flags" -f 30d "$d"
    fi
done
10日で消えます。
tmpwatchは、もちろんディレクトリごと消すので、現用系サーバーから定期的にファイルが送られてくる/tmp/createrは消えないですが、/tmp/indexや、/tmp/gameは10日で消えます。
トップページのPHPスクリプトは/tmp/indexにキャッシュを生成しようとしますが、/tmp/indexがないのでキャッシュを生成できず、いちいちDBにアクセスして応答を返す、応答を返すまで2秒くらい…という状況になっていたということです。

ああ、そら、駄目だ…

ということで、待機系サーバーにキャッシュ用のディレクトリを作りなおして、現用系サーバーのrsyncも設定し直して、現用系サーバーからrsyncして、めでたしめでたし…となると思ったのですが、 それでも状況はかわりませんでした。応答がすごく遅いです。

考えられる可能性は「キャッシュが読めてない」でした。
でも、キャッシュファイルは確かにあるだけどなあ…と思ってls -lで見ると、

[ap2@erogamescape15 brand]$ ls -l
合計 8
-rw-r--r-- 1 ap2 ap2 4226 12月 24 19:20 2012 cache_c21f969b5f03d33d43e04f8f136e7682_dc23d669a5a1fd3a31f1472f9a7458b7

のような出力でした。
現用系サーバーですと

[ap2@erogamescape14 brand]$ ls -l
合計 8
-rw-r--r-- 1 apache apache 4226 12月 24 19:20 2012 cache_c21f969b5f03d33d43e04f8f136e7682_dc23d669a5a1fd3a31f1472f9a7458b7

です。

(1) なんで待機系サーバーのキッャシュファイルの権限がap2なんだっけ?
  権限がapacheじゃなきゃキャッシュを更新できないじゃん
(2) もしかしてpearのCache_Liteは、キャッシュファィルの権限がapache(というかApacheで設定したユーザー)じゃないと読まない?

pearのCache_Liteを使う前は、実は自身で作ったキャッシュ機構を使っていて、そのキャッシュ機構は
 ・キャッシュの権限は666で生成する
だったので、誰でも読めるし更新もできるものでした。
なので、キャッシュを生成するユーザーは全然気にしていませんでした。

Cashe_Liteは644で、ユーザーはapacheで生成します。…正しいですね。
※ちなみに権限を変更するオプションはないので、権限をかえるならスクリプトの中でchownするなりする必要があるかなと。まあ…そんな必要はないかな…

644のapacheで生成されたファィルをrsyncで待機系サーバーに送っているのですが、rsyncで権限をそのままにコピーするには

[ap2@erogamescape15 ~]$ rsync --help | grep owner
 -o, --owner                 preserve owner (super-user only)

で、root権限がないと駄目です。
私はそもそもそんなオプションつけてませんでした…オプションをつけるならつけたときにrootユーザーでrsyncのcronを設定していたと思いますし…

これで(1)は解決、(2)についてはちゃんと調べていないのですが、実際キャッシュファイルを読めていなかったので、まあそんなもんなんだろう…ということで、
  • /tmp配下のキャッシュファィルを削除 
  • キャッシュに必要なディレクトリだけ作成
  • 現用系サーバーからのrsyncをストップ
  • tmpwatchの設定を変更してとりあえず1年は/tmp配下のファィルを消さないように修正
して、めでたく待機系サーバーでもトラヒックをさばけるようになりました。


あと一箇所設定ミスがありました。 
ErogameScapeではApacheが応答を返さなかった場合に、httpdをrestartするcronを動かしています。
以下のようなスクリプトです。

[root@erogamescape15 ~]# cat httpd_restart.sh
check=`wget -nv -S --spider -t 2 -T 5 http://127.0.0.1/~ap2/ero/toukei_kaiseki/ 2>&1|grep -c "200 OK"`

if [ $check != 2 ]
then
    echo 'NG'
    RESULT=`/sbin/service httpd restart`
    `date >> httpd_restart_date.txt`
else
    echo 'OK'
fi

これを動かすcrontabは
*/2 * * * * /root/httpd_restart.sh
な感じなのですが、当時どうしてそうなっていたのか分からないのですが、
*/2 * * * * chmod 700 /root/httpd_restart.sh
になっていました。

意味がわかりません…

また、上記スクリプトのwgetは当時
wget -nv -S --spider -t 2 -T 5 http://127.0.0.1/~ap2/
としていました。

httpdの応答だから、これでいいかなと思っていたのですが、サービス監視としてはトップページである
http://127.0.0.1/~ap2/ero/toukei_kaiseki/
の応答を見るのが正しいなということで、変更しました。


以上が、12月23日~24日にかけて繋がりにくかった件の顛末です。
1年以上障害がなかったので、待機系サーバーが使い物になっていないことに全然気がつきませんでした。
これからはたまに待機系サーバーに首をふってみようと思います。

大変ご迷惑をおかけいたしました。
今後ともよろしくお願いいたします。
 

ケースファンの重要性について

ある日ケース背面(リア)のファンがうるさい音をたてるようになりました。
電源を落として再度電源を投入すると音が止まるのですが、しばらくするとまた音がではじめるので
  • 新しいファンを買わねば
  • 冬だからそんなに急がなくて大丈夫かな
と思って、ファンの電源を落としたままで、ケースの蓋を閉じてそのままにしていました。
12月23日の15時頃、以下のメッセージを出力してサーバーの応答がなくなりました。

/var/log/messages
Dec 22 10:02:56 mcelog: Processor 0 heated above trip temperature. Throttling enabled.
Dec 22 10:02:56 mcelog: Please check your system cooling. Performance will be impacted
Dec 22 10:02:56 mcelog: Processor 0 below trip temperature. Throttling disabled
Dec 22 14:10:26 mcelog: Processor 0 heated above trip temperature. Throttling enabled.
Dec 22 14:10:26 mcelog: Please check your system cooling. Performance will be impacted
Dec 22 14:10:26 mcelog: Processor 0 below trip temperature. Throttling disabled
Dec 22 14:17:56 mcelog: Processor 0 heated above trip temperature. Throttling enabled.
Dec 22 14:17:56 mcelog: Please check your system cooling. Performance will be impacted
Dec 22 14:17:56 mcelog: Processor 0 below trip temperature. Throttling disabled
Dec 22 14:24:11 mcelog: Processor 0 heated above trip temperature. Throttling enabled.
Dec 22 14:24:11 mcelog: Please check your system cooling. Performance will be impacted
Dec 22 14:24:11 mcelog: Processor 0 below trip temperature. Throttling disabled
Dec 22 14:29:11 mcelog: Processor 0 heated above trip temperature. Throttling enabled.
Dec 22 14:29:11 mcelog: Please check your system cooling. Performance will be impacted
Dec 22 14:29:11 mcelog: Processor 0 below trip temperature. Throttling disabled
Dec 22 14:35:26 mcelog: Processor 0 heated above trip temperature. Throttling enabled.
Dec 22 14:35:26 mcelog: Please check your system cooling. Performance will be impacted
Dec 22 14:35:26 mcelog: Processor 0 below trip temperature. Throttling disabled
Dec 22 14:42:56 mcelog: Processor 0 heated above trip temperature. Throttling enabled.
Dec 22 14:42:56 mcelog: Please check your system cooling. Performance will be impacted
Dec 22 14:42:56 mcelog: Processor 0 below trip temperature. Throttling disabled
Dec 22 14:50:26 mcelog: Processor 0 heated above trip temperature. Throttling enabled.
Dec 22 14:50:26 mcelog: Please check your system cooling. Performance will be impacted
Dec 22 14:50:26 mcelog: Processor 0 below trip temperature. Throttling disabled
Dec 22 14:52:56 mcelog: Processor 0 heated above trip temperature. Throttling enabled.
Dec 22 14:52:56 mcelog: Please check your system cooling. Performance will be impacted
Dec 22 14:52:56 mcelog: Processor 0 below trip temperature. Throttling disabled
Dec 22 15:00:26 mcelog: Processor 0 heated above trip temperature. Throttling enabled.
Dec 22 15:00:26 mcelog: Please check your system cooling. Performance will be impacted
Dec 22 15:00:26 mcelog: Processor 0 below trip temperature. Throttling disabled

/var/log/mcelog
CPU 0 THERMAL EVENT TSC 9557f0a491a8cb
TIME 1356155513 Sat Dec 22 14:51:53 2012
Processor 0 heated above trip temperature. Throttling enabled.
Please check your system cooling. Performance will be impacted
STATUS 8801000f MCGSTATUS 0
MCGCAP 806 APICID 0 SOCKETID 0
CPUID Vendor Intel Family 6 Model 23
Hardware event. This is not a software error.
MCE 1
CPU 0 THERMAL EVENT TSC 9557f0a4980a8d
TIME 1356155513 Sat Dec 22 14:51:53 2012
Processor 0 below trip temperature. Throttling disabled
STATUS 8801000a MCGSTATUS 0
MCGCAP 806 APICID 0 SOCKETID 0
CPUID Vendor Intel Family 6 Model 23
Hardware event. This is not a software error.
MCE 0
CPU 0 THERMAL EVENT TSC 9558bfcbfa2e21
TIME 1356155827 Sat Dec 22 14:57:07 2012
Processor 0 heated above trip temperature. Throttling enabled.
Please check your system cooling. Performance will be impacted
STATUS 8801000f MCGSTATUS 0
MCGCAP 806 APICID 0 SOCKETID 0
CPUID Vendor Intel Family 6 Model 23
Hardware event. This is not a software error.
MCE 1
CPU 0 THERMAL EVENT TSC 9558bfcc009e99
TIME 1356155827 Sat Dec 22 14:57:07 2012
Processor 0 below trip temperature. Throttling disabled
STATUS 8801000a MCGSTATUS 0
MCGCAP 806 APICID 0 SOCKETID 0
CPUID Vendor Intel Family 6 Model 23
 
ああ…、だいぶ熱かったんですね…
現在は蓋をしめずに、開けっ放しで運用しています。

教訓
  •  ケースファンが動いていないのに蓋をしめて運用するのは冬でも無理
  •  ケースファンが壊れたときにすみやかに交換できるように予備を用意しておこう


ケースファンが壊れたのは現用系のサーバーでした。
待機系のサーバーはVRRPでアドレスを引きついで動作を開始しました。

/var/log/messages
Dec 22 15:10:25 erogamescape15 Keepalived_vrrp: VRRP_Instance(VI_1) Transition to MASTER STATE
Dec 22 15:10:26 erogamescape15 Keepalived_vrrp: VRRP_Instance(VI_1) Entering MASTER STATE
Dec 22 15:10:26 erogamescape15 Keepalived_vrrp: VRRP_Instance(VI_1) setting protocol VIPs.
Dec 22 15:10:26 erogamescape15 Keepalived_vrrp: VRRP_Instance(VI_1) Sending gratuitous ARPs on eth0 for 192.168.0.100
Dec 22 15:10:26 erogamescape15 Keepalived_healthcheckers: Netlink reflector reports IP 192.168.0.100 added
Dec 22 15:10:27 erogamescape15 ntpd[10305]: Listening on interface #8 eth0, 192.168.0.100#123 Enabled
Dec 22 15:10:31 erogamescape15 Keepalived_vrrp: VRRP_Instance(VI_1) Sending gratuitous ARPs on eth0 for 192.168.0.100

開始したのですが…続く
 

POSTした値をPHPですべて受け取れない事象について

先日「批評空間にて点数を入力し更新しようとすると、無効のリンクと表示される」というご申告を頂きました。

ErogameScapeでは、GETやPOSTで渡ってくる値を検証(バリデーション)した結果、想定した値でない場合は404を返します。 

ご申告から、検証にひっかかっていると推測して調査しました。
申告頂いた方に点数を入力したフォームのURLを伺って試してみると…

1. フォームが送信したPOSTの内容 → 問題なし
2. PHPで受信したPOSTの内容(print_r( $_POST )で確認します。) → 1.の内容と相違有り

ApacheはPOSTした内容を制限するディレクティブ(LimitRequestBody)があります。
一応、設定していないことを確認しました。

PHPで何か悪さしているに違いないと思うのですか、本当にPHPが悪いのか分からないので、Apacheが受け取ったPOSTの内容がみたいなあと思いました。

そこで、 Apache 全I/Oデータをログするを参照してPOSTをログに出力する設定を実施。
error.logに結果が出力されるそうですので、tail -f error.logを実行したところ

 [Wed Dec 19 23:14:52 2012] [error] [client 192.168.0.12] PHP Warning:  Unknown: Input variables exceeded 1000. To increase the limit change max_input_vars in php.ini. in Unknown on line 0, referer: http://192.168.0.15/~ap2/ero/toukei_kaiseki/contents_tokuten_ichiran_default.php?mode=aiueo&gyou=a

と書いてありました。

Unknown: Input variables exceeded 1000. To increase the limit change max_input_vars in php.ini.
ということで、php.iniを見ても、 max_input_varsという設定がない。

max_input_varsをgoogleで検索すると php.ini で mbstring.encoding_translation を有効にすると max_input_vars が有効にならない(PHP 5.4.8以前、PHP 5.3.18以前) - t_komuraの日記にPHP 5.3.9 で max_input_vars が導入された(hashdos 脆弱性対策)とありました。

PHPのマニュアルでmax_input_varsを確認すると、PHP: 実行時設定 - Manualに該当項目がありまして、
入力変数 を最大で何個まで受け付けるかを指定します (この制限は、スーパーグローバル $_GET、$_POST そして $_COOKIE にそれぞれ個別に適用されます)。 このディレクティブを使うと、ハッシュの衝突を悪用したサービス不能攻撃を受ける可能性を軽減できます。 このディレクティブで設定した数を超える入力変数があった場合は E_WARNING が発生し、 それ以降の入力変数はリクエストから削除されます。 多次元配列の場合、この制限は個々の次元ごとにしか適用されません。
とのことです。

そういえば、最近phpのverをあげたな…
/etc/php.iniのある場所に、/etc/php.ini.rpmnewがありました…

※ソフトのVerをあげた際に設定項目に変更があると、.rpmnewというファイルが生成されます。Verをあげる際にはちゃんと新しいiniファイルで設定しなおさないと駄目です。

 /etc/php.ini.rpmnewを確認すると、max_input_varsがありました。

max_input_varsのデフォルトは1000です。
多分、普通の入力フォームですと、1000を超えることはない…どころか100を超えることもない気がしますが、ErogameScapeはとてもたくさんのデータを一度に入力できるので1000では足りてませんでした。

max_input_varsをそれなりな値に設定して、めでたくデータが入力できるようになりました。

教訓
 verをあげる場合は、ちゃんと追加された設定項目を確認しよう

類似話題
 php.iniのmax_input_varsというパラメータ « kawama.jp

CentOSでphpをインストールする場合に設定するEPELリポジトリのドメインの変更について

CentOSでphpやmysqlの最新版をインストールする場合、EPELリポジトリを設定します。
EPELリポジトリのドメインが変更になっていた(だいぶ前のようですが…) ので書いておきます。

旧:download.fedora.redhat.com
新:dl.fedoraproject.org

php5.4系の最新版をインストールする | レンタルサーバー・自宅サーバー設定・構築のヒントの記事で知りました。

すでにEPELリポジトリの設定がしてある場合は特に何かする必要は無い…と思います。ErogameScapeのサーバーは仕組みは分からないのですが、ちゃんとEPELリポジトリの最新の情報をftp.iij.ad.jpに取りに行ってました。

これからサーバーを新規構築する場合に気をつける項目かなと思います。

pg_dumpをするとmissing chunk number 0 for toast value 47801904 in pg_toast_28652299というエラーがでて失敗する

ErogameScapeでは待機系のサーバーで1日1回pg_dumpでバックアップをとって、さくらインターネットに借りているサーバーに転送しています。
ErogameScapeのサーバーがある場所が災害でつぶれても、私が生きていれば復旧可能です。

※さくらインターネットが同時につぶれることも想定して、一ヶ月に一回実家にデータをバックアップしたDVDを送っています。そのDVDをお父さんが貸金庫に預けているので、私が生きていれば…データ的には一ヶ月くらいの巻き戻りで済みます。問題は私が死んだ場合、どうしようかなあ…というところです。私のバックアップが必要なので、私が死んでもErogameScapeを運用できるマニュアルが必要だと今思いました…そういえば人間RAID - うんこめもな記事を読んだことを思い出ました。1人で運用しているサービスは、何かあったときにどうするかを考えているのか知りたいなあ…と思いました。

さて、そのバックアップが実はできていないことが先日分かりました。

※分かった契機は、PHP5.4でもErogameScapeは動くのか?の検証をするために、VMwareに検証環境を構築していたときでした。バックアップのデータをリストアしてみたら、nobodyの権限でDBに接続できませんでした。接続できない理由は、そもそもテーブルに権限が設定されていなかったからでした。バックアップしたデータは圧縮されているので、バックアップを取り直してみたら、 以下に記載するエラーを吐いてバックアップがちゃんとされていないことが分かりました。

pg_dumpを実行すると以下のメッセージを出力しました。
pg_dump: SQLコマンドが失敗しました
pg_dump: サーバのエラーメッセージ: ERROR:  missing chunk number 0 for toast value 47801904 in pg_toast_28652299
pg_dump: 次のコマンドでした: COPY public.serch_word_his (category, word, media, "timestamp") TO stdout;
pg_dump: *** エラーのため中断

googleで検索すると
PostgreSQL - admin - missing chunk number 0 for toast value
で、REINDEXすればよさそう的なことが書いてありました。

[ap2@erogamescape15 ~]$ psql
psql (9.0.10)
"help" でヘルプを表示します.
ap2=# select reltoastrelid::regclass from pg_class where relname = 'serch_word_his';
       reltoastrelid
----------------------------
 pg_toast.pg_toast_28652299
(1 行)

ap2=# reindex table pg_toast.pg_toast_28652299 ;
REINDEX
ap2=# \q
以上で、無事バックアップがとれるようになりました。

恐ろしいのは、バックアップはcronで仕掛けてとっているので全然エラーに気がつかなかったことと、バックアップが中途半端にとれてしまっているので、ファィルがそれなりの日付で生成されていて気がつかなかったことでした。

バックアップが中途半端なので、ファイルサイズがあきらかに以前より小さくなっていた(今は500MBくらいなのですが、失敗していたファイルは半分の250MBくらいでした)ので、そこで気がつけていなければいけなかった気がするのですが、ちょっと難易度高いなあと思いました。

 バックアップはcronで、そのままpg_dumpコマンドを叩いているのですが、pg_dumpコマンドの応答を見て、失敗しているようだったら通知する仕組みに変えないといけないなあと思いした。
 

VMwareにCentOSをいれて日本語環境にして日本語入力できるようにする

VMwareにCentOS6をいれると簡易インストールと呼ばれるインストールの仕方になります。
※他のVerだとどうなるかわからないのでCentOS6と書いておきます。

実マシンにCentOS6をいれると、いろいろなことを聞かれる(パッケージは何をいれると等々)のですが、VMwareの簡易インストールの場合、何も聞かれないので、とりあえずインストールしてからいろいろ設定をする必要があります。

日本語環境にする
 → CentOS 6 - 日本語環境にする : Server World 

日本語入力できるようにする
 → Cent OS 6 で日本語入力 - The Serenity Prayer

VMwareをいれようと思った理由はPHP5.4が動く環境を作ろう!でした。
自分はそれなりにCentOSを使ってきたので、VMwareいれてOSインストールして、いつものサーバーの設定をしていけばいいかなーくらいに思っていたのですが、そうそううまくいかないもんだなあと思いました。

一度、そういうもんだと分かれば大丈夫ですが、慣れるまではやっぱりちょっと大変かなと思いました。

VMware便利ですね。

何個でも仮想サーバーが作れるので、パソコン1つで、たとえば複数台の冗長構成を作って障害があった場合にちゃんと切り替わるかの設定が正しいかとかの試験ができると思いました。
前にそんな設定の検証をしたときには実家から古いパソコンを2台持ってきてやってました…
便利な世の中になったものです…

SQL初級者から見たO/Rマッパーについて

SQL上級者こそ知って欲しい、なぜO/Rマッパーが重要か? を読んで、確かにSQLにはWITH句があるけど、それはSQLの中での部品の再利用なので、スクリプトの中で同じようなSQLを実行したいときの再利用の機能はないなあ…と思いつつ、モダンなORMがSQLの完全な代替になるかというと、多分そうはならないんじゃないかなあと思いました。

自分と同じような感じ方をされる方がいらっしゃるかなと思ったらいらっしゃいました。
O/Rマッパーはなぜ悪かO/Rマッパーはなぜ悪か・2になります。

「は?最近のO/Rマッパーはそんなアホじゃないし?w」「あ,はい。そうだったんですねー」と瞬殺されたそうですので、この記事も瞬殺されそうですが…


私はErogameScapeでSQLを直接がりがり書いてます。
O/Rマッパーというものの存在を知ったのは、 CodeIgniterを学習したときになります。
O/Rマッパーを知って使ってみたときの感想は、INSERTやUPDATEは便利だけど、 SELECTは単純なものじゃないと使い物にならないな…でした。

※モダンなO/Rマッパーでしたら、複雑なSQLもスマートにかけるのでしょうか…

O/Rマッパーはなぜ悪かの文書にもあるように、O/RマッパーはとんでもないSQLを作成することがあって、びっくりすることがあります。
多分、そんなびっくりなSQLを生成しないように、ちゃんとしたSQLを生成するようにO/Rマッパーに値を渡すのだと思いますが、O/Rマッパーの使い方を学ぶよりSQLで直書きした方が、分かりやすいなあ…というのがSQLをガリガリ直接書いてきたものとしての感想です。

Javascriptに対するCoffeeScriptのような素晴らしいO/Rマッパーがでてくるかもしれませんが、まだそれはだいぶ先なのかなと思います。

※私はPHPのフレームワークのO/Rマッパーしか知らないので、JavaやRubyで使われるO/Rマッパーがすごかったらごめんなさい!

SQLで直書きしていれば、PHPのフレームワークで作っていたものをRuby on Railsに移植するときも問題ないと思いますが、現状O/Rマッパーは、フレームワークごとに違うと思いますので、一度開始したサービスのフレームワークをかえることはないかもしれませんが、あるとしたら…移植が大変なんじゃないかなあと思います。

うまく書けないのですが、リレーショナル・データベースの世界や大学等の授業で習うように、SQLは集合論を基礎としている言語で、O/Rマッパーで表現しようとすると、SQLで書くより複雑になってしまうこともあるんじゃないかなあと思います。その…ErogameScapeで実行しているSQLをCodeIgniterやFuelPHPやCakePHPのO/Rマッパーで書こうとすると、すごく悩んでしまうことがありました。

SQL上級者こそ知って欲しい、なぜO/Rマッパーが重要か? には、SQLには部品化の機能がない→SQLが長くなる・わかりくにいとありますが、私は…適切にインデントされたSQLの方がO/Rマッパーより分かりやすいなあと思います。

O/Rマッパーを使うと、SQL上級者にも納得がいくSQLを生成できて、SQLを知らなくてもSQL上級者並のSQLが生成されるようになったときに、SQL上級者の方々はO/Rマッパーもいいね、となるんじゃないかなあと思いました。

以上、10年くらい日曜プログラマーとして、SQLを書いてきたもののコメントです。

VMware Toolsのインストール時のtar.gzは、どこか別の場所にコピーしてから展開して作業すること

※すごいどうでもいいことにはまってしまったので、同じミスをする方がいるかもしれないのでメモです。

VMwareにOSをいれたら次にすることはVMware Toolsをインストールすることだと思います。
VMware Toolsをいれないと、VMwareの中でしかコピー&ペーストができないので、とても使い勝手が悪いです。

VMware Toolsをインストールするには、 いろんなHPに書いてある通り
 Player→ 設定→VMware Toolsのインストール
とクリックしていき、下に表示されるメッセージに従って作業するだけです。

VMware Player Ver5.0.1 build-894247では、VMware Toolsのインストールをクリックすると、どこかにあるVMware ToolsのISOイメージをマウントしてその中身を表示します。
中には 
  • manifest.txt
  • VMwareTools-[ver名].tar.gz
の2つのファィルがあります。
※[ver名]には8.4.6-385536のようなver名が入ります

ここで、やるべきなのは、VMwareTools-[ver名].tar.gzをどこか別の場所にコピーして、tarコマンドで展開して、vmware-install.plを実行するなのですが、私は何を勘違いしたのか

VMwareTools-[ver名].tar.gzをダブルクリックする
 → VMwareTools-[ver名].tar.gzがキャッシュディレクトリに展開されて中身が見える

vmware-install.plをダブルクリックする
 → Viewerが開いて中のperlのスクリプトがみえる
 → むむっ、これを実行するにはどうしらいいんだ…

findコマンドでvmware-install.plを探す
 → homeディレクトリの中に.casheというディレクトリがあって、その中にファイルがいるのを発見
 → treminalで、ファイルのあるところまでいってplファイルを実行
 → 途中でエラー、何かファイルがコピーできないメッセージ

ということをしていました。
悩んだあげく、はじめてのcentos5.6 VMware tools インストール VMware Player 3.1.4 VMware Workstation7 評価版の「作業をするために VMwareTools-8.4.6-385536.tar.gz をいったんどこか作業できる場所(ディレクトリ)へコピーします。」を見て、ああ、そういうことかと納得。

無事インストールが終わりました。

VMware Toolsをインストールするには、 いろんなHPに書いてある通り
 Player→ 設定→VMware Toolsのインストール
とクリックしていき、下に表示されるメッセージに従って作業するだけ…のはずですが、ちょっとメッセージが不親切だった気がするなあと人のせいにしてみます。


VMwareのpsqlで\dのようなメタコマンドが効かない

※根本的な解決方法があるかもしれないのですが、自分はその解決方法が分からなかったのでメモします。

環境
  • VMwareにCentOS6をインストール
  • キーボードの設定は日本語(かな86)
  • 日本語環境化済み
の状態で、psqlで、例えば\dを入力すると以下のようになってしまいます。
ap2=# \d
ap2-#
通常ならテーブルのリストが返ってくるのですが返ってきません。

ap2=# \d
とうつとちゃんと返ってきます。

psqlのマニュアルには
psqlコマンドはバックスラッシュに すぐ続く動詞コマンドと、それに続く何らかの引数からなります。
と書いてあるので、\dが正しいのだろうなあと思ったのですが、今まで\dと書いても問題なかったので、ちょっと手間取りました。

※ところで、livedoorBLOGでは\と打つと\と表示されてしまいますね…\はどうやってうてばいいのかな…
記事検索