1 Reaktion

PHP 5.4 unter Debian 6 Squeeze parallel zu PHP 5.3 (mod_php/mod_fcgid)

Geschätzte Lesedauer:

Nachdem ich vor einiger Zeit schon einen Artikel geschrieben hatte, wie man PHP 5.2.17 unter Squeeze installiert, hier nun der gleiche Artikel für PHP 5.4 (aktuell war zum Zeitpunkt dieses Artikels 5.4.14). Natürlich kann man auch alle 3 Versionen parallel nutzen.

Wie immer gilt auch bei dieser Anleitung: Verwendung auf eigene Gefahr.

Da die PHP 5.4 Version für die Nutzung mit mod_fcgid selbst kompiliert werden muss, stellen wir zuerst einmal sicher, dass wir die benötigten Pakete zum kompilieren installiert haben.
Davon, dass die grundlegenden Programme zum Kompilieren von Quellcode (z. B. gcc) installiert sind, gehe ich an dieser Stelle einmal stillschweigend aus.

Kommandozeile
apt-get install libapache2-mod-fcgid apache2-suexec libpcre3-dev libpcre++-dev libpng12-dev libbz2-dev libcurl4-openssl-dev libc-client2007e-dev libjpeg-dev libgif-dev libgif4 libpthread-stubs0 libpthread-stubs0-dev libx11-dev libxau-dev libxcb1-dev libxdmcp-dev libxpm-dev x11proto-core-dev x11proto-input-dev x11proto-kb-dev xtrans-dev libxml2-dev libmysqlclient-dev libfreetype6-dev

In Debian Squeeze ist das Standard-Upload Limit für das fcgid Modul auf ca. 128kb gesetzt.
Dies können wir in der Datei /etc/apache2/mods-available/fcgid.conf durch das Setzen von
FcgidMaxRequestLen 104857600
auf 100MB anheben. Natürlich können dort auch andere Werte gesetzt werden, sie sollten jedoch höher sein als das in der php.ini eingestellte Upload-Limit.

Als nächstes laden wir uns die aktuelle Version des PHP Quellcodes. Zum Zeitpunkt dieses Artikels war die aktuellste Version 5.4.14.

Kommandozeile
cd /tmp
wget "http://de.php.net/get/php-5.4.14.tar.bz2/from/this/mirror" -O php.tar.bz2
tar xjf php.tar.bz2
cd php-5.4.14

Nach dem Entpacken und Wechseln in das Quellcode-Verzeichnis kommt es beim Kompilieren nun darauf an, ob wir eine 64Bit oder eine 32Bit Installation von Debian verwenden.

Kommandozeile
server1:~# uname -a
Linux server1 2.6.30-2-amd64

In meinem Fall ist das System also mit einem 64Bit Kernel ausgestattet, wenn dort i386 oder i686 statt des amd64 steht kann man davon ausgehen, dass eine 32Bit Version installiert ist.

Kompilier-Befehl für 32Bit:

Kommandozeile
./configure --prefix=/usr/share/php54 --datadir=/usr/share/php54 --mandir=/usr/share/man --bindir=/usr/bin/php54 --with-libdir=lib --includedir=/usr/include/php54 --sysconfdir=/etc/php54/apache2 --with-config-file-path=/etc/php54/apache2 --with-config-file-scan-dir=/etc/php54/conf.d --enable-libxml --enable-session --with-pcre-regex=/usr --enable-xml --enable-simplexml --enable-filter --disable-debug --enable-inline-optimization --disable-rpath --disable-static --enable-shared --with-pic --with-gnu-ld --with-mysql --with-gd --with-jpeg-dir --with-png-dir --with-xpm-dir --enable-exif --with-zlib --with-bz2 --with-curl --with-ldap --with-mysqli --with-freetype-dir --enable-soap --enable-sockets --enable-calendar --enable-ftp --enable-mbstring --enable-gd-native-ttf --enable-bcmath --enable-zip --with-pear --with-openssl --with-imap --with-imap-ssl --with-kerberos --enable-phar --enable-pdo --with-pdo-mysql --with-mysqli

Kompilier-Befehl für 64Bit:

