Benutzer-Werkzeuge

Webseiten-Werkzeuge


Seitenleiste

Was fehlt?

Es liegt in der Natur der Sache: Ein Wiki ist niemals fertig. Wir geben uns große Mühe, mit der Entwicklung Schritt zu halten; lassen Supportanfragen direkt in neue Artikel einfließen … aber auch wir sind nicht perfekt. Wenn du hier nicht fündig wirst: Nicht schmollen - Bescheid sagen! Unter hallo@uberspace.de steht dir unser Team gerne bereit. Hand drauf!

development:php

PHP

Natürlich ist auch PHP auf unseren Servern verfügbar. Wir setzen hierbei auf ein Setup, bei dem für jeden Uberspace ein eigener PHP-Interpreter unter FastCGI läuft. Der kleine Nachteil dabei ist, dass beim ersten Aufruf eines PHP-Scripts nach einem Webserver-Restart oder nach längerer Nichtbenutzung zunächst ein PHP-Interpreter für deinen Uberspace gestartet werden muss, was ca. 1-2 Sekunden dauert. Aber keine Sorge: Sobald er einmal läuft, gehen die weiteren Zugriffe so schnell wie erwartet. Die Vorteile dieses Systems überwiegen aber aus unserer Sicht die kleine „Denkpause“:

  • Der eigene PHP-Interpreter läuft mit deinen Rechten und nicht wie anderswo mit den Rechten des Webservers. Insofern kannst du auf alle Dateien deines Uberspaces genauso zugreifen wie auf der Shell auch; gleichzeitig besteht eine maximale Absicherung gegen Übergriffe auf andere Uberspaces.
  • Durch diese Trennung der Interpreter können wir auf Frickeleien wie open_basedir, den safe_mode oder disable_functions getrost verzichten: Warum sollen wir PHP in Funktionen einschränken, die dir spätestens bei Nutzung einer anderen Programmiersprache doch sowieso bereitstünden?
  • Durch Einsatz des eigenen Interpreters kannst du problemlos eine eigene php.ini zum Einsatz bringen - oder auch die Version deines Interpreters wechseln.

Pfad zum PHP-Interpreter

Nach Einrichtung deines Uberspaces funktioniert PHP automatisch und arbeitet mit einer aktuellen Version der 5er-Serie. Unsere PHP-Interpreter liegen unter /package/host/localhost; mit ls -ld /package/host/localhost/php-* kannst du nachschauen, welche konkreten Versionen auf deinem Host verfügbar sind. So könnte das exemplarisch aussehen:

[clara@xenon ~]$ ls -ld /package/host/localhost/php-*
lrwxrwxrwx. 1 packagesync packagesync   31 Apr 13  2015 /package/host/localhost/php-5 -> /package/host/localhost/php-5.6
lrwxrwxrwx. 1 packagesync packagesync   34 Aug 30 10:25 /package/host/localhost/php-5.4 -> /package/host/localhost/php-5.4.44
drwxr-xr-x. 7 packagesync packagesync 4096 Aug 30 10:07 /package/host/localhost/php-5.4.44
lrwxrwxrwx. 1 packagesync packagesync   34 Jan  7 13:52 /package/host/localhost/php-5.5 -> /package/host/localhost/php-5.5.30
drwxr-xr-x. 7 packagesync packagesync 4096 Aug 30 10:14 /package/host/localhost/php-5.5.28
drwxr-xr-x. 9 packagesync packagesync 4096 Jan  7 10:24 /package/host/localhost/php-5.5.30
lrwxrwxrwx. 1 packagesync packagesync   34 Jan  7 13:19 /package/host/localhost/php-5.6 -> /package/host/localhost/php-5.6.16
drwxr-xr-x. 7 packagesync packagesync 4096 Jun 13  2015 /package/host/localhost/php-5.6.10
drwxr-xr-x. 7 packagesync packagesync 4096 Aug 30 09:39 /package/host/localhost/php-5.6.12
drwxr-xr-x. 9 packagesync packagesync 4096 Jan  6 17:07 /package/host/localhost/php-5.6.16
lrwxrwxrwx. 1 packagesync packagesync   31 Aug 30 09:43 /package/host/localhost/php-7 -> /package/host/localhost/php-7.0
lrwxrwxrwx. 1 packagesync packagesync   33 Jan  7 13:52 /package/host/localhost/php-7.0 -> /package/host/localhost/php-7.0.1
drwxr-xr-x. 8 packagesync packagesync 4096 Dec  3 23:18 /package/host/localhost/php-7.0.0
drwxr-xr-x. 9 packagesync packagesync 4096 Jan  7 09:49 /package/host/localhost/php-7.0.1

