PHP - impossible d'ouvrir le flux : aucun fichier ou répertoire de ce type
P粉145543872
P粉145543872 2023-08-23 16:30:33
0
2
582
<p>Dans un script PHP, que vous appeliez <code>include()</code>, <code>require()</code>, <code>fopen()</code> ou ses classes dérivées, telles que <code> include_once</code>, <code>require_once</code>, ou encore <code>move_uploaded_file()</code>, vous rencontrerez souvent des erreurs ou des avertissements : ≪ /p> <blockquote> <p>Impossible d'ouvrir le flux : aucun fichier ou répertoire de ce type. </p> </blockquote> <p>Quel est le bon processus pour trouver rapidement la cause première d’un problème ? </p>
P粉145543872
P粉145543872

répondre à tous(2)
P粉362071992

Ajouté à la (très bonne) réponse existante

Logiciel d'hébergement partagé

open_basedir 可能会难倒您,因为它可以在 Web 服务器配置中指定。虽然如果您运行自己的专用服务器,这很容易解决,但有一些共享托管软件包(如 Plesk、cPanel 等)可以在每个域的基础上配置配置指令。由于该软件会构建配置文件(即 httpd.conf), vous ne pouvez donc pas modifier ce fichier directement car le logiciel d'hébergement l'écrasera simplement au redémarrage.

Avec Plesk, ils fournissent un emplacement pour couvrir ce qu'ils ont à offrir httpd.conf(称为 vhost.conf). Seuls les administrateurs du serveur peuvent écrire dans ce fichier. La configuration Apache ressemble à ceci

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

Demandez à votre administrateur de serveur de consulter les manuels des logiciels d'hébergement et de serveur Web qu'il utilise.

Autorisations de fichiers

