Negli script PHP, sia che si chiami include()
, require()
, fopen()
, o i loro derivati come include_once
, require_once
, o anche, move_uploaded_file()
, ci si imbatte spesso in un errore o avviso:
Impossibile aprire il flusso: nessun file o directory di questo tipo.
Qual è un buon processo per trovare rapidamente la causa del problema?
Ci sono molte ragioni per cui si potrebbe incorrere in questo errore e quindi una buona lista di controllo su cosa controllare prima aiuta notevolmente. Consideriamo che stiamo risolvendo il problema della seguente linea:
require "/path/to/file"
br>
require*
o include*
in una propria variabile, echo, copiarla e provare ad accedervi da un terminale:
$path = "/path/to/file";
echo "Percorso: $path";
require "$path";
Poi, in un terminale
cat /users/tony/htdocs
.require __DIR__ . "/relative/path/from/current/file"
. La costante magica __DIR__
restituisce la directory del file corrente.SITE_ROOT
:config.php
.config.php
, scrivi
define('SITE_ROOT', DIR);config.php
, e poi usa la costante SITE_ROOT
dove vuoi:
require_once DIR."/../config.php";
...
require_once SITE_ROOT."/other/file.php";
Queste 2 pratiche rendono anche la vostra applicazione più portabile perché non si basa su impostazioni ini come il percorso include.
br>Un altro modo per includere i file, né relativamente né puramente in assoluto, è quello di fare affidamento sul include path. Questo è spesso il caso di librerie o framework come il framework Zend. Una tale inclusione sarà simile a questa :
include "Zend/Mail/Protocol/Imap.php"
In questo caso, vorrai assicurarti che la cartella dove si trova "Zend" faccia parte del percorso di inclusione. Puoi controllare il percorso include con :
echo get_include_path();
Puoi aggiungere una cartella ad esso con :
set_include_path(get_include_path().":"."/path/to/new/folder");
br>
Potrebbe essere che tutto sommato, l'utente che esegue il processo del server (Apache o PHP) semplicemente non ha il permesso di leggere o scrivere su quel file. Per controllare sotto quale utente sta girando il server puoi usare posix_getpwuid :
$user = posix_getpwuid(posix_geteuid());
var_dump($user);
Per scoprire i permessi sul file, digitate il seguente comando nel terminale:
ls -l <path/to/file>
e guardare [notazione simbolica dei permessi][notazione dei permessi] br>
Se nessuna delle precedenti ha funzionato, allora il problema è probabilmente che alcune impostazioni PHP vietano l'accesso a quel file. Tre impostazioni potrebbero essere rilevanti:
phpinfo()
o usando ini_get("open_basedir")
ini_get("allow_url_include")
e impostato con ini_set("allow_url_include", "1")
br>Se nessuno dei precedenti ha permesso di diagnosticare il problema, ecco alcune situazioni speciali che potrebbero verificarsi:
Può succedere che tu includa una libreria, per esempio il framework Zend, usando un percorso relativo o assoluto. Per esempio :
require "/usr/share/php/libzend-framework-php/Zend/Mail/Protocol/Imap.php"
Ma poi si ottiene ancora lo stesso tipo di errore. Questo potrebbe accadere perché il file che hai incluso (con successo) ha a sua volta una dichiarazione di include per un altro file, e questa seconda dichiarazione di include presuppone che tu abbia aggiunto il percorso di quella libreria al percorso di include. Per esempio, il file Zend framework menzionato prima potrebbe avere il seguente include :
include "Zend/Mail/Protocol/Exception.php"
che non è né un'inclusione per percorso relativo, né per percorso assoluto. Si suppone che la directory di Zend framework sia stata aggiunta al percorso di include. In tal caso, l'unica soluzione pratica è aggiungere la directory al percorso di include. br>
Se state eseguendo Security-Enhanced Linux, allora potrebbe essere la ragione del problema, negando l'accesso al file dal server.
Per controllare se SELinux è abilitato sul vostro sistema, eseguite il comando sestatus
in un terminale. Se il comando non esiste, allora SELinux non è sul vostro sistema. Se esiste, allora dovrebbe dirvi se è applicato o meno.
Per controllare se le politiche di SELinux sono la ragione del problema, potete provare a spegnerlo temporaneamente. Tuttavia siate prudenti, poiché questo disabiliterà completamente la protezione. Non fatelo sul vostro server di produzione.
setenforce 0
Se non avete più il problema con SELinux disattivato, allora questa è la causa principale. Per risolverlo, dovrete configurare SELinux di conseguenza. I seguenti tipi di contesto saranno necessari:
httpd_sys_content_t
per i file che volete che il vostro server possa leggerehttpd_sys_rw_content_t
per i file che volete leggere e scriverehttpd_log_t
per i file di loghttpd_cache_t
per la directory della cache
Per esempio, per assegnare il tipo di contesto httpd_sys_content_t
alla directory principale del tuo sito web, esegui :semanage fcontext -a -t httpd_sys_content_t "/path/to/root(/.*)?"
restorecon -Rv /path/to/root
Se il tuo file è in una directory home, dovrai anche attivare la booleana httpd_enable_homedirs
:
setsebool -P httpd_enable_homedirs 1
In ogni caso, ci potrebbero essere una varietà di ragioni per cui SELinux negherebbe l'accesso ad un file, a seconda delle vostre politiche. Quindi dovrete indagare su questo. Qui è un tutorial specifico sulla configurazione di SELinux per un server web. br>
Se stai usando Symfony, e stai riscontrando questo errore durante il caricamento su un server, allora può essere che la cache dell'app non sia stata resettata, o perché app/cache
è stata caricata, o perché la cache non è stata cancellata.
Puoi testare e risolvere questo problema eseguendo il seguente comando da console:
cache:clear
br>
Apparentemente, questo errore può accadere anche quando si chiama zip->close()
quando alcuni file all'interno dello zip hanno caratteri non-ASCII nel loro nome file, come "é".
Una potenziale soluzione è quella di avvolgere il nome del file in utf8_decode()
prima di creare il file di destinazione.
Crediti a Fran Cano per aver identificato e suggerito una soluzione a questo problema
Per aggiungere alla risposta esistente (davvero buona)
open_basedir
è una cosa che ti può lasciare perplesso perché può essere specificata in una configurazione del server web. Mentre questo è facilmente rimediato se si esegue il proprio server dedicato, ci sono alcuni pacchetti software di hosting condiviso là fuori (come Plesk, cPanel, ecc) che configureranno una direttiva di configurazione su una base per dominio. Poiché il software costruisce il file di configurazione (cioè httpd.conf
) non puoi cambiare quel file direttamente perché il software di hosting semplicemente lo sovrascriverà quando si riavvia.
Con Plesk, forniscono un posto per sovrascrivere il fornito httpd.conf
chiamato vhost.conf
. Solo l'amministratore del server può scrivere questo file. La configurazione per Apache assomiglia a questa
<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>
Chiedi all'amministratore del tuo server di consultare il manuale del software di hosting e del server web che usa.
E' importante notare che l'esecuzione di un file attraverso il vostro server web è molto diverso dall'esecuzione di una linea di comando o di un lavoro cron. La grande differenza è che il tuo server web ha il suo utente e i suoi permessi. Per ragioni di sicurezza quell'utente è piuttosto limitato. Apache, per esempio, è spesso apache
, www-data
o httpd
(a seconda del tuo server). Un cron job o un'esecuzione CLI ha tutti i permessi che l'utente che lo esegue ha (cioè l'esecuzione di uno script PHP come root verrà eseguito con i permessi di root).
Molte volte le persone risolvono un problema di permessi facendo quanto segue (esempio Linux)
chmod 777 /path/to/file
Questa non è un'idea intelligente, perché il file o la directory è ora scrivibile a livello mondiale. Se possedete il server e siete l'unico utente allora questo non è un grosso problema, ma se siete su un ambiente di hosting condiviso avete appena dato l'accesso a chiunque sul vostro server.
Quello che dovete fare è determinare l'utente (o gli utenti) che hanno bisogno di accesso e dare l'accesso solo a loro. Una volta che si sa quali utenti hanno bisogno di accesso si vuole fare in modo che
Quell'utente possiede il file e possibilmente la directory madre (specialmente la directory madre se volete scrivere file). Nella maggior parte degli ambienti di hosting condiviso questo non sarà un problema, perché il vostro utente dovrebbe possedere tutti i file sotto la vostra root. Un esempio di Linux è mostrato qui sotto
chown apache:apache /path/to/file
L'utente, e solo quell'utente, ha accesso. In Linux, una buona pratica sarebbe chmod 600
(solo il proprietario può leggere e scrivere) o chmod 644
(il proprietario può scrivere ma tutti possono leggere)
Potete leggere una discussione più estesa sui permessi e gli utenti Linux/Unix qui
Un'altra possibile causa: Rinominare e/o spostare i file in un editor di testo. Ho seguito tutti i passi precedenti senza successo fino a quando ho cancellato il file che continuava a dare questo errore e ne ho creato uno nuovo, che ha risolto il problema.