Was du hier siehst, ist ein mehrstufiges System von Symlinks. Die physischen Verzeichnisse tragen jeweils die vollständige Versionsnummer der PHP-Installation. Mit Symlinks bauen wir dann immer generischere Versionsangaben zurück.

Konkret bedeutet das: php-5 ist die jeweils aktuellste Version in der aktuellsten Kompilierung der PHP-5-Serie. php-5.6 ist das aktuellste PHP 5.6 und wird auch immer eins bleiben. php-5.6.16 bleibt immer PHP 5.6.16, auch wenn wir auf 5.6.17 oder 5.6.20 upgraden.

Hintergrund ist, dass es zwischen PHP-Versionen oft - manchmal nur minimale - Inkompatibilitäten gibt, die dafür sorgen, dass manche Dinge nicht richtig funktionieren. So gibt es auch heute noch einige Applikationen, die so spezifische Bugs beinhalten, dass sie nur mit PHP 5.5 korrekt ausführbar sind, während sie unter PHP 5.6 nicht richtig laufen. Mit unserem Schema hast du die Möglichkeit, unabhängig davon, was gerade aktuell ist, eine ganz bestimmte PHP-Version auf deinem Uberspace festzupinnen und für alle Zeit dabei zu bleiben (auch wenn ohne Frage sinnvoller wäre, keine Software einzusetzen, die zwangsweise auf älteren PHP-Versionen besteht).

PHP-Version einstellen

In deinem etc-Verzeichnis gibt es eine Datei namens phpversion, in der die Variable PHPVERSION gesetzt wird:

[martina@amnesia ~]$ cat ~/etc/phpversion 
## 2015-02-24 /usr/local/sbin/uberspace-account-create.sh 
PHPVERSION=5.6

Hier kannst du die Versionsnummer deiner Wahl eintragen - wähle einfach eine der Versionen, die in /package/host/localhost/php-* vorliegen.

Wir empfehlen dir hier ausdrücklich, eine Minor-Version zu wählen, also z.B. PHPVERSION=5.6. Das hat den Vorteil, dass du Bugfix-Releases ohne Zutun bekommst und immer auf dem aktuellen Stand bist.

Nach dieser Änderung musst du deinen Interpreter neu starten. Solltest du eine eigenen php.ini verwenden wäre es sinnvoll diese zu löschen und neu anzulegen. Das war's!

Wenn du den PHP-Interpreter auch direkt auf der SSH-Shell benutzt, musst du dich einmal aus- und wieder einloggen, damit deine ~/.bash_profile neu eingelesen wird; erst dann ist die Version auch auf der Shell entsprechend umgestellt.

Damit du den Zusammenhang verstehst: PHP wird bei uns über das Script php-fcgi-starter gestartet, was in deinem FastCGI-Verzeichnis liegt. Dieses Script bindet die ~/etc/phpversion ein. So sieht das aus:

[martina@amnesia ~]$ cat ~/fcgi-bin/php-fcgi-starter
#!/bin/sh
## 2015-01-21 /usr/local/sbin/uberspace-account-create.sh 
. ~/etc/phpversion
export PHPRC="/home/martina/etc"
exec /package/host/localhost/php-${PHPVERSION}/bin/php-cgi

Die Zentralisierung der PHP-Version in der separaten Datei hat den Vorteil, dass wir diese dann auch gleich via /etc/profile.d/phpversion.sh dergestalt einbinden können, dass sie nicht nur für deine Website gilt, sondern auch auf der Shell, wenn du einfach nur php ohne Angabe eines konkreten Pfads aufrufst.

Eigene php.ini

Wir setzen bei unseren PHP-Installationen eine php.ini ein, die weitestgehend der php.ini-recommended bzw. php.ini-production entspricht, wie das PHP-Entwicklungsteam sie vorschlägt, ergänzt um die Angabe der lokalen Zeitzone, die ab PHP 5.3 erforderlich ist. Die php.ini liegt dabei im Verzeichnis lib des von dir gewählten PHP-Interpreters. Mittels php --ini kannst du dir den vollständigen Pfad anzeigen lassen. So sieht das aus:

[martina@amnesia html]$ php --ini
Configuration File (php.ini) Path: /package/host/localhost/php-5.3.2-6/lib
Loaded Configuration File:         /package/host/localhost/php-5.3.2-6/lib/php.ini
Scan for additional .ini files in: (none)
Additional .ini files parsed:      (none)

Möchtest du nun abweichende Einstellungen von der Vorgabekonfiguration vornehmen, so lege dir eine Kopie der php.ini in deinem etc-Verzeichnis an; diese Kopie kannst du dann nach eigenem Gusto bearbeiten (das test -f zu Beginn stellt sicher, dass eine bereits bestehende lokale php.ini auf deinem Uberspace nicht überschrieben wird):

[martina@amnesia ~]$ test -f ~/etc/php.ini || cp -a /package/host/localhost/php-$PHPVERSION/lib/php.ini ~/etc/
[martina@amnesia ~]$ nano -w ~/etc/php.ini

Bitte beachte: Die eigene php.ini ersetzt die globale. Es ist also nicht möglich, lediglich die gewünschten Abweichungen in der eigenen php.ini zu notieren, in der Hoffnung, dass diese dann mit den globalen Einstellungen zusammengeführt würden. Stattdessen gelten dann für alle Einstellungen die einkompilierten Werte (plus dann deine eigenen), die sich von den in der globalen php.ini vorgegebenen Einstellungen unterscheiden.

Nach Änderungen musst du deinen PHP-Interpreter neu starten, damit jene übernommen werden.

Übrigens: Die eigene php.ini wirkt auch auf PHP-Scripts, die du außerhalb des Webservers ausführst, also direkt auf der Shell, als Cronjob, via runwhen etc., da wir über die /etc/profile.d/phpversion.sh auch die Umgebungsvariable PHPRC auf dein eigenes etc-Verzeichnis setzen.

.user.ini-Dateien

Eine Alternative zu einer php.ini-Datei können .user.ini-Dateien darstellen. Diese Variante hat einige Vor- aber auch Nachteile. Fangen wir mit den Vorteilen an:

  • .user.ini-Dateien können zusätzlich zur php.ini existieren.
  • Du kannst einzelne Werte der globalen (oder deiner eigenen) php.ini überschreiben. Damit kannst du also auch Abweichungen vom Standard abbilden.
  • Du musst den PHP-Interpreter nicht neu starten, um Änderungen wirksam zu machen. Die Konfigurationsdateien werden alle 5 Minuten neu eingelesen.
  • Du kannst die Dateien pro Ordner anlegen. Dein Owncloud braucht eine andere upload_max_filesize als dein Wordpress-Blog? Kein Problem.

Es gibt allerdings auch eine Einschränkung: Du kannst hier nicht alle Direktiven setzen. Nur Einstellungen mit den Modi PHP_INI_PERDIR und PHP_INI_USER werden in .user.ini-Dateien interpretiert. Falls du nicht im Kopf hast, welche Werte in welchem Kontext geändert werden können: Eine kleine Gedächtnisstütze gibt's hier.

PHP-Interpreter neu starten

Dein PHP-Interpreter wird bei einem Webserver-Restart beendet, außerdem nach längerer Inaktivität (wenn also über längere Zeit kein PHP-Script von deinem Uberspace aufgerufen wird). Nach Änderungen am php-fcgi-starter oder dem Anlegen oder Ändern einer eigenen php.ini musst du aber eventuell noch laufende PHP-Interpreter beenden, damit beim nächsten Aufruf einer PHP-Seite von deinem Uberspace die gewünschten Änderungen zum Tragen kommen. Das geht am einfachsten so:

[martina@amnesia ~]$ killall php-cgi

Eine Meldung „php-cgi: Kein Prozess abgebrochen“ stellt kein Problem dar: Sie signalisiert einfach nur, dass ohnehin kein PHP-Prozess unter deiner User-ID läuft, der abgebrochen werden könnte.

Der Neustart deines PHP-Interpreters erfolgt dann automatisch beim nächsten Aufruf einer PHP-Seite.

Eigene PEAR-Module installieren

