Журнал LinuxFormat - перейти на главную

LXF171:Рубрика сисадмина

Материал из Linuxformat
Перейти к: навигация, поиск

По рецептам доктора Брауна

Содержание

Эзо­те­ри­че­ское сис­тем­ное ад­ми­ни­ст­ри­ро­ва­ние из при­чуд­ли­вых за­во­ро­тов ки­шок сер­вер­ной

(thumbnail)
Д-р Крис Браун. Доктор обучает, пишет и консультирует по Linux. Ученая степень по физике элементарных частиц ему в этом совсем не помогает.

Ко­рот­ко о Tomcat

Бе­ре­ги­те мышь — мы вы­пус­ка­ем Tomcat, зна­ко­мим­ся с Java и пи­шем серв­лет.

На­чи­ная с са­мо­го на­ча­ла: Tomcat [англ. котяра] — это web-сер­вер. Как и Apache, он вла­де­ет язы­ком про­то­ко­ла HTTP и от­ве­ча­ет на за­про­сы брау­зе­ра о ста­ти­че­­ском кон­тен­те — HTML-фай­лах и изо­бра­же­ни­ях. Но Tomcat бо­лее узко спе­циа­ли­зи­ро­ван, чем Apache: его ис­тин­ное при­зва­ние — быть кон­тей­не­ром серв­ле­тов Java. Это оз­на­ча­ет, что он способен хра­нить ди­на­ми­че­­ски ге­не­ри­руе­мые web-стра­ни­цы, ис­поль­зую­щие Java как язык на сто­ро­не сер­ве­ра. Су­ще­ст­ву­ет стан­дарт, под­роб­но опи­сы­ваю­щий сре­ду, где бу­дут за­пус­кать­ся эти при­ло­же­ния, и Tomcat из­на­чаль­но раз­ра­ба­ты­вал­ся как реа­ли­за­ция данно­го стан­дар­та.

В пер­вой час­ти нашей се­рии из двух ста­тей мы нач­нем с ус­та­нов­ки па­ке­тов, не­об­хо­ди­мых для за­пус­ка Tomcat, а за­тем по­смот­рим, как раз­вер­нуть про­стое web-при­ло­же­ние из двух стра­ниц. Как и на дру­гих сво­их уро­ках в этом жур­на­ле, я бу­ду ра­бо­тать с чис­той ус­та­нов­кой CentOS 6.2, и ес­ли вы хо­ти­те сле­до­вать за мной, мо­же­те на­чать с ус­та­нов­ки CentOS на вир­ту­аль­ную ма­ши­ну.

(thumbnail)
> Установите эти пакеты с yum, чтобы получить рабочую конфигурацию Tomcat. Пакет javasdk нужен только для компиляции своих сервлетов. Но вы же будете их делать, правда?

Со­би­ра­ем час­ти вме­сте

Спер­ва ус­та­но­вим не­об­хо­ди­мые ком­по­нен­ты. Все не­об­хо­ди­мое есть в ре­по­зи­то­ри­ях CentOS, и нам нуж­но лишь вы­тя­нуть от­ту­да не­об­хо­ди­мые па­ке­ты с по­мо­щью yum. В таб­ли­це при­ве­де­ны пять па­ке­тов, ко­то­рые нам по­тре­бу­ют­ся; итак, при­сту­пай­те и вы­пол­ни­те ко­ман­ду yum install с ка­ж­дым из них. Я по­до­ж­ду, по­ка вы за­кон­чи­те...

Ну вот, Tomcat ус­та­нов­лен, и нуж­но за­пус­тить сер­вер, по­за­бо­тив­шись, что­бы по­сле пе­ре­за­груз­ки сис­те­мы он за­пус­кал­ся ав­то­ма­ти­че­­ски. Нам по­мо­гут следующие две ко­ман­ды (за­пус­ти­те их от име­ни суперпользователя-root):

# service tomcat6 start
# chkconfig tomcat6 on

