PHP – Kan streamen niet openen: geen bestand of directory

In PHP-scripts, of het nu gaat om het toevoegen van include(), require(), fopen()of hun derivaten zoals include_once, require_once, of zelfs, move_uploaded_file(), men werkt vaak in een fout of waarschuwing:

Kan streamen niet openen: geen bestand of map.

Wat is een goed proces om snel de oorzaak van het probleem te vinden?


Antwoord 1, Autoriteit 100%

Er zijn veel redenen waarom men deze fout kan tegenkomen en dus een goede checklist is van wat u moet controleren, het eerst aanzienlijk helpt.

Laten we overwegen dat we de volgende regel probleemoplossing oplossen:

require "/path/to/file"

Checklist

1. Controleer het bestandspad voor typefouten

  • Controleer ofwel handmatig (door het pad visueel te controleren)
  • OF MOEP WERKIG ALS DOOR require*OF include*NAAR ZIJN EIGEN VARIABEL, ECHO IT, kopieer het en probeer het van een terminal te openen:

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

    Dan, in een terminal:

    cat <file path pasted>
    

2. Controleer of het bestandspad correct is met betrekking tot relatieve vs absolute padoverwegingen

  • Als het wordt gestart door een voorwaartse slash “/”, verwijst dan niet naar de root van de map van uw website (de documenttocht), maar naar de root van uw server.
    • Bijvoorbeeld, de map van uw website is mogelijk /users/tony/htdocs
  • als het niet begint met een schuine streep, dan vertrouwt het op het include-pad (zie hieronder) of is het pad relatief. Als het relatief is, berekent PHP relatief ten opzichte van het pad van de huidige werkmap.
    • dus niet relatief ten opzichte van het pad van de root van je website, of het bestand waarin je typt
    • gebruik daarom altijd absolute bestandspaden

Beste praktijken:

Om je script robuust te maken voor het geval je dingen verplaatst, terwijl je tijdens runtime nog steeds een absoluut pad genereert, heb je 2 opties:

  1. gebruik require __DIR__ . "/relative/path/from/current/file". De __DIR__magische constantegeeft de directory van het huidige bestand.
  2. definieer zelf een SITE_ROOTconstante :

    • maak in de hoofdmap van de directory van uw website een bestand aan, b.v. config.php
    • in config.php, schrijf

      define('SITE_ROOT', __DIR__);
      
    • in elk bestand waarin u naar de hoofdmap van de site wilt verwijzen, neemt u config.phpop en gebruikt u vervolgens de constante SITE_ROOTwaar u maar wilt:

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

Deze twee werkwijzen maken uw toepassing ook draagbaarder omdat deze niet afhankelijk is van ini-instellingen zoals het include-pad.

3. Controleer je include-pad

Een andere manier om bestanden op te nemen, noch relatief, noch puur absoluut, is te vertrouwen op het voeg pad toe. Dit is vaak het geval voor bibliotheken of frameworks zoals het Zend-framework.

Een dergelijke opname ziet er als volgt uit:

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

In dat geval moet je ervoor zorgen dat de map waarin “Zend” staat, deel uitmaakt van het include-pad.

Je kunt het include-pad controleren met :

echo get_include_path();

Je kunt er een map aan toevoegen met :

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

4. Controleer of uw server toegang heeft tot dat bestand

Het kan zijn dat de gebruiker die het serverproces uitvoert (Apache of PHP) gewoonweg geen toestemming heeft om van dat bestand te lezen of naar dat bestand te schrijven.

Om te controleren onder welke gebruiker de server draait, kun je posix_getpwuid:

$user = posix_getpwuid(posix_geteuid());
var_dump($user);

Om de machtigingen voor het bestand te achterhalen, typt u de volgende opdracht in de terminal:

ls -l <path/to/file>

en kijk naar symbolische notatie voor toestemming

5. Controleer de PHP-instellingen

Als geen van bovenstaande werkt, is het probleem waarschijnlijk dat sommige PHP-instellingen het toegang tot dat bestand verbieden.

