パソコンQ&A

PHPのタイムアウト対策

Fatal error: Maximum execution time of 30 seconds exceeded in 【PHPファイル名】
について

PHPでタイムアウトエラー(Time out error)が出るとき、プログラムを見直して処理時間を短くする。

処理に時間がかかる場合はタイムアウトまでの時間を変更する。
php.iniのmax_excution_timeoutで変更することもできるが、これだと全てのPHPに影響するので各PHPファイルの先頭に設定したほうがいいかも。

(1)90秒にするには
set_time_limit(90);
(2)無制限にするには
set_time_limit(0);
注意:無制限にした場合は無限ループしないように

ただしapacheのtimeoutにも依存する


サーバー側(PHP・apache)のタイムアウトを長くしてもブラウザ側のタイムアウトがある。
(1)出力をバッファリングしない
ob_end_clean();

(2)出力をフラッシュする
flush();

Internet Explorerは256バイトの出力がないと表示しないので、256バイト空文字を出力する必要がある。
これについてはPHPマニュアルのflushの項にも書かれている。
echo str_pad('',256);

この処理は負荷がかかるのでサーバー会社によっては怒られることがあります。注意してください。

SAFE_MODEになっている場合
セーフモードでは時間制限を変更することができません。
このため繰り返し処理などは何度かに分けて処理するようにします。
時々ページを表示させて、自動的にPHPの処理に戻るといった感じです。

<?
  $diff= (isset($_GET['diff']))? $_GET['diff'] : 0;
  $unit=10;
  $max=100;
  $mmm="";

  ob_end_clean();

  for($i=$diff;$i<$diff+$unit && $i<$max;$i++){

〜〜〜〜〜〜
〜〜〜〜
〜〜〜〜〜〜

//printやechoは使えないので
//メッセージはこのように書きます。
    $mmm.="〜〜〜";

//ときどきブラウザにパケットを送ったほうがタイムアウトは防げます。
  echo str_pad('',256);
  flush();
  }

  if($diff+$unit<$max){
?>
<html>
<head>
<META http-equiv=Refresh content="1; URL=<?=$_SERVER['PHP_SELF']?>?diff=<?=($diff+$unit)?>">
</head>
<body>
<?=$mmm?>
</body>
</html>
<?
    exit;
  }else{
    echo $mmm;
    echo "終わりました";
    exit;
  }
?>

メッセージで進み具合が見れるようにしていますし、 時々パケットを送ったほうがいいので次のようなヘッダーでのページ変更はできないのです。

header("HTTP/1.1 301 Moved Permanently");
header("Location: ".$_SERVER['PHP_SELF']);
exit;


さらにサーバーのタイムアウトなどを考えると次のようになります。
処理が途中で途切れてしまったら、もう一度同じ処理をするような感じです。
これは下手をしたら延々処理を繰り返すことにもなりますので、どうしてもというとき以外は使わないほうがいいです。

やるとしてもマナーとして午前2時〜午前6時ぐらいの比較的アクセスの少ない時間帯に使用するか、自分でサーバーを作ってその中で行ったほうがいいでしょう。

<?
  $diff= (isset($_GET['diff']))? $_GET['diff'] : 0;
  $unit=10;
  $max=100;
  $mmm="";

  ob_end_clean();
?>
<html>
<head>
<script language="JavaScript"><!--
function PageJump(){
  if ('function' === typeof window.PageJump2){
   PageJump2();
  } else {
    location.href = "<?=$_SERVER['PHP_SELF']?>?diff=<?=$diff?>";
  }
}

setTimeout("PageJump()",60000);

// --></script>
</head>
<body onLoad="PageJump();">
<?
  echo str_pad('',256);
  flush();

  for($i=$diff;$i<$diff+$unit && $i<$max;$i++){

〜〜〜〜〜〜
〜〜〜〜
〜〜〜〜〜〜

//このやり方ではprintやechoは使えますが、そのあとにflush();をしないと表示されません。

//ときどきブラウザにパケットを送ったほうがタイムアウトは防げます。
  echo str_pad('',256);
  flush();
  }

  if($diff+$unit<$max){
?>
<script language="JavaScript"><!--
function PageJump2(){
  location.href = "<?=$_SERVER['PHP_SELF']?>?diff=<?=($diff+$unit)?>";
}
// --></script>
</body>
</html>
<?
    exit;
  }else{
?>
終わりました <script language="JavaScript"><!--
function PageJump2(){
  location.href = "./";
}
// --></script>
</body>
</html>
<?
    exit;
  }
?>

このページはリンクフリーです。設定などは自己責任で…
Copy Right kikky

kikky.net