Так как мы ус­та­но­ви­ли па­кет tomcat6-webapps, ко­то­рый фор­ми­ру­ет до­маш­нюю стра­ни­цу по умол­ча­нию, те­перь мож­но от­крыть брау­зер, зай­ти на http://localhost:8080 и по­лу­чить в на­гра­ду до­маш­нюю стра­ни­цу, по­ка­зан­ную на сним­ке эк­ра­на. Уч­ти­те, что по умол­ча­нию Tomcat слу­ша­ет порт 8080 (а не 80), по­это­му его нуж­но ука­зать в ад­ре­се. На этой стра­ни­це есть ссыл­ки на до­ку­мен­та­цию Tomcat (ко­то­рую мы так­же ус­та­но­ви­ли, из па­ке­та tomcat6-docswebapps), и здесь вы мо­же­те лег­ко ув­лечь­ся и по­тра­тить ос­та­ток дня на чте­ние. Так­же есть ссыл­ки на не­сколь­ко при­ме­ров ко­да.


Наш пер­вый серв­лет

При­сту­пим к де­лу и по­смот­рим, как раз­вер­нуть на Tomcat про­стой серв­лет. Что­бы не­мно­го ус­лож­нить тра­ди­ци­он­ную “hello world”, мы соз­да­дим web-при­ло­же­ние из двух стра­ниц. Пер­вая стра­ни­ца — чис­тый HTML: на ней есть фор­ма с тек­сто­вым по­лем, где поль­зо­ва­тель дол­жен вве­сти свое имя, и кноп­ка для от­прав­ки фор­мы серв­ле­ту. Вто­рая стра­ни­ца — серв­лет. Она про­сто при­вет­ст­ву­ет поль­зо­ва­те­ля по име­ни, по­лу­чен­но­му из тек­сто­во­го по­ля на фор­ме.

Фор­ма

Нач­нем с фор­мы. Ниже приведен ее код. По­ка про­сто по­мес­ти­те ее в файл formexample.html в сво­ем ка­та­ло­ге home. Поз­же мы ско­пи­ру­ем ее ку­да по­ла­га­ет­ся.

<html>

<head>

<title> Про­стой при­мер фор­мы </title>

</head>

<body>

Про­стой при­мер фор­мы

<form action=”pootle” method=”GET”>

Вве­ди­те ва­ше имя:

<INPUT type=”text” name=”name” />

<INPUT type=”submit” name=”Submit” value=”Submit Name”>

</form>

</body>

</html>


Сам серв­лет

Те­перь зай­мем­ся ко­дом на­ше­го серв­ле­та. В нем все­го од­на «ак­тив­ная» стро­ка — она об­ра­ща­ет­ся к дан­ным, вве­ден­ным в фор­му. Од­на­ко что­бы быть серв­ле­том, класс Java дол­жен на­сле­до­вать­ся от ба­зо­во­го клас­са HttpServlet. По­это­му во­круг этой един­ст­вен­ной стро­ки ко­да потребуется не­боль­шая оберт­ка. Для на­чи­наю­щих — нам надо оп­ре­де­лить класс, на­сле­дуе­мый от HttpServlet. Внут­ри это­го клас­са следует на­пи­сать ме­тод doGet(), ко­то­рый Tomcat будет вы­зы­вать, ко­гда брау­зер поль­зо­ва­те­ля вы­пол­нит за­прос HTTP GET к на­шей стра­ни­це. Так­же мож­но на­пи­сать ме­тод doPost() для об­ра­бот­ки за­про­сов HTTP POST. За­тем идет внут­рен­ний слой оберт­ки — он не­об­хо­дим, по­то­му что мы хо­тим вер­нуть брау­зе­ру пра­виль­но сфор­ми­ро­ван­ный до­ку­мент HTML, и нуж­но вклю­чить ос­нов­ные струк­тур­ные тэ­ги HTML, та­кие как <head> и <body>.

Ко­ро­че, вот каким получается код на­ше­го серв­ле­та (но­ме­ра строк при­ве­де­ны для удобства ссы­лок, они не яв­ля­ют­ся ча­стью фай­ла):

1. import java.io.*;

2. import javax.servlet.*;

3. import javax.servlet.http.*;

4. /* Очень про­стой серв­лет для дос­ту­па в по­ля фор­мы */

5. public class FormExample extends HttpServlet {

6. public void doGet(HttpServletRequest request,

7. HttpServletResponse response)

8. throws IOException, ServletException

9. {

10. response.setContentType(“text/html”);

11. PrintWriter out = response.getWriter();

12. out.println(“<html> <head>”);

13. out.println(“<title> Form Example </title>”);

14. out.println(“</head> <body>”);

15. out.println(“

Hello “ + request.getParameter(“name”) + “

”);

16. out.println(“</body> </html>”);

17. }

18. }

