pixel
Select Page

NETWAYS Blog

Tracing PHP memory usage with Xdebug


In addition to Xdebug’s great profiling and debugging features it also supports tracing memory usage. This helps to find functions which consume a lot of memory or to identify memory leaks. The following options enable tracing right away:

xdebug.auto_trace=1
xdebug.trace_format=1

Traces are written to /tmp by default. You may change this via the xdebug.trace_output_dir setting. With xdebug.trace_format=1 you tell Xdebug to write traces in an easy-to-parse tab separated format. The logged information includes the start and end times of function calls as well as the amount of used memory when entering and leaving the function. The last two numbers help to figure out which functions increase the memory usage a lot. Luckily you don’t have to interpret the traces yourself but use a script for that.
The script parses the trace files and aggregates the numbers by function name. It accepts a few different keys to sort the output: time-own, memory-own, time-inclusive, memory-inclusive and calls. You can also configure the number of elements to show:

php tracefile-analyser.php trace.662975268.xt memory-own 10
Showing the 10 most costly calls sorted by 'memory-own'.
                                                          Inclusive        Own
function                                          #calls  time     memory  time     memory
------------------------------------------------------------------------------------------
Icinga\Application\ClassLoader->loadClass             90  0.9151  2638176  0.0814  1262312
Zend_Loader::loadFile                                 17  0.1496  1183528  0.0345   882928
PDOStatement->execute                                 22  0.0102   395368  0.0102   395368
require                                               85  0.6066  1548112  0.0157   338512
require_once                                          22  0.0506   566296  0.0107   149128
Icinga\Application\ClassLoader->requireZendAutoloader  1  0.0045   154360  0.0023   120136
Composer\Autoload\includeFile                          8  0.0148    86544  0.0028    59448
Zend_Db_Select->_join                                 41  0.2599    59368  0.0627    57072
explode                                              135  0.0341    55672  0.0341    55672
Icinga\Application\Benchmark::measure                 94  0.2099    47448  0.0737    47352
Eric Lippmann
Eric Lippmann
CTO

Eric kam während seines ersten Lehrjahres zu NETWAYS und hat seine Ausbildung bereits 2011 sehr erfolgreich abgeschlossen. Seit Beginn arbeitet er in der Softwareentwicklung und dort an den unterschiedlichen NETWAYS Open Source Lösungen, insbesondere inGraph und im Icinga Team an Icinga Web. Darüber hinaus zeichnet er für viele Kundenentwicklungen in der Finanz- und Automobilbranche verantwortlich.

Canonical schließt Lücken in Ubuntu 18.04 LTS

Common Vulnerabilities and Exposures (CVE) ist ein Industriestandard, dessen Ziel die Einführung einer einheitlichen Namenskonvention für Sicherheitslücken und andere Schwachstellen in Computersystemen ist. Mehrfachbenennung gleicher Gefahren durch verschiedene Unternehmen und Institutionen werden um eine laufende Nummer ergänzt, um eine eindeutige Identifizierung der Schwachstelle zu gewährleisten. Dadurch ist ein reibungsloser Informationsaustausch zwischen den verschiedenen Datenbanken einzelner Hersteller möglich.

Canonical hat ein neues Kernel-Update für Ubuntu 18.04 LTS veröffentlicht, indem Lücken, die im VirtIO-Subsystem und dem ACPI Kernel stecken, gepatcht werden. Eine Lücke in der Speicherinitialisierung (CVE-2018-1118) im VirtIO-Subsystem des Kernels, die nicht immer funktionierte, wurde entfernt. Hier konnte ein Angreifer über einen lokalen Zugriff vertrauliche Informationen erhalten. Die zweite Lücke betrifft das ACPI (Advanced Configuration and Power Interface) des Kernels wodurch auch ein lokaler Angriff Erfolg hätte.
Außerdem gab es mehrere Schwachstellen in der PHP-Komponente FPM und EXIF bei denen Angreifer auch lokal mit speziell präpariertem PHP-Skripten die Vorbereitung von verschiedenen DoS-Angriffen ausführen konnten. Später dann auch aus der Ferne steuerbar. Die Schwachstellen CVE-2018-14851 und CVE-2018-14883 lassen den Angreifer beliebigen Programmcode ausführen. CVE-2015-9253 lassen sich aus der Ferne für DoS-Angriffe auf geteilte PHP-Server ausführen.
Die Updates stehen seit längerem für Ubuntu 18.04 LTS, 16.04 LTS und 14.04 LTS bereit.

