Posts Tagged ‘PHP’

WordPress 2.9.xの自動アップデートがコケる

結論から言えば/var/php.iniのmemory_limitの上限を引き上げれば解決します:

[変更前]
memory_limit = 16M
[変更後]
memory_limit = 64M

(変更後は 「service httpd restart」 を実行してapacheを再起動すること。念のため)

ズボラな私は基本的に自動アップデートで済ませてしまうのですが、バージョン2.9.1以降、以下のメッセージが表示されたままウンともスンとも言わないという状態が続いていました

http://ja.wordpress.org/wordpress-2.9.1-ja.zip からアップデートをダウンロードしています。

その前後でサーバの移行などしていたためエラー原因が絞りきれず、とりあえず放置しておいた(笑)んですが、2.9.2がリリースされても同様の現象が確認されたので、とりあえず/var/log/httpd配下にあったapacheのエラーログを確認したらそのものズバリなエラーが。最初から見とけよ。

[Fri Feb 26 08:20:10 2010] [error] [client 192.168.XXX.XXX] PHP Fatal error: Allowed memory size of 33554432 bytes exhausted (tried to allocate 2804864 bytes) in /xxx/xxx/tokiwasou.com/memo/wp-includes/http.php on line 1331, referer: http://www.tokiwasou.com/memo/wp-admin/update-core.php

要はPHP実行に必要なメモリが足りんと。どうやらサーバ移行した際にPHPに割り当てるメモリサイズ(memory_limit)を、デフォルト(16M)のまま放置しておいたのが原因のようです。33MB超のメモリを割り当てようとしてコケたみたいなのでとりあえず上記のmemory_limit=64Mで回避しましたが、このあたりのさじ加減はサーバによって異なると思うので、64Mで失敗する方は128Mでも256Mでもサーバのリソースが許す限りお好きな値をどうぞ。

 

PHP5.3.xは鬼門か?

何も考えずPHP5.3.xに上げたら動かないモジュール続発。
どうやら寝た子を起こしてしまったらしい。(泣)

現在認識している「問題のあるモジュール」は以下の3つ
・mecab
・php_perl
・apc (Alternative PHP Cache)

とりあえずmecab以外はパッチ当てたりベータ入れたりしてその場をしのいで見たものの、開発環境が残念な感じになってしまったのも事実。

mecabもmecab本体とPHPにパッチ当てれば動くようにななるんだが、、、

とりあえず様子をみるか。

 

date.timezoneを使えと怒られた

PHPを5.3.xに上げた後、いつも流してるスクリプトでdate()関数呼び出したらこんな警告が出た。回避するには/etc/php.iniでdate.timezoneでタイムゾーンを明示するか、事前にdate_default_timezone_set()を呼ばなければならないらしい。

PHP Warning: date(): It is not safe to rely on the system’s timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier.

オレ訳:
システムのタイムゾーン設定に依存するのは確実ではありません。date.timezoneを設定するかdate_default_timezone_set()を設定する必要があります。いずれかを設定後も引き続きこの警告が出る場合は、タイムゾーンIDが間違っている可能性が高いです。

調べたら日本のタイムゾーンIDは「Asia/Tokyo」なので、

# vi /etc/php.ini

[Date]
; Defines the default timezone used by the date functions
date.timezone = Asia/Tokyo

と設定するか、プログラム内でdate()関数を呼び出す前に

date_default_timezone_set(‘Asia/Tokyo’);

と宣言してあげてください。

ちなみにPHPでサポートしているタイムゾーンのリストはこちらで確認できます。

付録 H. サポートされるタイムゾーンのリスト

ちなみに影響範囲はPHP5.1.x以降らしいので、5.3.x固有の問題というわけではなさそう。単に俺が今まで気づかなかっただけか?

 

PHPで重複起動を防ぐ

cronで定期的に回すバッチなど、複数同時に呼び出したくない処理は、起動時に自分以外の誰かが既に突っ走ってないかチェックしてやる

$self = basename($_SERVER['SCRIPT_NAME']); //自身のファイル名取得
exec("ps aux | awk '{print $12}' | grep $self", $retVal); //プロセスを調べる
if(count($retVal) > 2) { //3つ以上の場合は誰か突っ走ってる
	echo "プロセスが既に起動中しています。処理を中止します。\n";
	exit(0);
}

$selfにチェックしたいファイル名を入れてやれば、自分自身以外のプログラムの起動チェックも可能。

 

file_get_contents()で値が取れないとき

リクエストそのものが問題なく終了しているのなら、サーバーが何らかのエラーメッセージを返している可能性が高い。とりあえずget_headers()使って様子を見よう。

$url = 'http://www.tokiwasou.com';
print_r(get_headers($url));