Kommandozeile
./configure --prefix=/usr/share/php54 --datadir=/usr/share/php54 --mandir=/usr/share/man --bindir=/usr/bin/php54 --with-libdir=lib64 --includedir=/usr/include/php54 --sysconfdir=/etc/php54/apache2 --with-config-file-path=/etc/php54/apache2 --with-config-file-scan-dir=/etc/php54/conf.d --enable-libxml --enable-session --with-pcre-regex=/usr --enable-xml --enable-simplexml --enable-filter --disable-debug --enable-inline-optimization --disable-rpath --disable-static --enable-shared --with-pic --with-gnu-ld --with-mysql --with-gd --with-jpeg-dir --with-png-dir --with-xpm-dir --enable-exif --with-zlib --with-bz2 --with-curl --with-ldap --with-mysqli --with-freetype-dir --enable-soap --enable-sockets --enable-calendar --enable-ftp --enable-mbstring --enable-gd-native-ttf --enable-bcmath --enable-zip --with-pear --with-openssl --with-imap --with-imap-ssl --with-kerberos --enable-phar --enable-pdo --with-pdo-mysql --with-mysqli

Der einzige Unterschied besteht eigentlich darin, dass bei der 64Bit-Variante bei der Option –with-libdir einen anderen Pfadnamen übergeben bekommt.
Die weiteren Optionen stellen sicher, dass die PHP Version später auch IMAP, MySQL (inkl. PDO), GD (Grafikbibliothek), Curl und ein paar weitere Module enthält.

Wenn der configure Befehl ohne Fehler beendet ist, kann das Kompilieren und Installieren durch die Befehlsfolge

Kommandozeile
make
make test # optional
make install

gestartet werden.
Der Befehl make test ist optional, sollte aber vor der Installation verwendet werden um sicherzustellen, dass PHP korrekt kompiliert wurde.

Nach der Installation befindet sich in /usr/bin/php54/ nun ein eigenes Verzeichnis für die PHP Binaries der Version 5.4.14.
Nun müssen wir noch sicherstellen, dass die Apache-Module mod_fcgid (Fast-CGI) und SuExec aktiv sind.

Kommandozeile
a2enmod fcgid
a2enmod suexec
/etc/init.d/apache2 force-reload

Als nächstes erstellen wir uns eine Starter-Datei für PHP als Vorlage für unsere Web-User. Was genau eine solche Datei tut, darüber wurde an anderen Stellen schon so viel geschrieben, dass ich mir die Erläuterungen hier spare. Eine Google Suche nach PHP FCGI wird sicherlich einige Ergebnisse bringen.
Natürlich bieten diese Skripte oft noch einige Funktionen, die an dieser Stelle bewusst weggelassen wurden. Hier wird wirklich nur eine minimale Version verwendet.

Kommandozeile
mkdir -p /etc/php54/php-fcgi
vim /etc/php54/php-fcgi/php-starter

Der Inhalt der Datei:

Shell-Script
#!/bin/sh
 
FCGID_STARTER_PHPBIN="/usr/bin/php54/php-cgi -c /etc/php54/cgi/"
 
exec $FCGID_STARTER_PHPBIN

Nach dem Speichern versehen wir die Datei mit den passenden Zugriffsrechten und setzen danach das Immutable Bit. Dadurch sind keine Änderungen mehr an der Datei möglich (auch nicht durch root-User), bis das Immutable Bit wieder gelöscht wird.

Kommandozeile
chmod 750 /etc/php54/php-fcgi/php-starter
chattr +i /etc/php54/php-fcgi/php-starter

Damit sind die Vorbereitungen abgeschlossen.
Was nun folgt sind die Einstellungen für die einzelnen Web-User, für die die neue PHP Version aktiviert werden sollen. Der Standard unter ISPConfig 2 ist PHP 5.3 als Apache mod_php.
Die folgenden Einstellungen müssen separat für jeden Benutzer vorgenommen werden, der die neue Version 5.4.14 verwenden soll.

Bei allen folgenden Befehlen und Dateien muss das {WEB_ID} jeweils durch den Namen des Webs ersetzt werden, z. B. web1, web17 oder web216.
{WEB_USER} muss durch den Besitzer des Webverzeichnisses ersetzt werden. Dies ist in den meisten Fällen der angelegte FTP Admin Account (z. B. web7_ftp oder web16_adminis). Wie die korrekten Werte sind, kann man sich leicht anzeigen lassen, indem man in das Webverzeichnis wechselt und sich dort die Dateiberechtigung ansieht:

Kommandozeile
cd /var/www/web1/
ls -ld web
 # Ausgabe:
 # drwxrwxr-x 14 web1_webmaster web1 4.0K Mar  5 04:00 web

In diesem Beispiel müsste also {WEB_ID} durch web1 und {WEB_USER} durch web1_webmaster ersetzt werden.

Kommandozeile
cp -a /etc/php54/php-fcgi /var/www/{WEB_ID}/
chown -R {WEB_USER}:{WEB_ID} /var/www/{WEB_ID}/php-fcgi
chattr +i /var/www/{WEB_ID}/php-fcgi/php-starter