Event-driven, async I/O with PHP

Ever wondered whether it is possible to write asynchronous code in PHP? Good news, it is! One of the most promising libraries is ReactPHP. It provides the powerful concept of event-driven, non-blocking I/O in PHP. Its core is an event loop, on top of which it provides utilities like stream abstraction and async network clients and servers. The library is written in pure PHP and its architecture is well-suited for high performance network servers and clients. The documentation and examples of ReactPHP’s components are quite detailed so it should be no problem to get started. The following example is a simple asynchronous web server written in ReactPHP which responds with “Hello World” for every request.

$loop = React\EventLoop\Factory::create();
$server = new React\Http\Server(function (Psr\Http\Message\ServerRequestInterface $request) {
    return new React\Http\Response(
        200,
        array('Content-Type' => 'text/plain'),
        "Hello World!\n"
    );
});
$socket = new React\Socket\Server(8080, $loop);
$server->listen($socket);
echo "Server running at http://127.0.0.1:8080\n";
$loop->run();
Eric Lippmann
Eric Lippmann
CTO

Eric kam während seines ersten Lehrjahres zu NETWAYS und hat seine Ausbildung bereits 2011 sehr erfolgreich abgeschlossen. Seit Beginn arbeitet er in der Softwareentwicklung und dort an den unterschiedlichen NETWAYS Open Source Lösungen, insbesondere inGraph und im Icinga Team an Icinga Web. Darüber hinaus zeichnet er für viele Kundenentwicklungen in der Finanz- und Automobilbranche verantwortlich.

Außerhalb von NETWAYS: Projektwoche in der Berufsschule

Heute möchte ich einen Blick außerhalb der betrieblichen Ausbildung werfen und ein wenig über die Projektwoche in der Berufsschule berichten. Alle Auszubildenden, die die Berufsschule B3 in Fürth im Zweig Fachinformatik Systemintegration oder Anwendungsentwicklung besuchen, führen dort am Ende des 2. Ausbildungsjahres eine Projektwoche durch.
Innerhalb dieser Projektwoche arbeiten die Schüler einer Klasse in Gruppen von 12 – 15 Mitgliedern zusammen. Dabei wird vor allem darauf geachtet, dass die Stärken der Schüler gleichmäßig auf die Gruppen verteilt werden.
Das Projekt selbst bestand aus der Simulation eines Kundenauftrages an eine Firma, die sowohl die Umsetzung von IT-Infrastrukturen als auch Software-Entwicklung bietet. Die Belegschaft der Firma wurde dann wie folgt auf die Mitschüler aufgeteilt:

  • Abteilung Management: 3 Schüler
  • Abteilung Infrastruktur: 3 Schüler
  • Abteilung Entwicklung: 6 Schüler

Die Gewichtung ergab sich aus der Analyse des Lastenheftes, das vom Lehrerkollegium zuvor ausgearbeitet und ausgehändigt wurde. Darin ging es darum, dass für den Kunden eine Infrastruktur und Software aufgebaut werden soll, mit der der Kunde sämtliches IT-Inventar in seinen Räumlichkeiten verwalten kann. Der Kunde selbst wurde dabei durch unsere Schule und einen Teil des Lehrerkollegiums dargestellt. Folgende Punkte waren dabei besonders von Bedeutung:

  • Netzwerk mit VLANs (Trennung von Schul- und Administrationsnetzwerk) mit Access Points für WLAN
  • Web- und Datenbankserver, auf denen die Inventarisierungssoftware laufen soll
  • Mit der Software müssen folgende Aktionen machbar sein:
    • Auflisten von Inventar
    • Ändern, Löschen und Hinzufügen von Inventar
    • Zuordnung von Inventar zu Räumen und Klassenzimmern
    • Login mit User/Passwort und Vergabe von Rechten (Admin oder User)
  • Einrichten von Clients für die Nutzung des Webfrontends der Software
    • Aufrufbar über Browser
    • Ergonomie muss beachtet werden
  • Erstellung eines Pflichtenheftes, einer Kundendokumentation und eines Wartungsvertrages
    • Pflichtenheft und Wartungsvertrag muss von den Lehrkräften abgenommen werden
    • Kundendokumentation soll als Benutzerhandbuch fungieren
  • Abschließende Projekt-Präsentation vor Publikum mit abschließender Fragerunde
  • Zeitlicher Rahmen: Montag bis Donnerstag, Umsetzung des Projektes mit freier Zeiteinteilung, Freitag morgen Präsentation

Nachdem wir den Montagvormittag damit verbrachten, die Aufgabenstellung durchzuplanen, setzten wir im Laufe der Woche die folgenden Schritte um:

  • Erstellung Pflichtenheft
  • Aufbau Netzwerk
  • Aufbau LAMP-Stack auf Server
  • Aufbau der MySQL-Datenbank
  • Erstellung der Core Software aus php und javascript
  • Erstellung des Webfrontends mit html und php
  • Erstellung Wartungsvertrag
  • Erstellung und Planung Projekt-Präsentation
  • Ausführliches Testen der einzelnen Komponenten
  • Fehlersuche, Debugging und Korrekturen
  • Erstellung Kundendokumentation, direkt aufrufbar über die Hilfe-Funktion in der Software

Mit dem Ergebnis aus dieser Woche konnten wir dann auch unsere Lehrer überzeugen, die unsere Gruppe durchweg positiv bewerteten und sehen konnten, dass wir als Klasse viel Wissen aus den letzten beiden Schuljahren mitgenommen haben.
Als Fazit kann ich persönlich sagen, dass es auf jeden Fall eine tolle und konstruktive Erfahrung ist, einmal komplett eigenverantwortlich und mit eigener Zeiteinteilung eine solche Aufgabe zu bewältigen. Außerdem bringt dies die Schüler auch zwischenmenschlich und bzgl. der eigenen Persönlichkeit weiter, denn jeder lernt nicht nur die eigenen Stärken und die der Mitschüler kennen und schätzen, sondern muss auch mit Schwächen und Fehlschlägen zurechtkommen bzw. anderen aus diesen heraushelfen. Es ist eben doch ganz gut, wenn man ab und zu mal die eigene Komfortzone verlässt!
Wer sich nun angesprochen fühlt, auch mal in die IT-Welt zu schnuppern oder mit dem Gedanken spielt, eine Ausbildung im Bereich Informatik zu machen, dann schreibt uns doch einfach unter jobs@netways.de. Mehr Infos findet Ihr auch auf unserer Webseite oder in unserer Stellenausschreibung zum Azubi Fachinformatik. Mehr Informationen zum Thema Ausbildung Fachinformatiker findet Ihr auch auf der Webseite der IHK.
 
Bildquellen: 
https://www.unixmen.com/how-to-install-lamp-stack-ubuntu-17-04/
http://www.b3-fuerth.de/ 

Die Extrawurst

Icinga Web 2 bietet eine Reihe von Möglichkeiten, Gruppen-Mitgliedschaften zuzuweisen. Am häufigsten werden Gruppenmitgliedschaften entweder via Web angelegt oder aus einem LDAP-Verzeichnis gezogen. Der bekannteste Vertreter dabei ist Microsofts Active Directory.
Weniger bekannt ist, dass man in eigenen Modulen Benutzer- sowie Gruppenmitgliedschafts-Backends bereitstellen kann. Manchmal braucht man aber gar nicht ein volles Backend, sondern nur ein paar kleine Korrekturen. Aus einem solchen Grund entstand diese Woche in einem Kundenprojekt ein neues Icinga Web 2 Modul: Extragroups.

Zusätzliche Gruppen für jeden

Einmal installiert, lassen sich in der config.ini des Moduls flexible Regeln definieren.
[Jeder ist ein Mimimi]
add_groups = "Mimimi"

Das allein hat erst mal keinen Effekt, also hinterlegen wir in der /etc/icingaweb2/roles.ini eine Rolle, welche unseren Usern eine entsprechende Einschränkung verpasst:
[Mimimi Demo]
groups = "Mimimi"
monitoring/filter/objects = "host_name=*mi*"

Sobald wir uns neu anmelden sind wir Mitglied der Gruppe “Mimimi” und sehen nur noch Hosts welche “mi” enthalten. Dabei ist nebensächlich, ob eine Benutzergruppe namens “Mimimi” existiert oder nicht.

Mustervergleich mit Benutzernamen

Lasst uns das Ganze ein wenig einschränken:
[Alle Heuler sollen Mimimis werden]
user_filter = "username=*heul*"
add_groups = "Mimimi"

Was hier passiert dürfte klar sein, wir machen nur noch unsere Heuler zu Mimimis.

Regeln basierend auf Umgebungsvariablen

Ihr möchtet alle Benutzer mit ein paar Ausnahmen in eine spezielle Gruppe geben, aber nur wenn diese remote arbeiten? Erstellt einfache eine auf deren IP-Range basierende Regel:
[Einschränkung wenn via VPN verbunden]
env_filter = "REMOTE_ADDR=192.0.2.*"
user_filter = "username!=tom&username!=admin"
add_groups = "Via VPN verbunden"

Ähnlich wie REMOTE_ADDR in diesem Beispiel können alle vom Web-Server bereitgestellten Umgebungsvariablen benutzt werden. Im nächsten Beispiel zeigen wir Netzwerk-Admins welche via Nagstamon angemeldet sind lediglich wirklich wichtige Hosts und Services:
[Filter für Nagstamon]
env_filter = "HTTP_USER_AGENT=Nagstamon*"
user_filter = "group=Network Admin"
add_groups = "VIP objects filter"

VORSICHT: Der User-Agent kann einfachst gefälscht werden. Dieses Beispiel dient dem Komfort unserer Benutzer: sie wollen in Nagstamon nicht mit allen Problemen belästigt werden. Für sicherheitskritische Regeln taugt der User-Agent nicht.

Mehrere Gruppen zuweisen

Manchmal will man mehrere Gruppen auf einmal zuweisen, ohne die ganze Regel zu klonen. Das lässt sich einfach bewerkstelligen, denn add_groups akzeptiert eine Komma-getrennte Liste:
[VPN-Benutzer einschränken]
; ..
add_groups = "Eingeschränkte Benutzer, Spezielle Dashboards, Business-Prozesse"

Soll die Gruppenliste noch dynamischer sein? Vorausgesetzt dass ein Webserver-Modul oder dessen Konfiguration diese Information bereitstellt, lässt sich jede Umgebungsvariable via {VARIABLE_NAME} nutzen:
[Gruppen des SSO-Moduls zuweisen]
add_groups = "{HTTP_AUTHZ_GROUPS}"

Auch in Strings die aus Umgebungsvariablen kommen funktioniert das Komma (,) als Trennzeichen. Und man kann natürlich Variablen-Platzhalter mit statischen Werten kombinieren:
[Eine Reihe von Gruppen]
add_groups = "Spezial-Gruppe, {REMOTE_GROUPS}, {HTTP_AUTHZ_GROUPS}"

Auf Gruppenmitgliedschaften basierende Regeln

Der user_filter erlaubt auch Regeln basierend auf bereits zugewiesene Gruppen. In unserem umfangreicheren letzten Beispiel erhalten alle Benutzer zusätzliche Gruppenmitgliedschaften via HTTP_AUTHZ_GROUPS. Na gut, jeder außer der guest und der admin-Benutzer.
Wenn sie Nagstamon nutzen während sie via VPN verbunden sind, sollen sie zusätzlich in die Gruppe Nagstamon Remote kommen.
Wird Nagstamon ohne VPN benutzt, sollen Mitglieder der Gruppen “Linux Benutzer” und/oder “Unix Benutzer” in die Gruppe “Nagstamon Lokal” kommen. Alle außer dem admin:
[Gruppen des SSO-Moduls zuweisen]
add_groups = "{HTTP_AUTHZ_GROUPS}"
user_filter = "user_name!=guest&username!=admin"

[Nagstamon via VPN]
env_filter = "REMOTE_ADDR=192.0.2.*&HTTP_USER_AGENT=Nagstamon*"
add_groups = "Nagstamon Remote"

[Nagstamon ohne VPN]
env_filter = "REMOTE_ADDR!=192.0.2.*&HTTP_USER_AGENT=Nagstamon*"
user_filter = "username!=admin&(group=Linux Benutzer|group=Unix Benutzer)"
add_groups = "Nagstamon Local"

Dabei gilt es zu beachten, dass der Filter basierend auf die group-Eigenschaft nur Gruppen sieht, welche von vorhergehenden Regeln zugewiesen wurden. Von anderen Backends bereitgestellte Gruppenmitgliedschaften sind nicht zugänglich.
Das war’s auch schon, viel Spaß!

Thomas Gelf
Thomas Gelf
Principal Consultant

Der gebürtige Südtiroler Tom arbeitet als Principal Consultant für Systems Management bei NETWAYS und ist in der Regel immer auf Achse: Entweder vor Ort bei Kunden, als Trainer in unseren Schulungen oder privat beim Skifahren in seiner Heimatstadt Bozen. Neben Icinga und Nagios beschäftigt sich Tom vor allem mit Puppet.