Рас­смот­рим ос­нов­ные стро­ки это­го фай­ла. В стро­ке 5 за­да­ет­ся наш класс (FormExample), а стро­ки 6 – 17 со­дер­жат ме­тод doGet(). Этот ме­тод по­лу­ча­ет два па­ра­мет­ра: request (стро­ка 6) и response (стро­ка 7). Мы ис­поль­зу­ем объ­ект request для дос­ту­па к по­лю фор­мы (стро­ка 15), а объ­ект response — для дос­ту­па к по­то­ку PrintWriter (стро­ка 11), с по­мо­щью ко­то­ро­го со­дер­жи­мое от­прав­ля­ет­ся об­рат­но брау­зе­ру (стро­ки 12 – 16).

Ес­ли вы сле­дуе­те за мной, соз­дай­те этот файл, на­зо­ви­те его FormExample.java и ском­пи­ли­руй­те его ко­ман­да­ми

$ export CLASSPATH=.:/usr/share/java/servlet.jar

$ javac FormExample.java

В том случае, ес­ли все прой­дет хо­ро­шо, вы бу­де­те воз­на­гра­ж­де­ны фай­лом FormExample.class. Он со­дер­жит ском­пи­ли­ро­ван­ный байт-код Java для это­го клас­са. Уч­ти­те, что Java раз­бор­чи­ва на­счет имен фай­лов. Код клас­са FormExample обязан на­хо­дить­ся в фай­ле FormExample.class.

Еще один файл, без ко­то­ро­го нам ни­как не обой­тись для за­пус­ка при­ло­же­ния — де­ск­рип­тор раз­вер­ты­ва­ния web.xml. В нем мож­но за­дать все, что угод­но, но мы лишь свя­зы­ва­ем «шаб­лон URL-ад­ре­са» с име­нем серв­ле­та и имя серв­ле­та — с клас­сом, ко­то­рый его реа­ли­зу­ет. (Ко­неч­но, на XML это вы­ра­жа­ет­ся го­раз­до длин­нее.) Для на­ше­го при­ме­ра де­ск­рип­тор вы­гля­дит так:

<web-app>

<description> Form Example Servlet </description>

<display-name> Form Example </display-name

<servlet>

<servlet-name>FormExampleServlet</servlet-name>

<servlet-class>FormExample</servlet-class>

</servlet>

<servlet-mapping>

<servlet-name>FormExampleServlet</servlet-name>

<url-pattern>/pootle</url-pattern>

</servlet-mapping>

</web-app>

Ие­рар­хия раз­вер­ты­ва­ния

У нас есть три фай­ла (фор­ма, серв­лет и де­ск­рип­тор раз­вер­ты­ва­ния), и мы го­то­вы раз­вер­нуть при­ло­же­ние. В спе­ци­фи­ка­ции J2EE оп­ре­де­ля­ет­ся очень чет­кая струк­ту­ра ка­та­ло­гов, по­ка­зан­ная на ри­сун­ке. Что­бы уп­ро­стить себе жизнь, мы раз­ме­ща­ем «кор­не­вой ка­та­лог до­ку­мен­та» при­ло­же­ния в var/lib/tomcat6/webapps, по­то­му что лю­бое при­ло­же­ние в этом ка­та­ло­ге ав­то­ма­ти­че­­ски раз­вер­ты­ва­ет­ся при за­пус­ке Tomcat.

Ба­зо­вый на­бор ка­та­ло­гов мож­но соз­дать все­го не­сколь­ки­ми ко­ман­да­ми:

# cd /var/lib/tomcat6/webapps
# mkdir -p FormExample/WEB-INF/classes

Здесь мож­но не­мно­го по­иг­рать с пра­ва­ми дос­ту­па, что­бы по­лу­чить воз­мож­ность ко­пи­ро­вать фай­лы в этот ка­та­лог, не бу­ду­чи ад­ми­ни­ст­ра­то­ром. Вот воз­мож­ное ре­ше­ние. Для на­ча­ла сде­лай­те ва­ше­го поль­зо­ва­те­ля чле­ном груп­пы tomcat (эту ко­ман­ду нуж­но вы­пол­нять от име­ни root):

# usermod -a -G tomcat chris

За­ме­ни­те имя поль­зо­ва­те­ля на свое (ес­ли толь­ко вам не по­везло быть мо­им тез­кой). По­том из­ме­ни­те груп­пу фай­лов в ка­та­ло­ге раз­вер­ты­ва­ния на tomcat и до­бавь­те пра­во для груп­пы на за­пись та­ким об­ра­зом:

# cd /var/lib/tomcat6/webapps
# chown -R root:tomcat FormExample
# chmod -R g+w FormExample

Да­лее вер­ни­тесь в ка­та­лог, где ком­пи­ли­ро­ва­ли файл Java, и ско­пи­руй­те его в долж­ный ка­та­лог:

$ cp FormExample.class /var/lib/tomcat6/webapps/FormExample/WEB-INF/classes

(Кста­ти, вы ведь знае­те, как поль­зо­вать­ся ав­то­до­пол­не­ни­ем, не так ли? Ме­ня очень огор­чит, ес­ли кто-то на­би­рал всю стро­ку вруч­ную...)

За­тем ско­пи­руй­те фор­му в долж­ный ка­та­лог. Это про­стой ста­ти­че­­ский кон­тент, и он раз­ме­ща­ет­ся в ка­та­ло­ге HelloWorld, но вне ка­та­ло­га WEB-INF. Для дос­ту­па к на­ше­му при­ло­же­нию мы про­сто об­ра­тим­ся к это­му фай­лу.

$ cp formexample.html /var/lib/tomcat6/webapps/FormExample

На­ко­нец, ско­пи­руй­те ту­да же де­ск­рип­тор раз­вер­ты­ва­ния. Этот файл дол­жен по­пасть в ка­та­лог WEB-INF:

$ cp web.xml /var/lib/tomcat6/webapps/FormExample/WEBINF

Мы ско­пи­ро­ва­ли все фай­лы в долж­ный ка­та­лог, и са­мый про­стой спо­соб раз­вер­нуть при­ло­же­ние — пе­ре­за­пус­тить сер­вер:

# service tomcat6 restart

Те­перь (настал мо­мент ис­ти­ны!) от­крой­те http://localhost:8080/FormExample/formexample.html, вве­ди­те свое имя в тек­сто­вое по­ле и на­жми­те на кноп­ку, что­бы от­пра­вить фор­му серв­ле­ту.

Мож­но сде­лать ссыл­ку на фор­му под на­зва­ни­ем index.html та­ким об­ра­зом:

$ cd /var/lib/tomcat6/webapps/FormExample

$ ln formexample.html index.html

Это по­зво­лит вам об­ра­щать­ся к при­ло­же­нию по бо­лее ко­рот­ко­му ад­ре­су — http://localhost:8080/FormExample.

Ес­ли вы хо­ти­те соз­дать чуть бо­лее ди­на­мич­ную стра­ни­цу, вер­ни­тесь к ис­ход­но­му ко­ду серв­ле­та и до­бавь­те стро­ку

out.println(“The time is “ + new java.util.Date());

ко­то­рая вы­ве­дет те­ку­щие вре­мя и да­ту. За­тем пе­ре­ком­пи­ли­руй­те файл и ско­пи­руй­те его в долж­ное ме­сто в ие­рар­хии раз­вер­ты­ва­ния. Пе­ре­за­пус­ти­те сер­вер, и при­ло­же­ние бу­дет раз­вер­ну­то.

Ме­нед­жер

Пе­ре­за­пус­кать сер­вер для ка­ж­до­го раз­во­ра­чи­ва­ния при­ло­же­ния — до­воль­но бру­таль­ная вещь. Сей­час я по­ка­жу спо­соб по­лу­чше. В Tomcat есть при­ло­же­ние Ме­нед­жер (мы ус­та­но­ви­ли его как часть па­ке­та tomcat6-admin-webapps), дос­туп­ное на http://localhost:8080/manager/html или по ссыл­ке «Tomcat Manager» на до­маш­ней стра­ни­це. Од­на­ко пре­ж­де чем им вос­поль­зо­вать­ся, нуж­но кое-что на­стро­ить, по­то­му что Tomcat даст дос­туп к это­му при­ло­же­нию, толь­ко ес­ли вы ау­тен­ти­фи­ци­руе­тесь как поль­зо­ва­тель — член ро­ли ‘manager’, а в кон­фи­гу­ра­ции по умол­ча­нию та­ко­го поль­зо­ва­те­ля нет. Что­бы это ис­пра­вить, от­крой­те файл /etc/tomcat6/tomcat-users.xml и до­бавь­те ту­да та­кие стро­ки:

<role rolename=”manager”/>

<user username=”tomcat” password=”tomcatpw” roles=”manager”/>

Убе­ди­тесь, что до­бав­ляе­те эти стро­ки в тэг <tomcatusers>. Имя поль­зо­ва­те­ля не име­ет зна­че­ния, ес­ли он член ро­ли manager. Пе­ре­за­пус­ти­те сер­вер еще раз и пе­рей­ди­те по ссыл­ке ‘Tomcat Manager’ на до­маш­ней стра­ни­це. От­кро­ет­ся ок­но ме­нед­же­ра web-при­ло­же­ний Tomcat со спи­ском всех за­пу­щен­ных при­ло­же­ний. Здесь мож­но ос­та­но­вить или за­пус­тить при­ло­же­ние, пе­ре­за­гру­зить или свер­нуть его.

Это так­же мож­но де­лать с ко­манд­ной стро­ки, за­хо­дя на со­от­вет­ст­вую­щие ад­ре­са ме­нед­же­ра. На­при­мер, что­бы по­лу­чить спи­сок всех ра­бо­таю­щих при­ло­же­ний, мож­но за­пус­тить wget та­ким об­ра­зом (я не­мно­го со­кра­тил вы­вод):

$ wget --user tomcat --password tomcatpw -O - http://localhost:8080/manager/list

OK - Listed applications for virtual host localhost

/:running:0:ROOT

/manager:running:6:manager

/sample:running:0:sample

/docs:running:0:docs

/examples:running:0:examples

/FormExample:running:0:FormExample

/host-manager:running:0:host-manager

/HelloWorld:running:0:HelloWorld

Дру­гой при­мер — пе­ре­за­гру­зим на­ше при­ло­же­ние FormExample:

$ wget --user tomcat --password tomcatpw -O - http://localhost:8080/manager/reload?path=/FormExample

OK - Reloaded application at context path /FormExample

WAR [вой­на] (и мир)

Аль­тер­на­ти­ва раз­вер­ты­ва­нию при­ло­же­ния в ие­рар­хию «рас­па­ко­ван­ных» ка­та­ло­гов — соз­да­ние еди­но­го фай­ла WAR и раз­вер­ты­ва­ние его. Файл WAR (Web Application Archive — ар­хив web-при­ло­же­ния) — про­сто файл JAR (Java Archive — ар­хив Java) ие­рар­хии раз­вер­ты­ва­ния. Фай­лы JAR по­хо­жи на ар­хи­вы tarball, и син­так­сис ко­ман­ды jar, ко­то­рая их соз­да­ет, поч­ти полностью иден­ти­чен син­так­си­су tar.

Пре­иму­ще­ст­во фай­лов WAR пе­ред фай­ла­ми tarball в том, что мож­но рас­про­стра­нять и раз­во­ра­чи­вать це­лое web-при­ло­же­ние в од­ном фай­ле. Один из не­дос­тат­ков — слож­нее бу­дет вы­пол­нять не­боль­шие из­ме­не­ния (на­при­мер, из­ме­нить все­го од­ну стро­ку ко­да в од­ном серв­ле­те), по­то­му что ка­ж­дый раз по­сле это­го при­дет­ся сно­ва ге­не­ри­ро­вать и раз­вер­ты­вать файл WAR.

Да­вай­те раз­вер­нем на­ше при­ло­же­ние FormExample в ви­де фай­ла WAR. Сна­ча­ла соз­дай­те ар­хив. Так как при­ло­же­ние уже раз­ло­же­но по не­об­хо­ди­мой струк­ту­ре ка­та­ло­гов, это лег­ко:

$ cd /var/lib/tomcat6/webapps/FormExample

$ jar cf ~/FormExample.war .

Здесь я соз­дал ар­хив в сво­ем до­маш­нем ка­та­ло­ге. Про­верь­те со­дер­жи­мое ар­хи­ва ко­ман­дой

$ jar tf ~/FormExample.war

Те­перь уда­ли­те ис­ход­ную струк­ту­ру ка­та­ло­гов и пе­ре­за­пус­ти­те Tomcat (от име­ни root):

# rm -r /var/lib/tomcat6/webapps/FormExample
# service tomcat6 restart

