I PHP-scripts, uanset om man kalder include()
, require()
, fopen()
, eller deres afledninger som include_once
, require_once
, eller endda move_uploaded_file()
, løber man ofte ind i en fejl eller advarsel:
Failed to open stream : No such file or directory.
Hvad er en god fremgangsmåde til hurtigt at finde årsagen til problemet?
Der er mange grunde til, at man kan løbe ind i denne fejl, og derfor er en god tjekliste over, hvad man skal tjekke først, en stor hjælp. Lad os antage, at vi er ved at fejlfinde følgende linje:
require "/path/to/file"
require*
eller include*
, til sin egen variabel, ekko den, kopier den og prøv at få adgang til den fra en terminal:
$path = "/path/to/file";
echo "Path : $path";
require "$path";
Derefter, i en terminal:
cat /users/tony/htdocs
.require __DIR__ . "/relative/path/fra/current/file"
. Den magiske konstant __DIR__
returnerer mappen for den aktuelle fil.SITE_ROOT
-konstant :config.php
.config.php
skal du skrive
define('SITE_ROOT', DIR);config.php
, og brug derefter konstanten SITE_ROOT
hvor du vil :
require_once DIR."/../config.php";
...
require_once SITE_ROOT."/other/file.php";;
Disse 2 fremgangsmåder gør også din applikation mere portabel, fordi den ikke er afhængig af ini indstillinger som f.eks. include stien.
En anden måde at inkludere filer på, hverken relativt eller rent absolut, er at stole på include path. Dette er ofte tilfældet for biblioteker eller frameworks såsom Zend framework. En sådan inklusion vil se således ud :
include "Zend/Mail/Protocol/Imap.php"
I det tilfælde skal du sikre dig, at den mappe, hvor "Zend" er, er en del af include-stien. Du kan tjekke inddragelsesstien med :
echo get_include_path();
Du kan tilføje en mappe til den med :
set_include_path(get_include_path().":"."/path/to/new/folder");
Det kan være, at alt sammen, at brugeren, der kører serverprocessen (Apache eller PHP) simpelthen ikke har tilladelse til at læse fra eller skrive til den pågældende fil. For at kontrollere under hvilken bruger serveren kører kan du bruge posix_getpwuid :
$user = posix_getpwuid(posix_geteuid());
var_dump($user);
For at finde ud af tilladelserne på filen skal du skrive følgende kommando i terminalen:
ls -l <path/to/file>
og se på permission symbolic notation
Hvis ingen af ovenstående har virket, er problemet sandsynligvis, at nogle PHP-indstillinger forbyder adgang til den pågældende fil. Tre indstillinger kan være relevante :
phpinfo()
eller ved at bruge ini_get("open_basedir")
ini_get("allow_url_include")
og sættes med ini_set("allow_url_include", "1")
Hvis ingen af de ovennævnte har været i stand til at diagnosticere problemet, er her nogle særlige situationer, der kan opstå :
Det kan ske, at du inkluderer et bibliotek, f.eks. Zend framework, ved hjælp af en relativ eller absolut sti. For eksempel :
require "/usr/share/php/libzend-framework-php/Zend/Mail/Protocol/Imap.php"
Men så får du stadig den samme slags fejl. Dette kan ske, fordi den fil, som du (med succes) har inkluderet, selv har en include-erklæring for en anden fil, og den anden include-erklæring antager, at du har tilføjet stien til det pågældende bibliotek til include-stien. F.eks. kunne den førnævnte Zend framework-fil have følgende include :
include "Zend/Mail/Protocol/Exception.php"
hvilket hverken er en inklusion ved relativ sti eller ved absolut sti. Det forudsætter, at Zend framework-mappen er blevet tilføjet til include-stien.
I et sådant tilfælde er den eneste praktiske løsning at tilføje mappen til din include-sti.
Hvis du kører Security-Enhanced Linux, kan det være årsagen til problemet ved at nægte adgang til filen fra serveren.
For at kontrollere, om SELinux er aktiveret på dit system, skal du køre kommandoen sestatus
i en terminal. Hvis kommandoen ikke findes, er SELinux ikke på dit system. Hvis den findes, bør den fortælle dig, om den er håndhævet eller ej.
For at kontrollere, om SELinux-politikker er årsagen til problemet, kan du prøve at slå den midlertidigt fra. Vær dog FORSIGTIG, da dette vil deaktivere beskyttelsen helt. Du må ikke gøre dette på din produktionsserver.
setenforce 0
Hvis du ikke længere har problemet med SELinux slået fra, er dette årsagen til problemet. For at løse det, skal du konfigurere SELinux i overensstemmelse hermed. Følgende konteksttyper vil være nødvendige :
httpd_sys_content_t
for filer, som du ønsker, at din server skal være i stand til at læsehttpd_sys_rw_content_t
for filer, som du vil have læse- og skriveadgang påhttpd_log_t
for logfilerhttpd_cache_t
til cache-mappen
Hvis du f.eks. vil tildele konteksttypen httpd_sys_content_t
til dit websteds rodmappe, skal du køre :semanage fcontext -a -t httpd_sys_content_t "/path/to/root(/.*)?"
restorecon -Rv /path/to/root
Hvis din fil er i en hjemmemappe, skal du også aktivere booleanen httpd_enable_homedirs
:
setsebool -P httpd_enable_homedirs 1
Under alle omstændigheder kan der være en række forskellige grunde til, at SELinux vil nægte adgang til en fil, afhængigt af dine politikker. Så du bliver nødt til at undersøge det. Her er en vejledning specifikt om konfigurering af SELinux til en webserver.
Hvis du bruger Symfony, og oplever denne fejl ved upload til en server, så kan det være, at app's cache ikke er blevet nulstillet, enten fordi app/cache
er blevet uploadet, eller at cache ikke er blevet slettet.
Du kan teste og rette dette ved at køre følgende konsolkommando:
cache:clear
Tilsyneladende kan denne fejl også opstå ved kald af zip->close()
, når nogle filer i zip-filen har ikke-ASCII-tegn i deres filnavn, såsom "é".
En mulig løsning er at indpakke filnavnet i utf8_decode()
, før målfilen oprettes.
Kredit til Fran Cano for at have identificeret og foreslået en løsning på dette problem
For at supplere det (virkelig gode) eksisterende svar
open_basedir
er en af dem, der kan give dig problemer, fordi den kan angives i en webserverkonfiguration. Mens dette er let at afhjælpe, hvis du kører din egen dedikerede server, er der nogle delte hosting-softwarepakker derude (som Plesk, cPanel osv.), der vil konfigurere et konfigurationsdirektiv på et per-domæne grundlag. Fordi softwaren opbygger konfigurationsfilen (dvs. httpd.conf
), kan du ikke ændre filen direkte, fordi hosting-softwaren bare vil overskrive den, når den genstarter.
Med Plesk tilbyder de et sted til at tilsidesætte den medfølgende httpd.conf
kaldet vhost.conf
. Kun serveradministratoren kan skrive denne fil. Konfigurationen for Apache ser nogenlunde sådan ud
<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>
Bed din serveradministrator om at konsultere manualen for den hosting- og webserversoftware, de bruger.
Det er vigtigt at bemærke, at det er meget forskelligt at udføre en fil via din webserver i forhold til en kommandolinje eller et cronjob. Den store forskel er, at din webserver har sin egen bruger og sine egne tilladelser. Af sikkerhedsmæssige årsager er denne bruger temmelig begrænset. Apache er f.eks. ofte apache
, www-data
eller httpd
(afhængigt af din server). Et cronjob eller en CLI-eksekvering har de tilladelser, som brugeren, der kører det, har (dvs. at hvis du kører et PHP-script som root, vil det blive eksekveret med root-tilladelser).
Mange gange vil folk løse et problem med tilladelser ved at gøre følgende (Linux-eksempel)
chmod 777 /path/to/file
Dette er ikke en smart idé, fordi filen eller mappen nu kan skrives i hele verden. Hvis du ejer serveren og er den eneste bruger, er det ikke så slemt, men hvis du er på et delt hostingmiljø, har du lige givet alle på din server adgang.
Det du skal gøre er at bestemme de(n) bruger(e), der har brug for adgang, og kun give dem adgang. Når du ved, hvilke brugere der har brug for adgang, skal du sikre dig, at
Den pågældende bruger ejer filen og eventuelt den overordnede mappe (især den overordnede mappe, hvis du vil skrive filer). I de fleste shared hosting-miljøer vil dette ikke være et problem, fordi din bruger bør eje alle filer under din rod. Et Linux-eksempel er vist nedenfor
chown apache:apache /path/to/file
Brugeren, og kun denne bruger, har adgang. I Linux vil en god praksis være chmod 600
(kun ejer kan læse og skrive) eller chmod 644
(ejer kan skrive, men alle kan læse)
Du kan [læse en mere uddybende diskussion om Linux/Unix-tilladelser og brugere her] (https://unix.stackexchange.com/questions/35711/giving-php-permission-to-write-to-files-and-folders)
En anden mulig årsag: Omdøbning og/eller flytning af filer i en teksteditor. Jeg gennemgik alle ovenstående trin uden held, indtil jeg slettede den fil, der blev ved med at give denne fejl, og oprettede en ny fil, hvilket løste problemet.