Drie instellingen kunnen relevant zijn:

  1. open_basedir
    • Als dit is ingesteld, heeft PHP geen toegang tot bestanden buiten de opgegeven map (zelfs niet via een symbolische link).
    • Het standaardgedrag is echter dat het niet wordt ingesteld, in welk geval er geen beperking is
    • Dit kan worden gecontroleerd door phpinfo()of door ini_get("open_basedir")
    • . te gebruiken

    • U kunt de instelling wijzigen door uw php.ini-bestand of uw httpd.conf-bestand te bewerken
  2. veilige modus
    • als dit is ingeschakeld, kunnen er beperkingen van toepassing zijn. Dit is echter verwijderd in PHP 5.4. Als u nog steeds een versie gebruikt die de veilige modus ondersteunt, moet u upgraden naar een PHP-versie die nog steeds wordt ondersteund.
  3. allow_url_fopen en allow_url_include
    • dit is alleen van toepassing op het opnemen of openen van bestanden via een netwerkproces zoals http://, niet wanneer u probeert bestanden op het lokale bestandssysteem op te nemen
    • dit kan worden gecontroleerd met ini_get("allow_url_include")en ingesteld met ini_set("allow_url_include", "1")

Hoekkasten

Als geen van de bovenstaande opties is ingeschakeld om het probleem te diagnosticeren, volgen hier enkele speciale situaties die kunnen gebeuren:

1. De opname van een bibliotheek die vertrouwt op het include-pad

Het kan voorkomen dat je een bibliotheek opneemt, bijvoorbeeld het Zend-framework, met een relatief of absoluut pad. Bijvoorbeeld:

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

Maar dan krijg je nog steeds dezelfde soort foutmelding.

Dit kan gebeuren omdat het bestand dat u (met succes) heeft opgenomen, zelf een include-instructie voor een ander bestand heeft, en die tweede include-instructie veronderstelt dat u het pad van die bibliotheek aan het include-pad hebt toegevoegd.

Het eerder genoemde Zend-frameworkbestand kan bijvoorbeeld het volgende bevatten:

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

wat noch een opname door relatief pad, noch door absoluut pad is. Er wordt aangenomen dat de Zend-frameworkdirectory is toegevoegd aan het include-pad.

In zo’n geval is de enige praktische oplossing om de map toe te voegen aan je include-pad.

2. SELinux

Als je Security-Enhanced Linux gebruikt, kan dit de oorzaak van het probleem zijn, door de toegang tot het bestand van de server te weigeren.

Om te controleren of SELinux is ingeschakeldop je systeem, voer je het sestatuscommando uit in een terminal. Als het commando niet bestaat, dan staat SELinux niet op je systeem. Als het bestaat, zou het je moeten vertellen of het wordt afgedwongen of niet.

Om te controleren of het SELinux-beleid de reden isvoor het probleem, kun je proberen het tijdelijk uit te schakelen. Wees echter VOORZICHTIG, aangezien dit de bescherming volledig zal uitschakelen. Doe dit niet op uw productieserver.

setenforce 0

Als je het probleem niet langer hebt met SELinux uitgeschakeld, dan is dit de hoofdoorzaak.

Om het op te lossen, moet je SELinux dienovereenkomstig configureren.

De volgende contexttypen zijn nodig:

  • httpd_sys_content_tvoor bestanden waarvan u wilt dat uw server deze kan lezen
  • httpd_sys_rw_content_tvoor bestanden waarvoor u lees- en schrijftoegang wilt hebben
  • httpd_log_tvoor logbestanden
  • httpd_cache_tvoor de cachemap

Als u bijvoorbeeld het contexttype httpd_sys_content_twilt toewijzen aan de hoofdmap van uw website, voert u :

uit

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

Als uw bestand zich in een homedirectory bevindt, moet u ook de httpd_enable_homedirsboolean :

inschakelen

setsebool -P httpd_enable_homedirs 1

