Projects | Community | Members 
 Midgard - Tutorial - 26.08.2002

  Inhalt 
 
Midgard
und
Mandrake
 
das ultimative Installationsmanual

3. [optional] extreme Midgard Debugging

Beim Installieren und benutzen von Midgard können diverse Probleme auftauchen. Es gibt mehrere Möglichkeiten diesen Problemen zu begegnen:

  • Auswerten der Logfiles von Midgard
  • Das Debuggen von Apache und mod_midgard
  • Das Debuggen des PHP-Codes von Midgard über Log-Files und gezieltem Setzen von Debug-Ausgaben im Code
3.1 Logfiles von Midgard

Logfiles werden nur ausgegeben wenn statt mod_midgard mod_preparse installiert wird. Dieses lässt sich von midgard-project.org downloaden und dann genau so wie mod_midgard installieren. Danach kann man in der Datei
/etc/httpd/conf/midgard-data.conf folgende Zeilen hinzufügen:

(ausserhalb des VirtualHost)
MidgardLog Debug+ /var/log/midgard.log

(innerhalb des VirtualHost)
LogLevel debug

Zusätzlich kann man die Debug-Ausgaben für PHP erhöhen und in ein Log-File leiten indem man in /etc/php.ini die Zeilen ändert:

error_reporting = E_ALL
display_errors = Off
log_errors = On
error_log = /var/log/php_error.log

Diese Einstellungen sollte man nach dem Debuggen auf Production-Servern wieder ausstellen.

3.2 mögliche Debugger und Tools

Um Apache zu debuggen habe ich lange im Internet gesucht und folgende Alternativen gefunden:

- gdb
  Der Standard-Debugger unter Linux. Ein sehr schlecht bedienbares aber relativ stabiles Console-Tool das als Grundlage für viele Debuggeraufsätze dient. Leider scheint es unter Linux KEINEN weiteren Console-Debugger zu geben der vielleicht zudem ein bisschen bedienungsfreundlich wäre. Zwar gibt es eine C/C++ Umgebung für die Console (SetEdit), die vielversprechend aussieht, aber die kann sich nicht zu einem fertigen Programm attachen.
   
- DDD (Data Display Debugger)
  Der Data Display Debugger ist ein Aufsatz über den Linux-Standard-Debugger gdb. Er ist unter den Linux-Anhängern wohl sehr verbreitet und deutlich bedienbarer als der gdb.
 
   
- TotalView 5 (kommerziell)
  TotalView 5 von Etnus ist ein kommerzieller Debugger.
 
   
- Insight 5.2
  Insight 5.2 ist kein Aufsatz auf gdb wie DDD sondern compiliert die Sources des gdb in sich hinein. Dadurch ist Insight spürbar schneller als DDD und benutzbarer wie ich finde... Wer sich wundert wohin das Executable verschwindet nachdem Insight compiliert wurde: Es nennt sich ebenfalls 'gdb' und lag bei mir in: /usr/local/bin/
 

Alle Debugger sind entweder frei, oder es gibt eine kostenlose Trial-Version im Internet.
Alle Debugger sind auch mal abgestürzt, haben Breakpoints fehlinterpretiert und kamen mit der komplett DSO-Variante des Apache überhaupt nicht zurecht. Also probiert es bitte gleich mit der statisch kompilierten Variante.

3.3 Debug-Compile von Apache

Debug Code in Apache und seine Module zu bringen erweist sich als schwerer als zunächst vermutet.

Zunächst muss der Apache als statisch konfiguriert werden:

./configure \
--enable-module=so \
--server-uid=apache \
--server-gid=apache \
--enable-rule=WANTHSREGEX \
--prefix=/etc/httpd \
--sysconfdir=/etc/httpd/conf \
--iconsdir=/var/www/icons \
--htdocsdir=/var/www/html \
--logfiledir=/var/log/httpd \
--cgidir=/var/www/cgi-bin \
--libexecdir=/usr/lib/apache/modules \
--bindir=/usr/bin \
--includedir=/usr/include/apache \
--mandir=/usr/share/doc \
--sbindir=/usr/sbin

"configure" erzeugt nicht nur das Makefile, sondern auch eine Datei src/Configuration.apaci. In dieser muss folgende Zeile verändert werden:

EXTRA_CFLAGS= `$(SRCDIR)/apaci` -g

Im diesem Verzeichniss src führen wir dann die Befehle aus:

./Configure
make

wieder zurück im Apache-Verzeichniss ändern wir die Makefile-Datei und verhindern mit der Änderung der Zeile

IFLAGS_PROGRAM = -m 755 -s

in

IFLAGS_PROGRAM = -m 755

das die neu erzeugten Debug-Symbole wieder verschwinden. Ein

make
make install

installiert nun Apache mit Debugsymbolen.

3.4 statisches eincompilieren von mod_midgard und PHP

Wenn PHP und/oder mod_midgard oder mod_preparse statisch in Apache eincompiliert werden müssen, dann muss zuerst Apache mimimalistisch konfiguriert worden sein, z.B. mit:

./configure \
--enable-module=so \
--server-uid=apache \
--server-gid=apache \
--enable-rule=WANTHSREGEX \
--prefix=/etc/httpd \
--sysconfdir=/etc/httpd/conf \
--iconsdir=/var/www/icons \
--htdocsdir=/var/www/html \
--logfiledir=/var/log/httpd \
--cgidir=/var/www/cgi-bin \
--libexecdir=/usr/lib/apache/modules \
--bindir=/usr/bin \
--includedir=/usr/include/apache \
--mandir=/usr/share/doc \
--sbindir=/usr/sbin

dann müssen die entsprechenden Module vorher jeweils mit dem

--with-apache=<dein_Pfad_zum_Apache_Source>

statt dem

--with-apxs=/usr/sbin/apxs

Flag konfiguriert werden, danach ist Apache wie folgt zu konfigurieren:

./configure \
--enable-module=so \
--add-module=<Dein_Pfad_zum_mod_midgard_Source>/mod_midgard.c \
--enable-module=midgard \
--activate-module=<Dein_Pfad_zum_PHP4_source-lib-Verzeichiss>/libphp4.a \
--server-uid=apache \
--server-gid=apache \
--enable-rule=WANTHSREGEX \
--prefix=/etc/httpd \
--sysconfdir=/etc/httpd/conf \
--iconsdir=/var/www/icons \
--htdocsdir=/var/www/html \
--logfiledir=/var/log/httpd \
--cgidir=/var/www/cgi-bin \
--libexecdir=/usr/lib/apache/modules \
--bindir=/usr/bin \
--includedir=/usr/include/apache \
--mandir=/usr/share/doc \
--sbindir=/usr/sbin

(Manchmal ist es notwendig vorher noch in der Datei src/Configuration.tmpl die Zeilen
EXTRA_LDFLAGS=-L/var/midgard/lib
EXTRA_INCLUDES=-I/var/midgard/include
zu ändern)
Ich würde jedoch zumindest mod_midgard weiterhin als DSO nachladen, da ich es zwar so kompilieren konnte, aber Apache sich nicht mehr starten liess...

3.5 Debuggen von mod_midgard_preparse

mod_midgard_preparse ist ein 1:1 mod_midgard-pendant mit dem Unterschied das Logging integriert ist. Man compiliert und installiert es wie das Original.
Das Debuggen von Apache funktioniert mit allen Debuggern ähnlich, deswegen demonstriere ich es hier nur mit dem gdb.Alles was man wissen muss, ist der Umstand das Apache in form des httpd-Programmes in
/usr/sbin liegt und mit dem Parameter -X im single-process mode läuft damit wir einen gezielten Request debuggen können.

Zunächst können wir in der Funktion ap_process_request einen Breakpoint setzen, da dies die Haupt-Request-Behandlungsfunktion im apache ist, und danach (nachdem er alle Libs etc geladen hat) einen Breakpoint auf midgard_translate_handler, das ist die Hauptfunktion im mod_midgard. In gdb funktioniert das ungefähr so (grün sind die Benutzereingaben):

% gdb httpd
GNU gdb 5.1.1
Copyright 2002 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-mandrake-linux".
(gdb) b ap_process_request
Breakpoint 1 at 0x49fb4: file http_request.c, line 1164.
(gdb) run -X