Nachdem die Vorlagendatei in das Webverzeichnis kopiert wurde und die korrekten Dateirechte vergeben wurden, muss nun noch die Einstellung für den Apache VHost gemacht werden. Dies geschieht über ISPConfig in den Apache Direktiven:

Apache Direktiven
SuexecUserGroup {WEB_USER} {WEB_ID}
<filesmatch \.php$>
    SetHandler fcgid-script
</filesmatch>
 
AddHandler fcgid-script .php .php4 .php5
FCGIWrapper "/var/www/{WEB_ID}/php-fcgi/php-starter" .php
FCGIWrapper "/var/www/{WEB_ID}/php-fcgi/php-starter" .php5
FCGIWrapper "/var/www/{WEB_ID}/php-fcgi/php-starter" .php4

Eigentlich war es das schon und das Web sollte auf PHP 5.4.14 laufen.
Durch die Umstellung kann es sein, dass PHP keinen Zugriff mehr auf zuvor von PHP angelegte Dateien hat. Dies liegt dann daran, dass der Besitzer von Dateien, die mit PHP (mod_php) angelegt wurden www-data als Besitzer haben, da PHP als Apache Modul unter diesem Benutzer ausgeführt wird.
In der hier eingerichteten Variante wird PHP mit SuExec als {WEB_USER} ausgeführt.

Man kann sehr einfach alle Dateien finden, die www-data gehören und den Besitzer ändern:

Kommandozeile
cd /var/www/{WEB_ID}/web
find /var/www/{WEB_ID}/web -user www-data -exec chown {WEB_USER}:{WEB_ID} {} \;

Natürlich muss auch hier wieder {WEB_USER} und {WEB_ID} ersetzt werden. Achtung: das {} am Ende wird nicht ersetzt!

Zum Testen der PHP Version ist es am einfachsten eine einfache PHP Datei in das Web-Verzeichnis zu legen, die nur den folgenden Inhalt hat:

PHP
< ?php phpinfo(); ?>

Falls beim Aufruf dieser Datei im Webbrowser noch die falsche PHP Version angezeigt wird oder ein Fehler 500 auftritt, oder der Apache sich nicht starten lässt hilft es die Fehlermeldungen in den Logdateien zu lesen.
Die wichtigsten Meldungen sind hierbei im SuExec Log (/var/log/apache2/suexec.log) und im Apache Log (/var/www/webXY/log/error.log) zu finden.
Der häufigste Fehler sind fehlerhafte Berechtigungen der php-starter Datei, die zu einem Streik von SuExec führen.

Jetzt noch ein Shellskript, das die Vorlage für den php-starter automatisch in das Webverzeichnis kopiert und den Text für die Apache Direktiven ausgibt. Der Aufruf erfolgt mit ./fcgi-copy.sh {WEB_USER} {WEB_ID}
Also z. B. ./fcgi-copy.sh web1_ftp_admin web1

Shell-Script
#!/bin/sh
WEB_USER=$1
WEB_ID=$2
 
if [ "$WEB_USER" = "" ] ; then
echo "$0 <web_user> <web_id>.";
exit 1;
fi
 
if [ "$WEB_ID" = "" ] ; then
echo "$0 <web_user> <web_id>.";
exit 1;
fi
 
if [ ! -e "/var/www/${WEB_ID}" ] ; then
echo "Das Verzeichnis /var/www/${WEB_ID} existiert nicht."
exit 1;
fi
 
if [ ! -e "/etc/php54/php-fcgi" ] ; then
echo "Das Vorlagenverzeichnis /etc/php54/php-fcgi existiert nicht."
exit 1;
fi
 
cp -a /etc/php54/php-fcgi /var/www/${WEB_ID}/
chown -R ${WEB_USER}:${WEB_ID} /var/www/${WEB_ID}/php-fcgi
chattr +i /var/www/${WEB_ID}/php-fcgi/php-starter
 
find /var/www/${WEB_ID}/web -user www-data -exec chown ${WEB_USER}:${WEB_ID} {} \;
 
echo "Bitte den folgenden Abschnitt in die Apache Direktiven von ${WEB_ID} einfügen:"
echo "====================================="
echo "SuexecUserGroup ${WEB_USER} ${WEB_ID}"
echo "<filesmatch \.php$>"
echo "    SetHandler fcgid-script"
echo "</filesmatch>"
echo ""
echo "AddHandler fcgid-script .php .php4 .php5"
echo "FCGIWrapper \"/var/www/${WEB_ID}/php-fcgi/php-starter\" .php"
echo "FCGIWrapper \"/var/www/${WEB_ID}/php-fcgi/php-starter\" .php5"
echo "FCGIWrapper \"/var/www/${WEB_ID}/php-fcgi/php-starter\" .php4"
echo ""
echo "====================================="</web_id></web_user></web_id></web_user>