In ieder geval kunnen er verschillende redenen zijn waarom SELinux de toegang tot een bestand zou weigeren, afhankelijk van je beleid. Dat zul je dus moeten navragen. Hieris een tutorial specifiek over het configureren van SELinux voor een webserver.

3. Symfonie

Als u Symfony gebruikt en deze fout ervaart bij het uploaden naar een server, kan het zijn dat de cache van de app niet opnieuw is ingesteld, ofwel omdat app/cacheis geüpload, of die cache is niet gewist.

Je kunt dit testen en oplossen door de volgende consoleopdracht uit te voeren:

cache:clear

4. Niet-ACSII-tekens in zip-bestand

Blijkbaar kan deze fout ook optreden bij het aanroepen van zip->close()wanneer sommige bestanden in de zip niet-ASCII-tekens in hun bestandsnaam hebben, zoals “é”.

Een mogelijke oplossing is om de bestandsnaam in utf8_decode()te plaatsen voordat u het doelbestand maakt.

Met dank aan Fran Canovoor het identificeren en voorstellen van een oplossing voor dit probleem


Antwoord 2, autoriteit 6%

Om toe te voegen aan het (heel goede) bestaande antwoord

Gedeelde hostingsoftware

open_basediris er een die je kan verbazen omdat het kan worden gespecificeerd in een webserverconfiguratie. Hoewel dit eenvoudig kan worden verholpen als u uw eigen dedicated server gebruikt, zijn er enkele shared hosting-softwarepakketten (zoals Plesk, cPanel, enz.) Die een configuratierichtlijn per domein configureren. Omdat de software het configuratiebestand bouwt (d.w.z. httpd.conf), kunt u dat bestand niet rechtstreeks wijzigen omdat de hostingsoftware het gewoon zal overschrijven wanneer het opnieuw wordt opgestart.

Met Plesk bieden ze een plaats om de verstrekte httpd.confgenaamd vhost.confte overschrijven. Alleen de serverbeheerder kan dit bestand schrijven. De configuratie voor Apache ziet er ongeveer zo uit

<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>

Laat uw serverbeheerder de handleiding raadplegen van de hosting- en webserversoftware die zij gebruiken.

Bestandsmachtigingen

Het is belangrijk op te merken dat het uitvoeren van een bestand via uw webserver heel anders is dan het uitvoeren van een opdrachtregel of cron-taak. Het grote verschil is dat uw webserver zijn eigen gebruiker en permissies heeft. Om veiligheidsredenen is die gebruiker behoorlijk beperkt. Apache is bijvoorbeeld vaak apache, www-dataof httpd(afhankelijk van je server). Een cron-taak of CLI-uitvoering heeft alle machtigingen die de gebruiker die deze uitvoert heeft (d.w.z. het uitvoeren van een PHP-script als root wordt uitgevoerd met de machtigingen van root).

Vaak lossen mensen een machtigingsprobleem op door het volgende te doen (Linux-voorbeeld)

chmod 777 /path/to/file

Dit is geen slim idee, omdat het bestand of de map nu wereldwijd beschrijfbaar is. Als je de eigenaar bent van de server en de enige gebruiker bent, is dit niet zo’n groot probleem, maar als je op een gedeelde hostingomgeving zit, heb je zojuist iedereen op je server toegang gegeven.

Wat u moet doen, is de gebruiker(s) bepalen die toegang nodig hebben en alleen die gebruikers toegang geven. Zodra u weet welke gebruikers toegang nodig hebben, moet u ervoor zorgen dat

  1. Die gebruiker is eigenaar van het bestand en mogelijk de bovenliggende map(vooral de bovenliggende map als je bestanden wilt schrijven). In de meeste shared hosting-omgevingen zal dit geen probleem zijn, omdat je gebruiker alle bestanden onder je root zou moeten bezitten. Hieronder ziet u een Linux-voorbeeld

    chown apache:apache /path/to/file
    
  2. De gebruiker en alleen die gebruiker heeft toegang. In Linux zou een goede praktijk zijn chmod 600(alleen eigenaar kan lezen en schrijven) of chmod 644(eigenaar kan schrijven, maar iedereen kan lezen)

