Error 500 – Internal Server Error

През последните няколко седмици непрекъснато се тормозех от следната грешка:

HTTP Error 500 – Internal server error

Не стига, че че нямам свестен достъп до error log-а на уеб сървъра (само някакъв окастрен уеб интерфейс), ами и грешката се появяваше произволно без някаква логика. Единствената следа в логовете беше съобщението

[error] [client 304.608.192.724] Premature end of script headers: /home/user/www/toshe/blog/index.php

Малкото ми разследване първоначално показа, че в скрипта за пренасочване на индекс-а към директорията на блог-а му липсват двата знака за нов ред “\n\n”, които се изискват след заглавната част на HTTP протокола. Дотук добре. Само че грешката продължаваше да се появява в логовете, но по-рядко.

Реших да сменя пренасочването от PHP скрипт към чист HTML с META REFRESH тагове, но тогава се появи неприятно мигане и забавяне при зареждане. Това можеше да се преживее, но .. грешката упорите продължаваше да ми се присмива от лог-а. Писах писмо на поддръжката на моя доставчик, но оттам ми отговориха, че при тях всичко е наред и да се обърна към създателя на скрипта, понеже те не отговарят за инсталирания от клиента софтуер. След като ги “благослових” няколко пъти реших, че е крайно време да си припомня добрите стари времена и да се заема с истинско дебъгване. На PHP не бях прорамирал достатъчно дълго, за да забравя неприятния стил на смесване на HTML тагове и програмен код. Добре поне, че авторите на WordPress са минималисти и кода им се чете сравнително лесно. Само че не е толкова лесно да се дебъгне. Първия ми опит се провали с гръм и трясък – единствения резултат бе, че си затлачих яко блог-а до степен, че да не се показва нищо на заглавната страница. Таня както винаги се погрижи да не оставам прекалено дълго на компютъра и след като възстанових оригиналните файлове (споменах ли че правя архивни копия на почти всичко, особено когато пипам по него:) ) зарязах нещата за по-добри времена. Междувременно мозъка ми продължи да работи по въпроса и на следващия ден почти бях сигурен какъв може да е причината за проблема – от доставчика ми хостват множество виртуални хостове на една машина – вярно, мощен сървър, само че с ограничения откъм процесорното време. Ако някоя заявка или клиент на сървъра изконсумира повече от определеното му време, просто процеса му се “замразява” докато натоварването на процесорите намалее. По-този начин се избягват твърде лакомите скриптове на едни потребители да “изядат” процесорното време на останалите. След като получавах съобщение ” Premature end of script headers” значи явно моите скриптове (разбирай скриптовете на блог софтуера) консумират твърде много време и най-вероятно биват терминирани преди да изработят цялата уеб страница на блог-а. Понеже всичките постинги се съхраняват в MySQL база данни, най-вероятно заявките и/или информацията от тях отнема твърде много време да бъдат обработени и ако отнемат твърде много процесорно време – биват прекратявани междувременно. И съответно се получава “недоизработен” отговор на уеб заявката, коети води и до съответната грешка в error log-а. Зареден с тази теоретична постановка, реших да я докажа. Наложи се да напиша една кратичка функция на PHP, която да записва в текстов файл прости съобщения и времето на извикване на функцията. Като поставям извиквания към тази функция на определени места във скриптовете ще мога да определя относителното време за обработката на съответните части от скрипта. Ето я и самата функция:

function toshe_debug($message){
      $fname = “/var/www/test/debuglog.txt”;
      $logtime = date(“Y/m/d H:i:s T”) . ” debug: “;
      $handle = fopen($fname,”a”); // open file for appending
      fwrite($handle, $logtime . $message . “n”);
      fclose($handle);
}

Единствения проблем може да се появи ако уеб сървъра няма права за писане в съответната директория, но мисля че всеки що-годе запознат с UNIX/Linux администриране ще успее да се справи с проблема (айде за домашно) 😀

Следващата стъпка беше да “разчленя” дебъгвания файл (в случая index.php) на части и да извиквам функцията във всеки от блоковете. След няколко експеримента ето и резултата:

2005/02/05 16:12:02 EST debug: wp-blog-header.php start
2005/02/05 16:12:02 EST debug: wp-blog-header.php end
2005/02/05 16:12:02 EST debug: index.php start
2005/02/05 16:12:02 EST debug: index.php     head start
2005/02/05 16:12:02 EST debug: index.php     head end
2005/02/05 16:12:02 EST debug: index.php     body start
2005/02/05 16:12:02 EST debug: index.php        posts start
2005/02/05 16:12:02 EST debug: index.php            post content start
2005/02/05 16:12:02 EST debug: index.php            post content end
2005/02/05 16:12:02 EST debug: index.php            post feedback start
2005/02/05 16:12:02 EST debug: index.php            post feedback end
2005/02/05 16:12:02 EST debug: index.php            post rdf start
2005/02/05 16:12:02 EST debug: index.php            post rdf end
2005/02/05 16:12:02 EST debug: index.php        posts end
2005/02/05 16:12:02 EST debug: index.php        posts start
2005/02/05 16:12:02 EST debug: index.php            post content start
2005/02/05 16:12:02 EST debug: index.php            post content end
2005/02/05 16:12:02 EST debug: index.php            post feedback start
2005/02/05 16:12:02 EST debug: index.php            post feedback end
2005/02/05 16:12:02 EST debug: index.php            post rdf start
2005/02/05 16:12:02 EST debug: index.php            post rdf end
2005/02/05 16:12:02 EST debug: index.php        posts end
…..
2005/02/05 16:12:09 EST debug: index.php      menu start
2005/02/05 16:12:09 EST debug: index.php      menu end
2005/02/05 16:12:09 EST debug: index.php     body end
2005/02/05 16:12:09 EST debug: index.php end

Добихте ли представа кое отнема най-много време? Изненадващо за мен, не беше часта с header-ите. Най-много време отнема обработката на постингите. Ако човек се поразрови по-надълбоко из скриптовете (нещо, което направих през първия опит) ще види, че авторите използват един лесен за прилагане, но доста хабящ ресурси метод – генерират се заявки “в движение” и после се пускат към уеб сървъра. Проблемът е, че ако това отнеме твърде много време (както е в случая) ядрото прекъсва процеса и тъй като PHP модула кешира съдържанието преди да ги изпрати на уеб сървъра, последния не получава цялата уеб страница, а само заглавната и част. И това води до грешката в лог-а. Малко по-задълбочено разследване показа, че най-бавна е функцията the_content(), но не ми се задълбаваше чак толкова надълбоко. Някой друг път може би.

Добре де, сума ти философия дотук, но какъв е извода и какво да се направи, за да се реши проблема? Ами както винаги сложните проблеми имат извънредно просто решение – щом обработката на заявките отнема толкова много време, ще ги намалим. И вместо на заглавната страница на блог-а да има 15 постинга, ще има … да кажем 5. Voila. Грешката изчезна. Няма я. Край. Finito. Капут. Поне до следващия път 😉

Целта на цялото това упражнение беше най-сетне да може блог-а на Тошето и Таня да се чете нормално, без дразнещите грешки. Но като страничен ефект си направих следните изводи:

  • другия път да внимавам повече като си избирам хостинг компания
  • винаги е полезно човек първо да помисли и събере информация, преди да тръгне с главата напред да дебъгва и програмира
  • не забравяй правилото KISS – Keep It Simple Stupid (в свободен превод – “придържай се към простотата” 🙂 )

Е, дано този челен опит да помогне поне на някой и да му спести главобъскането през което минах аз.

Наздраве.

4 thoughts on “Error 500 – Internal Server Error

  1. Не искам да ти развалям кефа, но след като свърших четенето, кликнах на Toshe and Tanya’s blog и познай какво стана:
    Internal server error
    Please try again in a few minutes.
    If the problem persist, please contact todor[at]bukov[dot]com about it.
    THz

  2. Не съм и очаквал проблема да се реши толкова лесно. По-важното е, че грешките намаляха до по-приемливо ниво. Мисля, че знам къде още трябва да пипна, но първо ще направя още малко тестове.
    Ако има проблеми – не се срамувай да пишеш пак. Само посочи времето, за да сравня с логовете.

  3. Ами сложи го 1 минута преди постването на коментара.
    Наистина сега грешката се появява доста по-малко.

  4. Много благодаря за ценната информация! След като прочетох този блог успях да разбера какъв е проблема на хостинг сървъра на който пиша скрипт за обработка на изображения и нямам достап дори до логовете. Когато скрипта се опита да отвори jpeg с размер над 3мб изкача тази грешка. За малки картинки няма проблем. Наистина избора на хостинг компания е решаващ! Благодарности още веднъж!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.