【问题标题】:php script just stops even with set_time_limit(0)即使使用 set_time_limit(0),php 脚本也会停止
【发布时间】:2014-06-10 05:50:40
【问题描述】:

我查看了其他 10 篇似乎与我有相同问题的人的帖子,大多数人建议输入 set_time_limit(0);。但即使这样,无论我运行什么脚本,它总是在大约 9-10 分钟后停止。

我尝试了以下3个变量的多种组合,将它们设置为-109999999;只是总是停止。不久前,我在下面运行了完全相同的脚本。就在一天,我对任何脚本都有这个问题。

我 100% 确定它会在完成之前停止,并且不会因为错误而停止。因为我的任何脚本现在都在同一个应用运行时停止。

非常沮丧,任何帮助将不胜感激。

在 php.ini 中:

max_input_time = -1
max_execution_time = 0
set_time_limit = 0

另一个脚本:(同样在 10 分钟后停止)

<?php
set_time_limit(0);
ignore_user_abort(true);
function categoryinsert($english, $name, $keywords, $language)
{
    if(!$english)
    {
        echo "no english recieved! in categoryinsert<br />";
        return 0;
    }
    else if(!$name)
    {
        echo "no name recieved! in categoryinsert<br />";
        return 0;
    }
    else if(!$language)
    {
        echo "no language recieved! in categoryinsert<br />";
        return 0;
    }
    $DBConnect = mysqli_connect("localhost", "USER***", "************");
    mysqli_set_charset($DBConnect, "utf8");
    mysqli_select_db($DBConnect, "db***");

    $qwry = "INSERT INTO `categories` (english, name, keywords, language) values ('$english','$name','$keywords','$language');";
            $QueryResult = mysqli_query($DBConnect, $qwry);
            //Or die("<p>Unable to execute the query.[".$qwry."]<p>"
            //. "<p>Error code " . mysqli_errno($DBConnect)
            //. ": " . mysqli_error($DBConnect)) . "</p>"; 

            mysqli_close($DBConnect);
}
function checkfor($english, $lang)
{
    $DBConnect = mysqli_connect("localhost", "USER***", "************");
    mysqli_set_charset($DBConnect, "utf8");
    mysqli_select_db($DBConnect, "db***");

    $qwry = "SELECT * FROM `categories` where english = '$english' and language = '$lang';";
            $QueryResult = mysqli_query($DBConnect, $qwry);

            $Row = mysqli_fetch_row($QueryResult);

            mysqli_close($DBConnect);

            if($Row) return true;
            else return false;
}
function categoryupdate($keywords, $language, $english)
{
if(!$english)
    {
        echo "no english recieved! in categoryupdate<br />";
        return 0;
    }
    else if(!$keywords)
    {
        echo "no keywords recieved! in categoryupdate<br />";
        return 0;
    }
    else if(!$language)
    {
        echo "no language recieved! in categoryupdate<br />";
        return 0;
    }
    $DBConnect = mysqli_connect("localhost", "USER***", "************");
    mysqli_set_charset($DBConnect, "utf8");
    mysqli_select_db($DBConnect, "db***");

    $qwry = "UPDATE `categories` set keywords = '$keywords' where language = '$language' and language = '$language';";
            $QueryResult = mysqli_query($DBConnect, $qwry)
            Or die("<p>Unable to execute the query.[".$qwry."]<p>"
            . "<p>Error code " . mysqli_errno($DBConnect)
            . ": " . mysqli_error($DBConnect)) . "</p>"; 

            mysqli_close($DBConnect);
}
function translatekeywords($keywords, $tolang)
{

    if(!$keywords)
    {
        echo "no keywords recieved! in translatekeywords<br />";
        return 0;
    }
    else if(!$tolang)
    {
        echo "no tolang recieved! in translatekeywords<br />";
        return 0;
    }
    $parts = explode(", ", $keywords);
    $count = 0;
    $out = "";

    while($parts[$count])
    {
        if(($count != 0) and ($result)) $out = $out . ", ";
        $result = translate($parts[$count], 'eng', $tolang);
        if($result) $out = $out . $result;
        $count++;
    }

    return $out;
}
include '../functions.php';