u kunt Lees een uitgebreidere discussie over Linux / UNIX-machtigingen en gebruikers hier


Antwoord 3, Autoriteit 3%

  1. Kijk naar de exact fout

Mijn code werkte prima op alle machines, maar alleen aan deze begon met het geven van een probleem (dat vroeger werkte, denk ik dat ik denk). Gebruikte Echo “Document_root” pad naar debug en keek ook goed op de fout, vond dit

WAARSCHUWING:
opnemen (D: /myprojects/testproject//functions/connections.php ):
Kan stream niet openen:

U kunt eenvoudig zien waar de problemen zijn. De problemen zijn // vóór functies

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

Verwijder dus gewoon de lading / van het opnemen en het zou goed moeten werken. Wat interessant is, is dit gedrag anders op verschillende versies. Ik voer dezelfde code op laptop, MacBook Pro en deze pc, alles werkte allen tot. Ik hoop dat dit iemand helpt.

  1. Kopiëren langs de bestandslocatie in de browser om ervoor te zorgen dat het bestand bestaat. Soms worden bestanden onverwachts verwijderd (gebeurd met mij) en het was ook het probleem in mijn geval.

Antwoord 4

Samba-aandelen

Als u een Linux-testserver hebt en u werkt vanuit een Windows-client, interfereert het SAMBA-aandeel met de opdracht CHMOD . Dus, zelfs als u gebruikt:

chmod -R 777 myfolder

aan de Linux-kant is het heel goed mogelijk dat de Unix Group\www-data nog steeds geen schrijftoegang heeft. Een werkende oplossing als uw share zo is ingesteld dat Windows-beheerders worden toegewezen aan root: Open vanuit Windows de machtigingen, schakel Overerving uit voor uw map met kopiëren en verleen vervolgens volledige toegang voor www-data.


Antwoord 5

Script toevoegen met queryparameters

Dat was mijn geval. Het linkt eigenlijk naar vraag #4485874, maar ik ga het hier binnenkort uitleggen.
Wanneer u path/to/script.php?parameter=valueprobeert te eisen, zoekt PHP naar het bestand met de naam script.php?parameter=value, omdat u in UNIX paden zoals deze.
Als je echt wat gegevens moet doorgeven aan het opgenomen script, declareer het dan als $variable=...of $GLOBALS[]=...of op een andere manier leuk vinden.


Antwoord 6

PHP – Kan stream niet openen: geen bestand of map in mac

Ik zal bijvoorbeeld een foto uploaden. Maar ik krijg deze fout. Het eerste wat ik doe, klik met de rechtermuisknop op de afbeelding en krijg informatie.

$thePathOfMyPicture = "/Users/misstugba/Desktop/";
gebruik met functie

if(move_uploaded_file($_FILES["file"]["tmp_name"],$thePathOfMyPicture.$_FILES["file"]["name"])){
echo "image uploaded successfully";

}


Antwoord 7

De volgende PHP-instellingen in php.inikunnen, indien ingesteld op een niet-bestaande directory, ook verhogen

PHP-waarschuwing: onbekend: kan stream niet openen: toestemming geweigerd in
Onbekend online 0

sys_temp_dir
upload_tmp_dir
session.save_path

Antwoord 8

Bij mij kreeg ik deze foutmelding omdat ik een bestand probeerde te lezen waarvoor HTTP-verificatie was vereist, met een gebruikersnaam en wachtwoord. Hoop dat het anderen helpt. Misschien een andere hoekzaak.

Bewerken

U kunt controleren of dit type authenticatie aanwezig is door de headers te inspecteren:

$file_headers = get_headers($url);
if (!$file_headers) echo 'File headers missing';
else if (strpos($file_headers[0], '401 Unauthorized') > -1) echo '401 Unauthorized';

Other episodes