(Für wiederkehrende Besucher: Wir haben hier früher den Weg über den PEAR-Installer aus dem Web dokumentiert, http://pear.php.net/go-pear - der aber leider mit neueren PHP-Versionen nicht mehr funktioniert. Dafür haben wir jetzt eine noch schickere Lösung gefunden, bei der du gar nichts mehr installieren musst, sondern nur noch eine eigene PEAR-Konfiguration anlegen musst.)

Viele größere PHP-Applikationen benötigen eine ganze Reihe an Modulen aus dem PEAR-Repository. Global haben wir nur ein Standardset davon installiert; wenn dir etwas fehlt, kannst du das zunächst ganz simpel bei uns anfragen.

Wenn du nicht warten willst oder aber volle Kontrolle haben willst, kannst du dir problemlos eigene PEAR-Module innerhalb deines Uberspaces installieren. Das Kommandozeilentool pear wird bereits von unserem PHP-Setup bereitgestellt; was dir noch fehlt, ist eine lokale Konfigurationsdatei mit den Pfaden, in denen deine eigenen PEAR-Module installiert werden sollen. Diese kannst du dir wie folgt anlegen:

[martina@amnesia ~]$ pear config-create ~ ~/.pearrc

Dir wird eine Übersicht über die verwendeten Pfade angezeigt. Du kannst hier ersehen, dass PEAR gerne das Unterverzeichnis pear in deinem Home-Verzeichnis verwenden möchte, was eine gute Idee ist. Anschließend solltest du das Channel-Protokoll aktualisieren, weil dies typischerweise immer schon neuer ist als das der PEAR-Version, die mit PHP ausgeliefert wird (wenn nicht, schadet der Befehl auch nichts):

[martina@amnesia ~]$ pear channel-update pear.php.net

Das war's auch schon beinahe - nur ein letzter Schritt fehlt noch: Du musst nämlich deinem PHP sagen, wo es die von dir selbst installierten PEAR-Module finden kann. Dazu brauchst du eine eigene php.ini, um in jener dann den include_path so zu setzen kannst, dass er deine lokale PEAR-Installation mit berücksichtigt. Dazu legst du dir eine Kopie der globalen php.ini an (das test -f zu Beginn sorgt dafür, dass die globale php.ini nur dann in deinen Uberspace kopiert wird, wenn du dort nicht schon eine liegen hast - die sollte dann ja nicht überschrieben werden):

[martina@amnesia ~]$ test -f ~/etc/php.ini || cp -a /package/host/localhost/php-$PHPVERSION/lib/php.ini ~/etc/

Nun gilt es, den include_path anzupassen. Wir schlagen vor, hier drei Verzeichnisse angeben (die jeweils durch einen Doppelpunkt getrennt werden): Erstens den aktuellen Pfad (symbolisiert durch einen Punkt), zweitens dein lokales PEAR-Verzeichnis, drittens das globale PEAR-Verzeichnis. Die erste und dritte Angabe sind unser Default; die zweite kommt nun dazu. Du kannst das von Hand mit einem Texteditor machen oder mit einem regulären Ausdruck direkt ersetzen; unser Vorschlag:

[martina@amnesia ~]$ perl -pi -e "s|^;?include_path.*|include_path=.:$HOME/pear/php:/package/host/localhost/php-$PHPVERSION/lib/php|" ~/etc/php.ini

Bitte vergiss nicht, noch deinen PHP-Interpreter neu zu starten. Das ist erforderlich, weil ja deine php.ini angepasst wurde. Nach der Installation einzelner PEAR-Module brauchst du diesen Neustart nicht; diese werden automatisch zur Laufzeit gesucht und gefunden.

Das war's - du kannst nun eigene PEAR-Module installieren und nutzen. Wir zeigen das hier mal exemplarisch am Beispiel des PEAR-Moduls Mail_Mime (du musst diesen Schritt natürlich nicht nachvollziehen, ist ja nur ein Beispiel):

[martina@amnesia ~]$ pear install Mail_Mime
downloading Mail_Mime-1.8.1.tgz ...
Starting to download Mail_Mime-1.8.1.tgz (31,530 bytes)
........done: 31,530 bytes
install ok: channel://pear.php.net/Mail_Mime-1.8.1

Eigene PECL-Module installieren

Während im Prinzip die Installation von PECL-Modulen analog zu der von PEAR-Modulen mit dem Kommandozeilentool pecl erfolgen könnte, so funktioniert das in der Praxis leider nicht. Zwar bietet die Konfigurationsdatei .peclrc theoretisch die Möglichkeit, das extension_dir, in dem kompilierte Erweiterungen installiert werden sollen, userspezifisch festzulegen - in der Praxis kommt diese Einstellung im Prozess der Installation aber gar nicht zum Tragen, sondern es wird das extension_dir verwendet, das von php-config ausgegeben wird, so dass das pecl-Tool Module grundsätzlich global installieren will, was als Nicht-root-User natürlich nicht möglich ist. Auch eine eigene php.ini mit angepasstem extension_dir hilft in diesem Punkt nicht.

Wir haben daher einen eigenen kleinen Wrapper geschrieben, der das pecl-Tool lediglich zum Download des Moduls verwendet und es dann aber gemäß der Anleitung zum Kompilieren mittels phpize selbst baut und innerhalb deines Uberspaces installiert, und zwar im Verzeichnis ~/pecl (sofern du kein anderes extension_dir mittels einer eigenen php.ini angegeben hast - dann würde automatisch jenes verwendet). Solltest du noch keine eigene php.ini haben, legt es automatisch eine Kopie des globalen Defaults für dich an. Anschließend bindet es das Modul dort ein.

Der Wrapper wird mit uberspace-install-pecl aufgerufen und bekommt den Namen des gewünschten PECL-Moduls als Argument übergeben. Er kann im Gegensatz zum Original-pecl-Tool zwar keine Abhängigkeiten auflösen; da aber viele häufig benutzten Module ohnehin keine besonderen Abhängigkeiten zu anderen PECL-Modulen haben, sollte das kein Problem darstellen. Zu den Modulen, die sich erfahrungsgemäß unproblematisch installieren lassen, zählen unter anderemimagick, mongo, pecl_http und zip.

So sieht die Installation dann aus, exemplatisch am Beispiel des Moduls mongo:

[martina@amnesia ~]$ uberspace-install-pecl mongo
Creating build directory ... done: /tmp/tmp.BYQti10179
Downloading PECL module ... 
downloading mongo-1.2.7.tgz ...
Starting to download mongo-1.2.7.tgz (84,677 bytes)
....................done: 84,677 bytes
File /tmp/tmp.BYQti10179/mongo-1.2.7.tgz downloaded
Extracting ./mongo-1.2.7.tgz ... done: extracted to ./mongo-1.2.7
Configuring for:
PHP Api Version:         20090626
Zend Module Api No:      20090626
Zend Extension Api No:   220090626
[...]
Copying /package/host/localhost/php-5.3.5-1/lib/php.ini to ~/etc ... done
Configuring your extension_dir to /home/martina/pecl ... done
Creating /home/martina/pecl ... done
Installing mongo.so to /home/martina/pecl ... done
Activating mongo.so in ~/etc/php.ini ... done
Killing currently running PHP processes (if any) ... done

Da im letzten Schritt alle aktuell noch laufenden PHP-Interpreter beendet werden, wirkt sich die Installation sofort im Web aus. Solltest du über eine PECL-Erweiterung stolpern, die sich nicht mittels uberspace-install-pecl installieren lässt, sag uns einfach Bescheid und wir schauen, was wir für dich tun können.

Interpreter nicht vergessen

Vergiss dabei bitte nicht, dass bei Skriptsprachen, wie PHP, Perl oder Python, der jeweilige Interpreter voranzustellen ist. Skripte sind keine ausführbaren Binaries, sondern müssen interpretiert werden, Du musst sie daher immer mit Angabe des Interpreters aufrufen, egal ob auf der Shell, in einer Crontab oder in einem runwhen-Job. Das heißt, in einer Crontab müsste der Aufruf zum Beispiel so aussehen:

*/5 * * * * php /home/DeinUsername/DeinSkript.php

Der Interpreter ist in diesem Fall das Programm php.

Bekannte Probleme

PHP 5.6 und redis

Die neueste Version des redis-Moduls 3.0.0 unterstützt nur noch PHP 7. Wenn du also mit PHP 5.6 uberspace-install-pecl redis ausführst, schlägt die Installation fehl. Zur Lösung des Problems musst du entweder auf PHP 7 umsteigen oder explizit die Version redis-2.2.8 installieren.

development/php.txt · Zuletzt geändert: 2016/10/26 07:35 von uber