(結果)
Array
(
[0] => HTTP/1.1 200 OK
[1] => Date: Thu, 11 Jun 2009 15:17:09 GMT
[2] => Server: Apache
[3] => Content-Length: 717
[4] => Connection: close
[5] => Content-Type: text/html
)

問題があれば0行目にHTTPのエラーコードが格納されているのでそれを確認する。

ちなみにURLの後ろにオプションのフラグを立てれば、連想配列で結果を返してくれる。
こういう細かい心配りがPHPはうれしい。

$url = 'http://www.tokiwasou.com';
print_r(get_headers($url, 1));

(結果)
Array
(
[0] => HTTP/1.1 200 OK
[Date] => Thu, 11 Jun 2009 15:17:23 GMT
[Server] => Apache
[Content-Length] => 717
[Connection] => close
[Content-Type] => text/html
)

大抵はコンテンツがリダイレクト先にあって301とか302が返ってきているか、500(Internal Server Error)が返されているはず。レアなところだと401(Gone:イッちまった)が返される場合もある。それはもうキミのせいじゃない。男らしくすっぱりあきらめよう。

 

PHPでプロキシを使いたい(stream_context_create編)

Proxy経由でfopen()やfile_get_contents() を使う場合は、stream_context_create()を使ってプロキシ経由のストリームコンテキストを作成してやる。

そいでそいつをfopen()やらfile_get_contents()に渡してあげればOK。

(1) Proxy用オプション設定(必要最低限Ver.)

$sc_opts = array(
‘http’=>array(
‘proxy’ => ‘tcp://192.168.0.XX:8888‘,
‘request_fulluri’ => True
)

(2) ストリームコンテキスト作成

$sc= stream_context_create($sc_opts);

(3) コンテンツ取得

$contents = file_get_contents(‘http://www.tokiwasou.com‘, TRUE, $sc);

(4) 結果表示

var_dump($contents);

ただし上記設定はProxy経由で通信するために最低限必要なオプションを指定しているだけなので、例えばユーザーエージェントで表示するページを変えているサイトとかだと、期待したコンテンツを取得できない(あるいはアクセスそのものが拒否されてしまう)ことがある。

あるいはコンテンツが複数回のリダイレクトの果てにようやくたどり着けるような、若干危険な香り漂うサイトとかだと、リダイレクト指定をちゃんとしてやらないと途中で泣きながら帰ってきてしまうケースもある。というかあった。

完全な解決策とはいきませんが、とりあえずこれだけ指定してやれば大丈夫だろ的なオプション設定を作ったので、どうぞ。

お約束ですがプロキシのIP/ポート番号とか取得先URLとかは自分の環境に合わせて適宜修正して下さいな。

各設定の詳細が知りたい勉強熱心な方は、文末に載せておいた参考サイトがおすすめです。勉強になります。

# Proxy用オプション設定(暫定最強Ver.)

$sc_opts = array(
‘http’=>array(
‘method’=> ‘GET’,
‘header’=>
“Host: www.tokiwasou.com\r\n” .
“Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n”.
“Accept-Language: ja,en-us;q=0.7,en;q=0.3\r\n”.
“Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.7\r\n”.
“Keep-Alive: 300\r\n”,
‘user_agent’ => ‘Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.9.0.10)’,
‘proxy’ => ‘tcp://192.168.0.XX:8888‘,
‘request_fulluri’ => True,
‘max_refirects’ => 20
)

参考になったサイト:
PHP.net(file_get_contents)

HTTPとHTTPS (コンテキストのオプションが載ってる)

 

Proxyを設定する

環境変数を参照してプロキシの有無を判別するアプリケーションならばこれでOK。

————————————————————

# vi /etc/profile.d/proxy.sh

export http_proxy=http://192.168.0.xx:8888/
export ftp_proxy=http://192.168.0.xx:8888/
export HTTP_PROXY=http://192.168.0.xx:8888/
export FTP_PROXY=http://192.168.0.xx:8888/

————————————————————

# vi /etc/profile.d/proxy.csh

setenv http_proxy http://192.168.0.xx:8888/
setenv ftp_proxy http://192.168.0.xx:8888/
setenv HTTP_PROXY http://192.168.0.xx:8888/
setenv FTP_PROXY http://192.168.0.xx:8888/

————————————————————

言い換えればhttp_proxyまたはHTTP_PROXYを参照しないアプリケーションでは意味がないです。念のため。

赤字の部分は自分の環境向けに適宜読みかえてね。

ちなみにproxy.csh は C Shell 用。標準のBourne Shellしか使わないのなら、proxy.shだけ設定してあげればOK。(だよね?)

参考サイト
Linux/環境変数の設定