Il est important de noter que l’exécution de fichiers via un serveur Web est très différente de l’exécution d’une ligne de commande ou d’une tâche cron. La plus grande différence est que votre serveur Web possède ses propres utilisateurs et autorisations. Cet utilisateur est fortement restreint pour des raisons de sécurité. Par exemple, Apache est généralement apachewww-datahttpd (selon votre serveur). Une tâche cron ou une exécution CLI a toutes les autorisations dont dispose l'utilisateur qui l'exécute (c'est-à-dire qu'un script PHP exécuté en tant que root s'exécutera avec les autorisations root).

Souvent, les gens résolvent les problèmes d'autorisation en procédant comme suit (exemple Linux)

chmod 777 /path/to/file

Ce n'est pas une bonne idée car le fichier ou le répertoire est désormais accessible en écriture par tout le monde. Si vous possédez le serveur et êtes le seul utilisateur, ce n'est pas grave, mais si vous êtes dans un environnement d'hébergement partagé, vous accordez l'accès à tout le monde sur le serveur.

Ce que vous devez faire est d'identifier les utilisateurs qui ont besoin d'un accès et de leur accorder l'accès uniquement. Une fois que vous savez quels utilisateurs ont besoin d'accéder, vous devez vous en assurer

  1. Cet utilisateur est propriétaire du fichier et possède probablement le répertoire parent (en particulier le répertoire parent si vous écrivez dans le fichier). Dans la plupart des environnements d'hébergement partagé, cela ne posera pas de problème puisque votre utilisateur doit être propriétaire de tous les fichiers du répertoire racine. Un exemple Linux est présenté ci-dessous

    chown apache:apache /path/to/file
  2. Cet utilisateur (et uniquement cet utilisateur) a accès. Sous Linux, une bonne pratique est chmod 600(只有所有者可以读写)或 chmod 644 (le propriétaire peut écrire, mais tout le monde peut lire)

Vous pouvez lire une discussion plus large sur les autorisations et les utilisateurs Linux/Unix ici

P粉268654873

Il existe de nombreuses raisons pour lesquelles vous pouvez rencontrer cette erreur, donc une bonne liste de contrôle de ce qu'il faut vérifier en premier peut être utile.

Supposons que nous résolvions la ligne suivante :

require "/path/to/file"


Liste de contrôle


1. Vérifiez le chemin du fichier pour les fautes de frappe

  • Inspection manuelle (en inspectant visuellement le chemin)
  • Ou déplacez l'appel de require*include* dans sa propre variable, faites-lui écho, copiez-le et essayez d'y accéder depuis le terminal :

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

    Puis, dans le terminal :

    cat <file path pasted>


2. Vérifiez si le chemin du fichier des considérations de chemin relatif et absolu est correct

Meilleures pratiques :

Pour rendre votre script robuste lors du déplacement de contenu tout en générant des chemins absolus au moment de l'exécution, vous avez 2 options :

    Utilisez
  1. constantes magiquesrequire __DIR__ 。 “/相对/路径/来自/当前/文件”__DIR__ pour renvoyer le répertoire du fichier actuel.
  2. Définissez vous-même une

    constante : SITE_ROOT

      Créez un fichier à la racine du répertoire du site par exemple
    • config.php
    • Écrivez

      dans config.php

      define('SITE_ROOT', __DIR__);
    • Dans chaque fichier auquel vous souhaitez référencer le dossier racine du site, incluez

      , puis utilisez la constante config.php,然后在任意位置使用 SITE_ROOT n'importe où : p>

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

Ces 2 pratiques rendent également votre application plus portable car elle ne repose pas sur les paramètres ini tels que les chemins d'inclusion.


3. Vérifiez vos chemins d'inclusion

Une autre façon d'inclure des fichiers, qui n'est ni relative ni purement absolue, consiste à s'appuyer sur le chemin d'inclusion. C'est souvent le cas des bibliothèques ou des frameworks tels que Zend Framework.

Une telle inclusion ressemblerait à ceci :

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

Dans ce cas, vous devez vous assurer que le dossier où se trouve "Zend" fait partie du chemin d'inclusion.

Vous pouvez vérifier le chemin d'inclusion à l'aide de la commande suivante :

echo get_include_path();

Vous pouvez y ajouter des dossiers en utilisant la commande suivante :

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


4. Vérifiez si votre serveur a accès au fichier

Pour résumer, l'utilisateur qui exécute le processus serveur (Apache ou PHP) peut ne pas avoir du tout l'autorisation de lire ou d'écrire le fichier.

Pour vérifier sous quel utilisateur le serveur s'exécute, vous pouvez utiliser posix_getpwuid :

$user = posix_getpwuid(posix_geteuid());

var_dump($user);

Pour retrouver les permissions d'un fichier, tapez la commande suivante dans le terminal :

ls -l <path/to/file>

Et consultez la notation d'autorisation


5. Vérifiez les paramètres PHP

Si aucune des méthodes ci-dessus ne fonctionne, le problème peut être que certains paramètres PHP l'empêchent d'accéder au fichier.

Trois paramètres peuvent être pertinents :

  1. open_basedir
    • Si ceci est défini, PHP ne pourra accéder à aucun fichier en dehors du répertoire spécifié (pas même via des liens symboliques).
    • Cependant, le comportement par défaut est de ne pas le définir, auquel cas il n'y a pas de limite
    • Peut être vérifié en appelant phpinfo()phpinfo()进行检查> 或使用 ini_get("open_basedir") ou en utilisant ini_get("open_basedir")
    • Vous pouvez modifier les paramètres en éditant le fichier php.ini ou le fichier httpd.conf
  2. Mode sans échec
    • Cette fonctionnalité peut être restreinte si elle est activée. Cependant, cela a été supprimé dans PHP 5.4. Si vous utilisez toujours une version prenant en charge le mode sans échec, veuillez passer à une version toujours prise en charge de PHP.
  3. allow_url_fopen etallow_url_include
    • Cela ne fonctionne que lors de l'inclusion ou de l'ouverture de fichiers via un processus réseau (par exemple http://), et non lorsque vous essayez d'inclure des fichiers sur votre système de fichiers local
    • Peut être défini à l'aide de ini_get("allow_url_include") 检查并使用 ini_set("allow_url_include", "1") Paramètres


Situations extrêmes

Si aucune des méthodes ci-dessus ne permet de diagnostiquer le problème, certaines des situations particulières suivantes peuvent se produire :


1. Inclusion des bibliothèques qui dépendent des chemins d'inclusion

Vous pouvez inclure une bibliothèque, telle que le framework Zend, en utilisant un chemin relatif ou absolu. Par exemple :

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

Mais vous rencontrerez toujours le même type d’erreurs.

Cela se produit parce que le fichier que vous incluez (avec succès) lui-même a une instruction d'inclusion provenant d'un autre fichier, et la deuxième instruction d'inclusion suppose que vous avez ajouté le chemin d'accès à la bibliothèque au chemin d'inclusion.

Par exemple, le fichier du framework Zend mentionné précédemment peut contenir les éléments suivants :

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

Ni inclus via un chemin relatif ni inclus via un chemin absolu. On suppose que le répertoire du framework Zend a été ajouté au chemin d'inclusion.

Dans ce cas, la seule solution pratique est d'ajouter le répertoire au chemin d'inclusion.


2. SELinux

Si vous utilisez Linux à sécurité renforcée, cela peut être la cause du problème, car l'accès au fichier depuis le serveur est refusé.

Pour vérifier si SELinux est activé sur votre système, exécutez la commande sestatus dans le terminal. Si cette commande n'existe pas, SELinux n'existe pas sur votre système. S'il existe, il devrait vous indiquer s'il est appliqué.

Pour vérifier si la politique SELinux est à l'origine du problème, vous pouvez essayer de la désactiver temporairement. Mais soyez prudent car cela désactivera complètement la protection. Ne faites pas cela sur un serveur de production.

setenforce 0

Si vous n'avez plus de problèmes après avoir désactivé SELinux, alors c'est la cause première.

Pour résoudre ce problème, vous devez configurer SELinux en conséquence.

Les types de contexte suivants sont requis :

  • httpd_sys_content_t pour les fichiers que vous souhaitez que le serveur puisse lire
  • httpd_sys_rw_content_t pour les fichiers auxquels vous souhaitez accéder en lecture et en écriture
  • httpd_log_t pour les fichiers journaux
  • httpd_cache_t pour le répertoire de cache

Par exemple, pour attribuer le type de contexte httpd_sys_content_t à la racine de votre site Web, exécutez :

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

Si votre fichier se trouve dans votre répertoire personnel, vous devrez également ouvrir httpd_enable_homedirs Booléen :

setsebool -P httpd_enable_homedirs 1

Quoi qu'il en soit, il peut y avoir plusieurs raisons pour lesquelles SELinux refuse l'accès à un fichier, en fonction de votre stratégie. Vous devez donc enquêter là-dessus. Voici un tutoriel spécifiquement pour configurer SELinux pour votre serveur Web.


3. Symphonie

Si vous utilisez Symfony et que vous rencontrez cette erreur lors du téléchargement sur le serveur, il est possible que le cache de votre application n'ait pas été réinitialisé depuis le téléchargement de app/cache, ou que le cache n'ait pas encore été vidé.

Vous pouvez tester et résoudre ce problème en exécutant la commande de console suivante :

cache:clear


4. Caractères non ACSII dans les fichiers Zip

Apparemment, cette erreur se produit également lors de l'appel de zip->close() lorsque certains fichiers du zip contiennent des caractères non-ASCII (par exemple "é") dans leurs noms de fichiers.

Une solution possible consiste à envelopper le nom de fichier dans utf8_decode() avant de créer le fichier cible.

Merci à Fran Cano d'avoir identifié ce problème et proposé une solution

Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal