it-swarm.com.de

PHP - Fehler beim Öffnen des Streams: Keine solche Datei oder Verzeichnis

In PHP -Skripten, ob Aufruf von include(), require(), fopen() oder deren Ableitungen wie include_once, require_once oder sogar move_uploaded_file(), wird oft ein Fehler oder eine Warnung angezeigt: 

Stream konnte nicht geöffnet werden: Keine solche Datei oder Verzeichnis.

Was ist ein guter Prozess, um die Ursache des Problems schnell zu finden?

119

Es gibt viele Gründe, warum man auf diesen Fehler stößt, und daher hilft eine gute Checkliste, was zuerst überprüft werden muss, erheblich.

Nehmen wir an, dass wir die folgende Zeile zur Fehlerbehebung verwenden:

require "/path/to/file"


Checkliste


1. Überprüfen Sie den Dateipfad auf Tippfehler

  • entweder manuell überprüfen (durch visuelle Überprüfung des Pfades)
  • oder verschieben Sie alles, was von require* oder include* aufgerufen wird, in eine eigene Variable, geben Sie es aus, kopieren Sie es und versuchen Sie, von einem Terminal aus darauf zuzugreifen:

    $path = "/path/to/file";
    
    echo "Path : $path";
    
    require "$path";
    

    Dann in einem Terminal:

    cat <file path pasted>
    


2. Überprüfen Sie, ob der Dateipfad in Bezug auf relative und absolute Pfade korrekt ist

  • beginnt es mit einem Schrägstrich "/", bezieht es sich nicht auf das Stammverzeichnis Ihres Website-Ordners (das Dokumentenstammverzeichnis), sondern auf das Stammverzeichnis Ihres Servers.
    • das Verzeichnis Ihrer Website könnte beispielsweise /users/tony/htdocs lauten.
  • beginnt es nicht mit einem Schrägstrich, wird entweder der Include-Pfad (siehe unten) verwendet oder der Pfad ist relativ. Wenn es relativ ist, berechnet PHP relativ zum Pfad des aktuellen Arbeitsverzeichnisses .
    • dies gilt nicht für den Pfad des Stammverzeichnisses Ihrer Website oder für die Datei, in die Sie eingeben
    • verwenden Sie daher immer absolute Dateipfade

Empfohlene Vorgehensweise :

Um Ihr Skript für den Fall, dass Sie Dinge verschieben und dennoch zur Laufzeit einen absoluten Pfad generieren, stabil zu machen, haben Sie zwei Möglichkeiten:

  1. benutze require __DIR__ . "/relative/path/from/current/file". Die magische Konstante __DIR__ gibt das Verzeichnis der aktuellen Datei zurück.
  2. definieren Sie selbst eine SITE_ROOT - Konstante:

    • erstellen Sie im Stammverzeichnis Ihrer Website eine Datei, z. config.php
    • schreiben Sie in config.php

      define('SITE_ROOT', __DIR__);
      
    • fügen Sie in jede Datei, in der Sie auf den Site-Stammordner verweisen möchten, config.php ein und verwenden Sie dann die Konstante SITE_ROOT, wo immer Sie möchten:

      require_once __DIR__."/../config.php";
      ...
      require_once SITE_ROOT."/other/file.php";
      

Diese beiden Vorgehensweisen machen Ihre Anwendung auch portabler, da sie nicht auf ini-Einstellungen wie dem Include-Pfad angewiesen ist.


3. Überprüfen Sie Ihren Include-Pfad

Eine andere Möglichkeit, Dateien weder relativ noch absolut einzuschließen, besteht darin, sich auf include path zu verlassen. Dies ist häufig bei Bibliotheken oder Frameworks wie dem Zend-Framework der Fall.

Eine solche Aufnahme sieht folgendermaßen aus:

include "Zend/Mail/Protocol/Imap.php"

In diesem Fall sollten Sie sicherstellen, dass der Ordner, in dem sich "Zend" befindet, Teil des Include-Pfads ist.

Sie können den Include-Pfad überprüfen mit:

echo get_include_path();

Sie können einen Ordner hinzufügen mit:

set_include_path(get_include_path().":"."/path/to/new/folder");


4. Überprüfen Sie, ob Ihr Server Zugriff auf diese Datei hat

Es kann sein, dass der Benutzer, der den Serverprozess (Apache oder PHP) ausführt, insgesamt keine Berechtigung zum Lesen oder Schreiben aus dieser Datei hat.

Um zu überprüfen, unter welchem ​​Benutzer der Server läuft, können Sie posix_getpwuid verwenden:

$user = posix_getpwuid(posix_geteuid());

var_dump($user);

Geben Sie den folgenden Befehl in das Terminal ein, um die Berechtigungen für die Datei zu ermitteln:

ls -l <path/to/file>

und schau auf Erlaubnis symbolische Notation


5. Überprüfen Sie die Einstellungen von PHP

Wenn keines der oben genannten Verfahren funktioniert hat, besteht das Problem wahrscheinlich darin, dass einige PHP) - Einstellungen den Zugriff auf diese Datei untersagen.

Drei Einstellungen könnten relevant sein:

  1. open_basedir
    • Wenn dies gesetzt ist, kann PHP nicht auf Dateien außerhalb des angegebenen Verzeichnisses zugreifen (auch nicht über einen symbolischen Link).
    • Das Standardverhalten ist jedoch, dass es nicht festgelegt wird. In diesem Fall gibt es keine Einschränkung
    • Dies kann entweder durch Aufrufen von phpinfo() oder durch Verwenden von ini_get("open_basedir") überprüft werden.
    • Sie können die Einstellung ändern, indem Sie entweder Ihre php.ini-Datei oder Ihre httpd.conf-Datei bearbeiten
  2. abgesicherter Modus
    • wenn dies aktiviert ist, gelten möglicherweise Einschränkungen. Dies wurde jedoch in PHP 5.4 entfernt. Wenn Sie immer noch eine Version verwenden, die ein Upgrade im abgesicherten Modus auf eine PHP Version mit dem Namen wird noch unterstützt .
  3. allow_url_fopen und allow_url_include
    • dies gilt nur für das Einschließen oder Öffnen von Dateien über einen Netzwerkprozess wie http: //, nicht für den Versuch, Dateien in das lokale Dateisystem einzuschließen
    • dies kann mit ini_get("allow_url_include") überprüft und mit ini_set("allow_url_include", "1") eingestellt werden


Eckkoffer

Wenn keine der oben genannten Methoden zur Diagnose des Problems aktiviert ist, können die folgenden besonderen Situationen auftreten:


1. Die Einbeziehung einer Bibliothek, die sich auf den Include-Pfad stützt

Es kann vorkommen, dass Sie eine Bibliothek, z. B. das Zend Framework, mit einem relativen oder absoluten Pfad einbinden. Beispielsweise :

require "/usr/share/php/libzend-framework-php/Zend/Mail/Protocol/Imap.php"

Aber dann erhalten Sie immer noch die gleiche Art von Fehler.

Dies kann passieren, weil die von Ihnen (erfolgreich) eingeschlossene Datei selbst eine include-Anweisung für eine andere Datei hat und diese zweite include-Anweisung davon ausgeht, dass Sie den Pfad dieser Bibliothek zum include-Pfad hinzugefügt haben.

Die oben erwähnte Zend Framework-Datei könnte beispielsweise Folgendes enthalten:

include "Zend/Mail/Protocol/Exception.php" 

dies ist weder eine Einbeziehung durch den relativen Pfad noch durch den absoluten Pfad. Es wird davon ausgegangen, dass das Zend Framework-Verzeichnis zum Include-Pfad hinzugefügt wurde.

In einem solchen Fall besteht die einzige praktikable Lösung darin, das Verzeichnis zu Ihrem Include-Pfad hinzuzufügen.


2. SELinux

Wenn Sie mit Security-Enhanced Linux arbeiten, ist dies möglicherweise der Grund für das Problem, da der Server den Zugriff auf die Datei verweigert.

Um zu überprüfen, ob SELinux auf Ihrem System aktiviert ist , führen Sie den Befehl sestatus in einem Terminal aus. Wenn der Befehl nicht vorhanden ist, befindet sich SELinux nicht auf Ihrem System. Wenn es existiert, sollte es Ihnen mitteilen, ob es erzwungen wird oder nicht.