Starting program: /usr/local/apache/src/httpd -X

[an diesem Punkt einen Request an Apache von einem anderen Fenster aus machen]

Breakpoint 1, ap_process_request (r=0x95250) at http_request.c:1164
1164 if (ap_extended_status)
(gdb) s
1165 ap_time_process_request(r->connection->child_num, START_PREQUEST);
(gdb) n
1167 process_request_internal(r);
(gdb) s
process_request_internal (r=0x95250) at http_request.c:1028
1028 if (!r->proxyreq && r->parsed_uri.path) {
(gdb) s
1029 access_status = ap_unescape_url(r->parsed_uri.path);
(gdb) n
1030 if (access_status) {
(gdb) s
1036 ap_getparents(r->uri); /* OK --- shrinking transformations... */
(gdb) n
1038 if ((access_status = location_walk(r))) {
(gdb) n
1043 if ((access_status = ap_translate_name(r))) {
(gdb) n
1048 if (!r->proxyreq) {
(gdb) n
1053 if (r->method_number == M_TRACE) {
(gdb) n
1062 if (r->proto_num > HTTP_VERSION(1,0) && ap_table_get(r->subprocess_env, "downgrade-1.0")) {
(gdb) n
1071 if ((access_status = directory_walk(r))) {
(gdb) s
directory_walk (r=0x95250) at http_request.c:288
288 core_server_config *sconf = ap_get_module_config(r->server->module_config,
(gdb) b ap_send_error_response
Breakpoint 2 at 0x47dcc: file http_protocol.c, line 2090.
(gdb) c
Continuing.

Breakpoint 2, ap_send_error_response (r=0x95250, recursive_error=0) at http_protocol.c:2090
2090 BUFF *fd = r->connection->client;
(gdb) where
#0 ap_send_error_response (r=0x95250, recursive_error=0) at http_protocol.c:2090
#1 0x49b10 in ap_die (type=403, r=0x95250) at http_request.c:989
#2 0x49b60 in decl_die (status=403, phase=0x62db8 "check access", r=0x95250) at http_request.c:1000
#3 0x49f68 in process_request_internal (r=0x95250) at http_request.c:1141
#4 0x49fe0 in ap_process_request (r=0x95250) at http_request.c:1167
#5 0x439d8 in child_main (child_num_arg=550608) at http_main.c:3826
#6 0x43b5c in make_child (s=0x7c3e8, slot=0, now=907958743) at http_main.c:3898
#7 0x43ca8 in startup_children (number_to_start=6) at http_main.c:3972
#8 0x44260 in standalone_main (argc=392552, argv=0x75800) at http_main.c:4250
#9 0x449fc in main (argc=4, argv=0xefffee8c) at http_main.c:4534
(gdb) s
2091 int status = r->status;
(gdb) p status
$1 = 403
(gdb)

Zu dem Thema habe ich hier eine schöne Graphic gefunden, die es auch im PDF-Format gibt:


Und nun Fröhliches Debuggen!

3.6 Debuggen des PHP-Codes durch Log-Files

Es gibt zwar mittlerweile schöne Lösungen die es ermöglichen mit übersichtlichen Remote-Debuggern komfortabel durch den Code zu laufen, aber da Midgard viel von nativem Code gebrauch macht (der seinerseits wieder PHP aufruft) nützt uns das bei den gängigen PHP-Debuggern nur etwas für die midgard-root.php, und die stellt meistens nicht das Problem dar. Wir sind leider gezwungen eine weit weniger komfortable Möglichkeit zu nutzen - wir müssen den vermeindlich absturzgefährdeten durch Debug-Ausgaben finden. Dazu könnt Ihr wie oben beschrieben in
/etc/php.ini die Debug-Ausgaben von PHP in eine log-datei leiten, sie mit tail -f <logdatei> in einem Console-Fenster beobachten und den eigentlichen Code (z.B. durch Nutzung des /admin/ - Interfaces) mit kleinen error_log("<sinnvolle Debugausgabe>", 0); - Befehlen spicken.


| © 2002 by 3rd-evolution