Ganz zum Schluss noch ein Shell-Skript, das eigentlich alle oben genannten Schritte automatisiert und auch das fcgi-copy Skript im /root Verzeichnis anlegt.
Ich übernehme keine Gewähr für die Funktionalität – Verwendung auf eigene Gefahr.

Shell-Script
#!/bin/sh
 
if [[ $(id -u) -ne 0 ]] ; then
    echo "Dieses Script funktioniert nur als root!" ;
    exit 2 ;
fi
 
DEBIAN_OK=`cat /etc/debian_version`
 
if [[ "$DEBIAN_OK" = "" ]] ; then
  echo "Dies scheint nicht Debian zu sein...";
  exit;
fi
 
read -p "ACHTUNG! Es werden nun Pakete installiert und Dateien modifiziert. Soll die Installation gestartet werden (y/j/N)? " DOIT
 
if [[ "$DOIT" != "j" && "$DOIT" != "y" ]] ; then
    echo "Abgebrochen." ;
    exit 0 ;
fi
 
apt-get install -q -y libapache2-mod-fcgid apache2-suexec libpcre3-dev libpcre++-dev libpng12-dev libbz2-dev libcurl4-openssl-dev libc-client2007e-dev libjpeg-dev libgif-dev libgif4 libpthread-stubs0 libpthread-stubs0-dev libx11-dev libxau-dev libxcb1-dev libxdmcp-dev libxpm-dev x11proto-core-dev x11proto-input-dev x11proto-kb-dev xtrans-dev libfreetype6-dev libxml2-dev libmysqlclient-dev libfreetype6-dev
 
a2enmod fcgid
a2enmod suexec
 
cd /tmp
wget -q "http://de.php.net/get/php-5.4.14.tar.bz2/from/this/mirror" -O php.tar.bz2
tar xjf php.tar.bz2
cd php-5.4.14
 
CHECK=`grep "FcgidMaxRequestLen" /etc/apache2/mods-available/fcgid.conf`
if [[ "$CHECK" = "" ]] ; then
  CHECK=`grep "FcgidConnectTimeout" /etc/apache2/mods-available/fcgid.conf`
  if [[ "$CHECK" = "" ]] ; then
    echo "FcgidMaxRequestLen 1073741824" >> /etc/apache2/mods-available/fcgid.conf ;
  else
    sed -i -e "s/^\(\s*FcgidConnectTimeout.*\)$/\1\n  FcgidMaxRequestLen 1073741824/" /etc/apache2/mods-available/fcgid.conf ;
  fi
else
  sed -i -r "s/^\s*FcgidMaxRequestLen\s+\d+.*$/FcgidMaxRequestLen 1073741824/" /etc/apache2/mods-available/fcgid.conf ;
fi
 
/etc/init.d/apache2 stop
/etc/init.d/apache2 start
 
CHECK=`uname -a | grep 'amd64'`
if [[ "$CHECK" = "" ]] ; then
  echo "Kompiliere auf 32Bit System" ;
  ./configure --prefix=/usr/share/php54 --datadir=/usr/share/php54 --mandir=/usr/share/man --bindir=/usr/bin/php54 --with-libdir=lib --includedir=/usr/include/php54 --sysconfdir=/etc/php54/apache2 --with-config-file-path=/etc/php54/apache2 --with-config-file-scan-dir=/etc/php54/conf.d --enable-libxml --enable-session --with-pcre-regex=/usr --enable-xml --enable-simplexml --enable-filter --disable-debug --enable-inline-optimization --disable-rpath --disable-static --enable-shared --with-pic --with-gnu-ld --with-mysql --with-gd --with-jpeg-dir --with-png-dir --with-xpm-dir --enable-exif --with-zlib --with-bz2 --with-curl --with-ldap --with-mysqli --with-freetype-dir --enable-soap --enable-sockets --enable-calendar --enable-ftp --enable-mbstring --enable-gd-native-ttf --enable-bcmath --enable-zip --with-pear --with-openssl --with-imap --with-imap-ssl --with-kerberos --enable-phar --enable-pdo --with-pdo-mysql --with-mysqli ;
