In PHP-Skripten stößt man beim Aufruf von include()
, require()
, fopen()
oder deren Derivaten wie include_once
, require_once
oder sogar move_uploaded_file()
häufig auf einen Fehler oder eine Warnung:
Failed to open stream : No such file or directory.
Was ist ein gutes Verfahren, um schnell die Ursache des Problems zu finden?
Es gibt viele Gründe, warum man auf diesen Fehler stoßen könnte, und so hilft eine gute Checkliste, was zuerst zu überprüfen ist, erheblich. Nehmen wir an, wir suchen nach einem Fehler in der folgenden Zeile:
require "/path/to/file"
require*
oder include*
aufgerufen wird, in eine eigene Variable, echoen Sie es, kopieren Sie es und versuchen Sie, es von einem Terminal aus aufzurufen:
$path = "/path/to/file";
echo "Pfad : $path";
require "$pfad";
Dann, in einem Terminal:
cat /users/tony/htdocs
lautenrequire __DIR__ . "/relative/path/from/current/file"
. Die magische Konstante __DIR__
gibt das Verzeichnis der aktuellen Datei zurück.SITE_ROOT
-Konstante :config.php
.config.php
define('SITE_ROOT', DIR);config.php
ein, und verwenden Sie dann die Konstante SITE_ROOT
, wo immer Sie wollen:
require_once DIR."/../config.php";
...
require_once SITE_ROOT."/andere/file.php";
Diese 2 Praktiken machen Ihre Anwendung auch portabler, da sie nicht auf Ini-Einstellungen wie den Include-Pfad angewiesen ist.
Eine weitere Möglichkeit, Dateien weder relativ noch absolut einzubinden, besteht darin, sich auf den include path zu verlassen. Dies ist oft der Fall für Bibliotheken oder Frameworks wie das Zend Framework. Eine solche Einbindung wird wie folgt aussehen:
include "Zend/Mail/Protocol/Imap.php"
In diesem Fall müssen Sie sicherstellen, dass der Ordner, in dem sich "Zend" befindet, Teil des Include-Pfads ist. Sie können den Include-Pfad mit überprüfen:
echo get_include_path();
Sie können einen Ordner hinzufügen mit :
set_include_path(get_include_path().":"."/path/to/new/folder");
Es könnte sein, dass der Benutzer, unter dem der Serverprozess (Apache oder PHP) läuft, einfach keine Berechtigung hat, von dieser Datei zu lesen oder in sie zu schreiben. 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);
Um die Berechtigungen für die Datei herauszufinden, geben Sie den folgenden Befehl in das Terminal ein:
ls -l <path/to/file>
und schauen Sie unter permission symbolic notation
Wenn keine der obigen Maßnahmen funktioniert hat, liegt das Problem wahrscheinlich darin, dass einige PHP-Einstellungen den Zugriff auf diese Datei verbieten. Drei Einstellungen könnten relevant sein:
phpinfo()
oder durch die Verwendung von ini_get("open_basedir")
überprüft werden.ini_get("allow_url_include")
geprüft und mit ini_set("allow_url_include", "1")
gesetzt werden
Wenn keine der oben genannten Möglichkeiten zur Diagnose des Problems führt, gibt es noch einige Sonderfälle, die auftreten können:
Es kann vorkommen, dass man eine Bibliothek, zum Beispiel das Zend-Framework, mit einem relativen oder absoluten Pfad einbindet. Zum Beispiel :
require "/usr/share/php/libzend-framework-php/Zend/Mail/Protocol/Imap.php"
Aber dann erhalten Sie immer noch die gleiche Art von Fehler. Das könnte passieren, weil die Datei, die man (erfolgreich) eingebunden hat, selbst eine Include-Anweisung für eine andere Datei hat, und diese zweite Include-Anweisung nimmt an, dass man den Pfad dieser Bibliothek zum Include-Pfad hinzugefügt hat. Zum Beispiel könnte die zuvor erwähnte Zend Framework Datei das folgende include haben:
include "Zend/Mail/Protocol/Exception.php"
was weder ein Einschluss durch einen relativen Pfad, noch durch einen absoluten Pfad ist. Es wird angenommen, dass das Zend Framework Verzeichnis zum Include Pfad hinzugefügt wurde.
In einem solchen Fall ist die einzige praktische Lösung, das Verzeichnis zum eigenen Include-Pfad hinzuzufügen.
Wenn Sie ein sicherheitsverbessertes Linux verwenden, könnte dies der Grund für das Problem sein, da es den Zugriff auf die Datei vom Server aus 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, ist SELinux auf Ihrem System nicht aktiviert. Wenn er vorhanden ist, sollte er Ihnen sagen, ob er erzwungen wird oder nicht.
Um zu überprüfen, ob SELinux-Richtlinien der Grund für das Problem sind, können Sie versuchen, sie vorübergehend zu deaktivieren. Seien Sie jedoch VORSICHTIG, denn dadurch wird der Schutz vollständig deaktiviert. Tun Sie dies nicht auf Ihrem Produktionsserver.
setenforce 0
Wenn das Problem bei ausgeschaltetem SELinux nicht mehr auftritt, dann ist dies die Ursache. Um das Problem zu lösen, müssen Sie SELinux entsprechend konfigurieren. Die folgenden Kontexttypen werden benötigt:
httpd_sys_content_t
für Dateien, die Ihr Server lesen können sollhttpd_sys_rw_content_t
für Dateien, auf die Sie lesend und schreibend zugreifen wollenhttpd_log_t
für Log-Dateienhttpd_cache_t
für das Cache-Verzeichnis
Um zum Beispiel den Kontexttyp httpd_sys_content_t
dem Stammverzeichnis Ihrer Website zuzuweisen, führen Sie aus:semanage fcontext -a -t httpd_sys_content_t "/path/to/root(/.*)?"
restorecon -Rv /path/to/root
Wenn sich Ihre Datei in einem Home-Verzeichnis befindet, müssen Sie auch den Boolean httpd_enable_homedirs
aktivieren:
setsebool -P httpd_enable_homedirs 1
In jedem Fall kann es eine Vielzahl von Gründen geben, warum SELinux den Zugriff auf eine Datei verweigert, abhängig von Ihren Richtlinien. Das müssen Sie also selbst herausfinden. Hier finden Sie ein Tutorial speziell zur Konfiguration von SELinux für einen Webserver.
Wenn Sie Symfony verwenden und dieser Fehler beim Hochladen auf einen Server auftritt, dann kann es sein, dass der Cache der App nicht zurückgesetzt wurde, entweder weil app/cache
hochgeladen wurde oder der Cache nicht gelöscht wurde.
Sie können dies testen und beheben, indem Sie den folgenden Konsolenbefehl ausführen:
cache:clear
Anscheinend kann dieser Fehler auch beim Aufrufen von zip->close()
auftreten, wenn einige Dateien in der Zip-Datei Nicht-ASCII-Zeichen in ihrem Dateinamen enthalten, wie z. B. "é".
Eine mögliche Lösung besteht darin, den Dateinamen in utf8_decode()
einzuschließen, bevor die Zieldatei erstellt wird.
Gutschrift an Fran Cano für die Identifizierung und den Vorschlag einer Lösung für dieses Problem
Um die (wirklich gute) Antwort zu ergänzen
open_basedir" ist eine Angabe, die Sie verwirren kann, weil sie in einer Webserver-Konfiguration angegeben werden kann. Während dies leicht zu beheben ist, wenn Sie Ihren eigenen dedizierten Server betreiben, gibt es einige Shared-Hosting-Softwarepakete (wie Plesk, cPanel, etc.), die eine Konfigurationsrichtlinie auf einer Pro-Domain-Basis konfigurieren. Da die Software die Konfigurationsdatei (z. B. httpd.conf
) erstellt, können Sie diese Datei nicht direkt ändern, da die Hosting-Software sie beim Neustart einfach überschreibt.
Bei Plesk gibt es einen Ort, an dem die mitgelieferte httpd.conf
überschrieben werden kann: vhost.conf
. Nur der Server-Administrator kann diese Datei schreiben. Die Konfiguration für Apache sieht etwa 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 Server-Administrator, das Handbuch für die von ihm verwendete Hosting- und Webserver-Software zu konsultieren.
Es ist wichtig zu wissen, dass sich die Ausführung einer Datei über Ihren Webserver stark von der Ausführung einer Befehlszeile oder eines Cron-Jobs unterscheidet. Der große Unterschied besteht darin, dass Ihr Webserver einen eigenen Benutzer und eigene Berechtigungen hat. Aus Sicherheitsgründen ist dieser Benutzer ziemlich eingeschränkt. Apache zum Beispiel ist oft apache
, www-data
oder httpd
(je nach Server). Ein Cron-Job oder eine CLI-Ausführung hat die Berechtigungen des Benutzers, der sie ausführt (d. h. ein PHP-Skript, das als root ausgeführt wird, hat die Berechtigungen von root).
Oftmals wird ein Berechtigungsproblem wie folgt gelöst (Beispiel Linux)
chmod 777 /path/to/file
Dies ist keine gute Idee, da die Datei oder das Verzeichnis nun weltweit beschreibbar ist. Wenn Sie der Eigentümer des Servers und der einzige Benutzer sind, ist das keine große Sache, aber wenn Sie in einer gemeinsam genutzten Hosting-Umgebung sind, haben Sie gerade jedem auf Ihrem Server Zugriff gegeben.
Sie müssen die Benutzer ermitteln, die Zugang benötigen, und nur diesen Zugang gewähren. Sobald Sie wissen, welche Benutzer Zugang benötigen, müssen Sie sicherstellen, dass
Dieser Benutzer ist Eigentümer der Datei und möglicherweise des übergeordneten Verzeichnisses (insbesondere des übergeordneten Verzeichnisses, wenn Sie Dateien schreiben wollen). In den meisten Shared-Hosting-Umgebungen ist dies kein Problem, da Ihr Benutzer alle Dateien unterhalb Ihres Stammverzeichnisses besitzen sollte. Ein Linux-Beispiel ist unten dargestellt
chown apache:apache /pfad/zu/datei
Der Benutzer, und nur dieser Benutzer, hat Zugriff. Unter Linux wäre eine gute Praxis chmod 600
(nur der Besitzer kann lesen und schreiben) oder chmod 644
(der Besitzer kann schreiben, aber jeder kann lesen)
Eine ausführlichere Diskussion über Linux/Unix-Berechtigungen und Benutzer können Sie hier lesen
Eine andere mögliche Ursache: Umbenennen und/oder Verschieben von Dateien in einem Texteditor. Ich habe alle oben genannten Schritte ohne Erfolg durchgeführt, bis ich die Datei, die diesen Fehler verursachte, löschte und eine neue erstellte, wodurch das Problem behoben wurde.