Makrothek
PHP PHP

Problembeschreibung:

Wenn es mal wieder länger dauert...

Programmiert man mittels PHP Berechnungen oder Prozesse, deren Abarbeitung längere Zeit in Anspruch nehmen, ist es für den Benutzer vor dem Bildschirm nicht zumutbar, diese Zeit ohne entsprechende Pausenüberbrückung (Wartemeldung oder Fortschrittsbalken) zu warten. Außerdem läuft man Gefahr, dass entweder der Browser oder sogar der Webserver selbst den Prozess wegen eines Timeouts abbricht.

Lösungsidee

Die Lösung besteht darin, den lang dauernden Prozess als parallelen Prozess (Hintergrundprozess oder Background Process) in PHP zu starten. Dafür gibt es mehrere Möglichkeiten (exec, system, popen, WScript, etc.), die jedoch je nach Sicherheitseinstellungen und Hostsystem (Windows, Linux) mehr oder weniger ausscheiden.

Hinzu kommt, was bei Linux tadellos funktioniert, funktioniert bei Windows noch lange nicht und umgekehrt. Da Linux hier sehr pflegeleicht ist, werde ich mich auf die funktionierende Windows-Variante beschränken. Außerdem setze ich eine Windows-Installation voraus, deren Zugriffsbeschränkungen (Dateien, Verzeichnisse, Systemprogramme) der Standardeinstellungen nach einer frischen Installation entsprechen.

Um einen parallelen Prozess aus PHP heraus zu starten, welches als FastCGI im Microsoft-Webserver IIS 7 unter Windows 7 (64bit) läuft, hat sich die Popen-Pclose-Variante als die zuverlässigste unter verschiedenen Windowssystemen herausgestellt.

Achtung! Diese Variante funktioniert nicht bei Windows-Server-Betriebssystemen, da der Befehl POPEN die Programme über die COMMAND.COM startet, die unter Windows-Server-Betriebssystemen normal nicht zugänglich ist.

Damit die Popen-Pclose-Variante auch funktioniert, müssen folgende Voraussetzungen geschaffen sein:

  • In der php.ini muss zusätzlich die Extension=php_com_dotnet.dll aktiviert sein.
  • Die Befehle POPEN und PCLOSE dürfen nicht durch Safe-Mode-Einstellungen gesperrt sein.
  • Der PHP-Pfad zur php.exe muss in der PATH-Variable des Systems enthalten sein.
  • Wenn das Verzeichnis durch den IIS mit Zugriffsbeschränkungen (Benutzerauthentifizierung) versehen ist, dann ist darauf zu achten, dass unbedingt die Windows-Authentifizierung deaktiviert ist und stattdessen die Standard-Authentifizierung aktiviert ist. Die Windows-Authentifizierung scheint hier Fehler zu produzieren. Popen meldet dann immer No such file or direktory.

Sollte es dann immer noch nicht möglich sein, einen parallelen Prozess zu starten, dann sind womöglich die Sicherheitseinstellungen verstellt, oder die php.exe oder die auszuführende PHP-Datei wurden im Dateisystem nicht gefunden. Bitte keine Lösungen wie - der cmd.exe Ausführungsrechte für den IUSR geben - anwenden.

Programmcode

<?php 
  // Aufruf eines parallelen PHP-Prozesses mittels Popen und Pclose
  $handle = popen("start /B php \\"C:\\\\inetpub\\\\wwwroot\\\\background_process.php\\" && exit", "r");
  if ($handle !== false) {// Paralleler Prozess wurde erfolgreich gestartet}
  else {// Fehler! Es konnte kein paralleler Prozess gestartet werden}

  if ($handle) {pclose($handle);}
?>