else
  echo "Kompiliere auf 64Bit System" ;
  ./configure --prefix=/usr/share/php54 --datadir=/usr/share/php54 --mandir=/usr/share/man --bindir=/usr/bin/php54 --with-libdir=lib --includedir=/usr/include/php54 --sysconfdir=/etc/php54/apache2 --with-config-file-path=/etc/php54/apache2 --with-config-file-scan-dir=/etc/php54/conf.d --enable-libxml --enable-session --with-pcre-regex=/usr --enable-xml --enable-simplexml --enable-filter --disable-debug --enable-inline-optimization --disable-rpath --disable-static --enable-shared --with-pic --with-gnu-ld --with-mysql --with-gd --with-jpeg-dir --with-png-dir --with-xpm-dir --enable-exif --with-zlib --with-bz2 --with-curl --with-ldap --with-mysqli --with-freetype-dir --enable-soap --enable-sockets --enable-calendar --enable-ftp --enable-mbstring --enable-gd-native-ttf --enable-bcmath --enable-zip --with-pear --with-openssl --with-imap --with-imap-ssl --with-kerberos --enable-phar --enable-pdo --with-pdo-mysql --with-mysqli ;
fi
 
make && make install
 
echo "Kompilierung ist abgeschlossen. Sollten Fehler aufgetreten sein, bitte jetzt STRG+C druecken!"
read -p "Lege nun Skripte an... ENTER um fortzufahren (STRG+C um abzubrechen)"
 
cp /etc/php5/apache2/php.ini /etc/php54/apache2/
mkdir /etc/php54/cgi
cp /etc/php5/apache2/php.ini /etc/php54/cgi/
 
mkdir -p /etc/php54/php-fcgi/
 
echo '#!/bin/sh
 
FCGID_STARTER_PHPBIN="/usr/bin/php54/php-cgi -c /etc/php54/cgi/"
     
exec $FCGID_STARTER_PHPBIN
' > /etc/php54/php-fcgi/php-starter
 
chmod 750 /etc/php54/php-fcgi/php-starter
chattr +i /etc/php54/php-fcgi/php-starter
 
 
echo '#!/bin/sh
WEB_USER=$1
WEB_ID=$2
  
if [ "$WEB_USER" = "" ] ; then
echo "$0 <web_user> <web_id>.";
echo "z. B. $0 web4_ftp_adm web4";
exit 1;
fi
  
if [ "$WEB_ID" = "" ] ; then
echo "$0 <web_user> <web_id>.";
echo "z. B. $0 web4_ftp_adm web4";
exit 1;
fi
  
if [ ! -e "/var/www/${WEB_ID}" ] ; then
echo "Das Verzeichnis /var/www/${WEB_ID} existiert nicht."
exit 1;
fi
  
if [ ! -e "/etc/php54/php-fcgi" ] ; then
echo "Das Vorlagenverzeichnis /etc/php54/php-fcgi existiert nicht."
exit 1;
fi
  
cp -a /etc/php54/php-fcgi /var/www/${WEB_ID}/
chown -R ${WEB_USER}:${WEB_ID} /var/www/${WEB_ID}/php-fcgi
chattr +i /var/www/${WEB_ID}/php-fcgi/php-starter
  
find /var/www/${WEB_ID}/web -user www-data -exec chown ${WEB_USER}:${WEB_ID} {} \;
  
echo "Bitte den folgenden Abschnitt in die Apache Direktiven von ${WEB_ID} einfügen:"
echo "====================================="
echo "SuexecUserGroup ${WEB_USER} ${WEB_ID}"
echo "<filesmatch \.php$>"
echo "    SetHandler fcgid-script"
echo "</filesmatch>"
echo ""
echo "AddHandler fcgid-script .php .php4 .php5"
echo "FCGIWrapper \"/var/www/${WEB_ID}/php-fcgi/php-starter\" .php"
echo "FCGIWrapper \"/var/www/${WEB_ID}/php-fcgi/php-starter\" .php5"
echo "FCGIWrapper \"/var/www/${WEB_ID}/php-fcgi/php-starter\" .php4"
echo ""
echo "====================================="' > /root/fcgi-copy.sh
 
chmod 700 /root/fcgi-copy.sh
 
echo "FERTIG!"
echo "Mit dem Befehl /root/fcgi-copy.sh kann nun ein Web fuer PHP 5.4 vorbereitet werden."</web_id></web_user></web_id></web_user>
Dieser Artikel wurde von Marius Burkard verfasst.

Marius Burkard ist Diplom-Wirtschaftsinformatiker und arbeitet seit 2006 als selbstständiger Software-Entwickler und Linux-Server-Administrator mit der Firma pixcept KG. Er ist unter anderem mitverantwortlich für die Projekte Was-lese-ich.de und ISPProtect.

Und jetzt du! Deine Meinung?

Erforderliche Felder sind mit einem Asterisk (*) gekennzeichnet. Die E-Mail-Adresse wird nicht veröffentlicht.