$DBConnect = mysqli_connect("localhost", "USER***", "************");
    mysqli_set_charset($DBConnect, "utf8");
    mysqli_select_db($DBConnect, "db***");


            $qwry = "SELECT english, keywords FROM `categories` where language = 'eng' order by name ASC;";
            $QueryResult = mysqli_query($DBConnect, $qwry)
            Or die("<p>Unable to execute the query.[".$qwry."]<p>"
            . "<p>Error code " . mysqli_errno($DBConnect)
            . ": " . mysqli_error($DBConnect)) . "</p>"; 

            $count = 0;
            $Row = mysqli_fetch_row($QueryResult);

            do
            {
                $categories[$count] = $Row;             
                echo $count.') ['.$categories[$count][0].']['.$categories[$count][1].']<br />';
                $Row = mysqli_fetch_row($QueryResult);
                $count++;
            }while($Row);

            $qwry = "SELECT ISO3 FROM `languages` order by name ASC;";
            $QueryResult = mysqli_query($DBConnect, $qwry)
            Or die("<p>Unable to execute the query.[".$qwry."]<p>"
            . "<p>Error code " . mysqli_errno($DBConnect)
            . ": " . mysqli_error($DBConnect)) . "</p>"; 

            $count = 0;
            $Row = mysqli_fetch_row($QueryResult);

            do
            {
                $languages[$count] = $Row[0];
                $Row = mysqli_fetch_row($QueryResult);
                echo '['.$languages[$count].']<br />';
                $count++;
            }while($Row);

            $lcount = 0;
            do
            {
                if($languages[$lcount] != 'eng')
                {
                    $ccount = 0;
                    do
                    {
                        if(!checkfor($categories[$ccount][0], $languages[$lcount]))
                        {
                            $name = translate($categories[$ccount][0], 'eng', $languages[$lcount]);
                            if($categories[$ccount][1]) $keywords = translatekeywords($categories[$ccount][1],$languages[$lcount]);
                            categoryinsert($categories[$ccount][0], $name, $keywords, $languages[$lcount]);
                        }
                        $ccount++;
                    }while($categories[$ccount]);
                }

            $lcount++;
            }while($languages[$lcount]);

mysqli_close($DBConnect);
echo "FINISHED! [$lcount] languages proccessed";
?>

脚本:

<html>
<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"></head>
<body>
<?php 
set_time_limit(0);
ignore_user_abort(true);
include 'functions.php'; 

function insertsentence($sentence, $lang, $id, $user)
{
    if(($lang == 'epo') and (strlen($sentence) < 255) )
    {
        $DBConnect = mysqli_connect("localhost", "xxxxx_userx", "xxxxxxx!");
        mysqli_set_charset($DBConnect, "utf8");
        mysqli_select_db($DBConnect, "xxxxx_main");

            $insertqwry = "INSERT INTO `sentences` (sentence, user, id, language) VALUES ('".withslashes($sentence)."', '".withslashes($user)."', '".withslashes($id)."', '".withslashes($lang)."');";

        $QueryResult = mysqli_query($DBConnect, $insertqwry) ;
        //Or die("<p>Unable to execute the query.[".$insertqwry."]<p>"
        //. "<p>Error code " . mysqli_errno($DBConnect)
        //. ": " . mysqli_error($DBConnect)) . "</p>"; 

        mysqli_close($DBConnect);
return 1;
    }

}

$myFile = "sentences_detailed.csv"; 
$fh = fopen($myFile, 'r');
$s = fread($fh, 3);
if ($s != pack('CCC',0xef, 0xbb, 0xbf)) {
    // bom not found, rewind file
    fseek($fh, 0, SEEK_SET);
}

$count = 0;
ob_start();
do
{

    $line = preg_replace('/^\p{Z}+|\p{Z}+$/u', '', withslashes(trim(fgets($fh))));
    $parts = explode("  ", $line);
        $id = $parts[0];
        $lang = $parts[1];
        $sentence = withslashes($parts[2]);
        $user = withslashes($parts[3]);
        $note = "";


        if ((!$line) or ($line == "") or ($line == "!"))
        {
            echo ($count-1)." entries were processed<br />";
            echo "done<br />";
            exit();
        }



                if ($sentence != "!" )
                {
                    if (insertsentence($sentence, $lang, $id, $user))
                    echo "!";
                }

        ob_flush();
        flush();

    $count++;

    echo ".";

}while($line);

fclose($fh);
mysqli_close($DBConnect);

echo ($count-1)." entries were processed<br />";

?>
</body>
</html>

编辑:无论我运行什么脚本,或者它多么简单,它总是在大约 10 分钟后停止。所以我怀疑这与我脚本中的代码有什么关系。所以我要补充一点,我正在运行脚本的 Web 服务器位于 Bluehost

【问题讨论】:

  • 看起来像您的标准服务器超时。一个方便的解决方法是每隔一段时间在页面上打印一些内容,并保持连接处于活动状态。
  • 我正在打印“.”不是吗?
  • 你检查 PHP 日志了吗...?
  • 查看您的代码,insertsentence 不返回任何内容,因此“。”没有打印出来。
  • 像这样在每个插入上连接和断开连接并且不使用准备好的语句和/或事务非常低效,这并不能直接回答您的问题,所以我正在使用评论。

标签: php mysql


【解决方案1】:

答案是 bluehost 对我的帐户设置的限制。这是他给我的回复:

...
The Dedicated IP (+$3.33 per month) will increase the limits on the account.


    The following it the limits on how the server will kill processes with and without the Dedicated IP on the account: 

                                    With a Dedicated IP         Without Dedicated IP
Apache/Web (HTML/PHP/Downloads)     12 hours                    10 minutes
...

【讨论】:

    【解决方案2】:

    考虑使用 PHP 的 flush 函数,这样您就可以连续执行循环 - 我知道这不是最好的最终解决方案,但这可能对您有所帮助:)

    先看这个example

    【讨论】:

    • 你没有看我发布的脚本吗?我正在使用冲洗。看起来我使用它的方式与您的示例相同。
    • 你是否包含了 sleep(2);功能?
    • 不,我没有,文件有数百万行长,所以我不想让它花更长的时间。你觉得这个 sleep() 函数会有什么帮助?
    • 如果进程如此繁重,使用 sleep() 或 usleep() 是加载服务器的好主意 - 至少您可以尝试使用它;)
    【解决方案3】:

    一些想法。

    首先,您的代码调用了一个名为withslashes() 的函数,我认为这是一个自定义函数,旨在将斜杠(又名:转义)值添加到引号和其他字符但是您使用的是 MySQLi 调用,对吗?那么为什么不避免重新发明轮子,而只使用 MySQLi 扩展中的mysqli_real_escape_string() 呢?

    另外,我添加了mysqli_free_result(),它“释放与结果相关的内存”。即使您的查询结果只是确认查询已运行,​​这也不会造成伤害。

    我添加了一个 sleep() 的值`秒,以至少稍微限制进程,让您的服务器有喘息的空间。

    整个目标是使用内置的 PHP 函数来避免在运行 MySQL 查询时使用过多的 RAM 并将脚本暂停 1 秒以给它喘息的空间。

    这是insertsentence() 的重构版本,使用第一组想法来提高性能:

    function insertsentence($sentence, $lang, $id, $user) {
    
        if (($lang == 'epo') and (strlen($sentence) < 255)) {
            $DBConnect = mysqli_connect("localhost", "xxxxx_userx", "xxxxxxx!");
            mysqli_set_charset($DBConnect, "utf8");
            mysqli_select_db($DBConnect, "xxxxx_main");
    
            $insertqwry = "INSERT INTO `sentences` (sentence, user, id, language)"
                        . " VALUES ('$sentence', '$user', '$id', '$lang');"
                        ;
    
            // Escape the query.
            $insertqwry = mysqli_real_escape_string($DBConnect, $insertqwry);
    
            $QueryResult = mysqli_query($DBConnect, $insertqwry) ;
    
            // Free the result set.
            mysqli_free_result($QueryResult);
    
            mysqli_close($DBConnect);
    
            // Sleep for 1 second.
            sleep(1);
    
            return TRUE;
        }
    }
    

    但是为什么不使用mysqli_stmt_bind_param() 来充分利用MySQLi 的prepared statements 能力呢?然后你不再需要使用mysqli_real_escape_string(),因为准备好的语句基本上可以处理所有这些。

    考虑到这一点,这是insertsentence() 的另一个重构版本,它使用mysqli_stmt_bind_param()

    function insertsentence($sentence, $lang, $id, $user) {
    
        if (($lang == 'epo') and (strlen($sentence) < 255)) {
            $DBConnect = mysqli_connect("localhost", "xxxxx_userx", "xxxxxxx!");
            mysqli_set_charset($DBConnect, "utf8");
            mysqli_select_db($DBConnect, "xxxxx_main");
    
            $insertqwry = "INSERT INTO `sentences` (sentence, user, id, language)"
                        . " VALUES (?, ?, ?, ?);"
                        ;
    
            // Bind the values to the statement.
            mysqli_stmt_bind_param($insertqwry, 'ssis', $sentence, $user, $id, $lang);
    
            $QueryResult = mysqli_query($DBConnect, $insertqwry) ;
    
            // Free the result set.
            mysqli_free_result($QueryResult);
    
            mysqli_close($DBConnect);
    
            // Sleep for 1 second.
            sleep(1);
    
            return TRUE;
        }
    }
    

    注意mysqli_stmt_bind_param() 中的'ssds'。每个字母确定您的 4 个值的类型。所以在这种情况下,它是字符串 (sentence)、字符串 (user)、整数 (id)、字符串 (language),这是我根据你给我的数据的最佳猜测。

    【讨论】:

    • mysqli_free_result 真的应该追随 mysqli_close 吗?
    • @user1397417 不。已更正。
    【解决方案4】:

    听起来您的脚本受服务器限制。我认为您可以在 php.ini 中更改它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-02-17
      • 1970-01-01
      • 2018-01-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-01
      相关资源
      最近更新 更多