Сей­час на­ше при­ло­же­ние FormExample уже не раз­вер­ну­то. Затем пе­рей­ди­те на до­маш­нюю стра­ни­цу Tomcat и на этой странице воспользуйтесь ссыл­кой для вхо­да в при­ло­же­ние ме­нед­же­ра. Про­кру­ти­те стра­ни­цу вниз до раз­де­ла Deploy [Раз­вер­ты­ва­ние]. Вве­ди­те /FormExample в ок­не Context Path [Кон­тек­ст­ный путь] и /home/chris/FormExample.war в по­ле WAR URL, за­тем на­жми­те Deploy [Раз­вер­нуть]. Про­кру­ти­те стра­ни­цу вверх и про­верь­те на­ли­чие со­об­ще­ния, под­твер­ждаю­ще­го, что при­ло­же­ние бы­ло раз­вер­ну­то. (Ес­ли не по­лу­чи­лось, про­верь­те пра­ва дос­ту­па к до­маш­не­му ка­та­ло­гу и к фай­лу и убе­ди­тесь, что они дос­туп­ны для чте­ния поль­зо­ва­те­лю tomcat.) Те­перь при­ло­же­ние долж­но сно­ва стать ак­тив­ным.

На этом по­ка все. Че­рез ме­сяц мы по­ра­бо­та­ем с кон­фи­гу­ра­ци­он­ным фай­лом сер­ве­ра, ус­та­но­вим не­сколь­ко фильт­ров для вхо­да в сис­те­му и управ­ле­ния дос­ту­пом и по­смот­рим, как спря­тать Tomcat за бо­лее тра­ди­ци­он­ным web-сер­ве­ром вро­де Apache. Уви­­дим­­ся! |

Стра­ни­цы Java

Tomcat так­же мо­жет вы­да­вать со­дер­жи­мое, струк­ту­ри­ро­ван­ное в ви­де сер­вер­ных стра­ниц Java, ко­то­рые со­сто­ят из HTML-раз­мет­ки со встав­ка­ми ко­да на Java в тэ­гах < % и  %>. Эта кон­цеп­ция рас­ши­ря­ет­ся с по­мо­щью стан­дарт­ной биб­лио­те­ки тэ­гов (JSTL); тэ­ги реа­ли­зу­ют опе­ра­ции, об­щие для мно­гих web-при­ло­же­ний, та­кие как об­ра­бот­ка XML-до­ку­мен­тов и дос­туп к ре­ля­ци­он­ным ба­зам дан­ных. Раз­ли­чие ме­ж­ду серв­ле­том и JSP в це­лом в том, что серв­лет вклю­ча­ет HTML в кар­кас на Java, то­гда как JSP вклю­ча­ет код Java в кар­кас на HTML. Под­ход JSP бу­дет бо­лее зна­ко­мым вам, ес­ли вы уже под­на­то­ре­ли, ска­жем, в ASP, .NET или LAMP.

> Ус­та­но­ви­те эти па­ке­ты с yum, что­бы по­лу­чить ра­бо­чую кон­фи­гу­ра­цию Tomcat. Па­кет javasdk ну­жен толь­ко для ком­пи­ля­ции сво­их серв­ле­тов. Но вы же бу­де­те их де­лать, прав­да?

А ес­ли не ра­бо­та­ет?

Ес­ли что-то ра­бо­та­ет не так, как долж­но, по­про­буй­те по­ис­кать со­об­ще­ния об ошиб­ках в /var/log/tomcat/catalina.out. Так­же уч­ти­те, что брау­зер кэ­ши­ру­ет стра­ни­цы, и это мо­жет дурно по­вли­ять на ва­шу стра­те­гию тес­ти­ро­ва­ния, ес­ли тестировать невни­ма­тель­но. Ти­пич­ный сце­на­рий та­ков: вы за­пус­кае­те тест, види­те в брау­зе­ре ошиб­ку, ис­прав­ляе­те ошиб­ку в про­грам­ме, сно­ва за­пус­кае­те тест, но все еще ви­ди­те (кэ­ши­ро­ван­ную) стра­ни­цу с ошиб­кой. Ес­ли у вас есть ма­лей­шее по­доз­ре­ние, что имен­но это и про­ис­хо­дит, со­ве­тую очи­стить кэш брау­зе­ра. На­при­мер, в Firefox вы­бе­ри­те Tools > Clear Recent History (Ин­ст­ру­мен­ты > Очи­стить не­дав­нюю ис­то­рию).

Персональные инструменты
купить
подписаться
Яндекс.Метрика