Um zu überprüfen, ob SELinux-Richtlinien der Grund für das Problem sind, können Sie es vorübergehend deaktivieren. Seien Sie jedoch VORSICHTIG, da hierdurch der Schutz vollständig deaktiviert wird. Tun Sie dies nicht auf Ihrem Produktionsserver.

setenforce 0

Wenn das Problem mit SELinux nicht mehr besteht, ist dies die Hauptursache.

Um das Problem zu lösen , müssen Sie SELinux entsprechend konfigurieren.

Folgende Kontexttypen werden benötigt:

  • httpd_sys_content_t Für Dateien, die Ihr Server lesen soll
  • httpd_sys_rw_content_t Für Dateien, auf die Sie Lese- und Schreibrechte haben möchten
  • httpd_log_t Für Protokolldateien
  • httpd_cache_t Für das Cache-Verzeichnis

Führen Sie beispielsweise Folgendes aus, um Ihrem Website-Stammverzeichnis den Kontexttyp httpd_sys_content_t Zuzuweisen:

semanage fcontext -a -t httpd_sys_content_t "/path/to/root(/.*)?"
restorecon -Rv /path/to/root

Wenn sich Ihre Datei in einem Ausgangsverzeichnis befindet, müssen Sie auch den Booleschen Wert httpd_enable_homedirs Aktivieren:

setsebool -P httpd_enable_homedirs 1

In jedem Fall kann es abhängig von Ihren Richtlinien verschiedene Gründe geben, warum SELinux den Zugriff auf eine Datei verweigert. Sie müssen sich also danach erkundigen. Hier ist ein Tutorial speziell zur Konfiguration von SELinux für einen Webserver.


3. Symfony

Wenn Sie Symfony verwenden und beim Hochladen auf einen Server dieser Fehler auftritt, wurde der Cache der App möglicherweise nicht zurückgesetzt, da entweder app/cache Hochgeladen oder der Cache nicht geleert wurde .

Sie können dies testen und beheben, indem Sie den folgenden Konsolenbefehl ausführen:

cache:clear


4. Nicht-ACSII-Zeichen in der Zip-Datei

Anscheinend kann dieser Fehler auch beim Aufrufen von Zip->close() auftreten, wenn einige Dateien in der Zip-Datei Nicht-ASCII-Zeichen im Dateinamen enthalten, z. B. "é".

Eine mögliche Lösung besteht darin, den Dateinamen in utf8_decode() zu setzen, bevor Sie die Zieldatei erstellen.

Dank an Fran Cano um eine Lösung für dieses Problem zu finden und vorzuschlagen

221

Zu der (wirklich guten) vorhandenen Antwort hinzufügen

Shared-Hosting-Software

open_basedir ist einer, der Sie stumpfen kann, weil er in einer Webserverkonfiguration angegeben werden kann. Dies lässt sich leicht beheben, wenn Sie einen eigenen dedizierten Server betreiben. Es gibt jedoch einige gemeinsam genutzte Hosting-Softwarepakete (wie Plesk, cPanel usw.), die eine Konfigurationsanweisung auf Domänenbasis konfigurieren. Da die Software die Konfigurationsdatei erstellt (d. H. httpd.conf), können Sie diese Datei nicht direkt ändern, da die Hosting-Software sie beim Neustart nur überschreibt.

Mit Plesk können Sie den angegebenen httpd.conf mit dem Namen vhost.conf überschreiben. Nur der Serveradministrator kann diese Datei schreiben. Die Konfiguration für Apache sieht ungefähr so ​​aus

<Directory /var/www/vhosts/domain.com>
    <IfModule mod_php5.c>
        php_admin_flag engine on
        php_admin_flag safe_mode off
        php_admin_value open_basedir "/var/www/vhosts/domain.com:/tmp:/usr/share/pear:/local/PEAR"
    </IfModule>
</Directory>

Bitten Sie Ihren Serveradministrator, das Handbuch für die verwendete Hosting- und Webserver-Software zu lesen.

Dateiberechtigungen

Beachten Sie, dass die Ausführung einer Datei über Ihren Webserver sich sehr von der Ausführung einer Befehlszeile oder eines Cron-Jobs unterscheidet. Der große Unterschied ist, dass Ihr Webserver über eigene Benutzer und Berechtigungen verfügt. Aus Sicherheitsgründen ist dieser Benutzer ziemlich eingeschränkt. Apache zum Beispiel ist häufig Apache, www-data oder httpd (abhängig von Ihrem Server). Ein Cron-Job oder eine CLI-Ausführung verfügt über alle Berechtigungen, die der Benutzer hat, der ihn ausführt (d. H. Das Ausführen eines PHP - Skripts als root wird mit Berechtigungen von root ausgeführt).

In vielen Fällen lösen Benutzer ein Berechtigungsproblem, indem sie Folgendes tun (Linux-Beispiel).

chmod 777 /path/to/file

Dies ist keine clevere Idee, da die Datei oder das Verzeichnis jetzt weltweit beschreibbar ist. Wenn Sie den Server besitzen und der einzige Benutzer sind, ist dies keine große Sache, aber wenn Sie sich in einer gemeinsam genutzten Hosting-Umgebung befinden, haben Sie gerade jedem auf Ihrem Server Zugriff gewährt.

Was Sie tun müssen, ist, die Benutzer zu ermitteln, die Zugriff benötigen, und nur diesen Benutzern Zugriff zu gewähren. Wenn Sie wissen, welche Benutzer Zugriff benötigen, sollten Sie dies sicherstellen 

  1. Dieser Benutzer besitzt die Datei und möglicherweise das übergeordnete Verzeichnis (insbesondere das übergeordnete Verzeichnis, wenn Sie Dateien schreiben möchten). In den meisten gemeinsam genutzten Hosting-Umgebungen ist dies kein Problem, da Ihr Benutzer alle Dateien unter Ihrem Stamm besitzen sollte. Ein Linux-Beispiel ist unten gezeigt

    chown Apache:apache /path/to/file
    
  2. Der Benutzer und nur dieser Benutzer hat Zugriff. Unter Linux wäre eine bewährte Methode chmod 600 (nur der Besitzer kann lesen und schreiben) oder chmod 644 (der Besitzer kann schreiben, aber jeder kann lesen)

Sie können eine ausführlichere Beschreibung der Linux/Unix-Berechtigungen und der Benutzer finden Sie hier }

11
Machavity

Fügen Sie ein Skript mit Abfrageparametern hinzu

Das war mein Fall. Es ist tatsächlich mit der Frage # 4485874 verlinkt, aber ich werde es hier in Kürze erklären.
Wenn Sie versuchen, path/to/script.php?parameter=value anzufordern, sucht PHP nach der Datei script.php?parameter=value, da Sie unter UNIX solche Pfade verwenden können.
Wenn Sie wirklich einige Daten an das enthaltene Skript übergeben müssen, deklarieren Sie es einfach als $variable=... oder $GLOBALS[]=... oder auf andere Weise.

1
Paul Lynn
  1. Schauen Sie sich den genauen Fehler an

Mein Code funktionierte auf allen Maschinen einwandfrei, aber nur auf diesem gab es Probleme (was früher funktioniert hat, denke ich). Echo "document_root" Pfad zum Debuggen verwendet und auch den Fehler genau untersucht, fand dies

Warnung: include ( D: /MyProjects/testproject//functions/connections.php ): Öffnen des Streams fehlgeschlagen:

Sie können leicht sehen, wo die Probleme sind. Die Probleme liegen vor Funktionen

$document_root = $_SERVER['DOCUMENT_ROOT'];
echo "root: $document_root";
include($document_root.'/functions/connections.php');

Entfernen Sie einfach die Ladung/aus Include und es sollte gut funktionieren. Interessant ist, dass dieses Verhalten in verschiedenen Versionen unterschiedlich ist. Ich verwende den gleichen Code auf Laptop, Macbook Pro und diesem PC. Hoffe das hilft jemandem.

  1. Kopieren Sie im Browser nach dem Dateispeicherort, um sicherzustellen, dass die Datei vorhanden ist. Manchmal werden Dateien unerwartet gelöscht (bei mir passiert) und dies war auch das Problem in meinem Fall.
1
Hammad Khan

Eine andere mögliche Ursache: Umbenennen und/oder Verschieben von Dateien in einem Texteditor. Ich habe alle oben genannten Schritte ohne Erfolg durchlaufen, bis ich die Datei gelöscht habe, die diesen Fehler ausgelöst hat, und eine neue erstellt, die das Problem behoben hat.

0
zMeadz