Em scripts PHP, seja chamando include()
, require()
, fopen()
, ou suas derivadas como include_once
, require_once
, ou até mesmo, move_uploaded_file()
, muitas vezes se esbarra em um erro ou aviso:
Failed to open stream : Nenhum ficheiro ou directório deste tipo.
O que é um bom processo para encontrar rapidamente a causa raiz do problema?
Há muitas razões pelas quais se pode deparar com este erro e, portanto, uma boa lista de verificação do que se deve verificar primeiro ajuda consideravelmente. Let's consideram que estamos resolvendo problemas na seguinte linha:
require "/path/to/file"
require*
ou include*
para sua própria variável, fazer eco, copiá-lo e tentar acessá-lo a partir de um terminal:
$caminho = "/caminho/para/arquivo";
echo "Path : $caminho";
requer "$caminho";;
Depois, em um terminal:
cat require __DIR__ . "/relative/path/from/current/file"
. A constante mágica __DIR__
retorna o diretório do arquivo atual.SITE_ROOT
:config.php
.config.php
, escreva
define('SITE_ROOT', DIR);config.php
, e então utilize a constante SITE_ROOT
onde você quiser :
require_once DIR."/.../config.php";
...
require_once SITE_ROOT."/other/file.php";
Estas 2 práticas também tornam a sua aplicação mais portátil porque não depende de configurações ini como o caminho de inclusão.
Outra forma de incluir arquivos, nem relativa nem puramente absoluta, é confiar no [incluir caminho][include path][includepath-docs]. Este é frequentemente o caso de bibliotecas ou frameworks como o framework Zend. Tal inclusão será parecida com isto :
include "Zend/Mail/Protocol/Imap.php"
Nesse caso, você vai querer ter certeza de que a pasta onde "Zend" é, faz parte do caminho de inclusão. Você pode verificar o caminho de inclusão com :
echo get_include_path();
Você pode adicionar uma pasta a ele com :
set_include_path(get_include_path().":"."/path/to/new/folder");
Pode ser que todos juntos, o usuário executando o processo do servidor (Apache ou PHP) simplesmente não'não tenha permissão para ler ou escrever naquele arquivo. Para verificar em que usuário o servidor está rodando você pode usar posix_getpwuid :
$user = posix_getpwuid(posix_geteuid());
var_dump($user);
Para saber as permissões no arquivo, digite o seguinte comando no terminal:
ls -l <path/to/file>
e olha para [notação simbólica de permissão] [notação de permissão].
Se nenhuma das opções acima funcionou, então a questão provavelmente é que algumas configurações do PHP proíbem o acesso a esse arquivo. Três configurações podem ser relevantes:
phpinfo()
][phpinfo-docs] ou utilizando ini_get("open_basedir")
ini_get("allow_url_include")
e definido com ini_set("allow_url_include", "1")
Se nenhuma das situações acima mencionadas permitir o diagnóstico do problema, aqui estão algumas situações especiais que podem acontecer :
Pode acontecer que você inclua uma biblioteca, por exemplo, a estrutura Zend, usando um caminho relativo ou absoluto. Por exemplo :
require "/usr/share/php/libzend-framework-php/Zend/Mail/Protocol/Imap.php"
Mas depois continuas a ter o mesmo tipo de erro. Isso pode acontecer porque o arquivo que você incluiu (com sucesso), tem uma declaração de inclusão para outro arquivo, e essa segunda declaração de inclusão assume que você adicionou o caminho dessa biblioteca ao caminho de inclusão. Por exemplo, o arquivo framework Zend mencionado anteriormente poderia ter o seguinte include :
include "Zend/Mail/Protocol/Exception.php"
que não é uma inclusão por caminho relativo, nem por caminho absoluto. É assumindo que o diretório estrutural Zend foi adicionado ao caminho da inclusão.
Nesse caso, a única solução prática é adicionar o diretório ao seu caminho de inclusão.
Se você está rodando o Security-Enhanced Linux, então pode ser a razão do problema, negando o acesso ao arquivo a partir do servidor.
Para verificar se o SELinux está habilitado no seu sistema, execute o comando sestatus
em um terminal. Se o comando não existir, então o SELinux não está no seu sistema. Se ele existe, então ele deve dizer-lhe se ele é ou não aplicado.
**Para verificar se as políticas do SELinux são a razão*** do problema, você pode tentar desligá-lo temporariamente. No entanto seja CARREGADO, já que isso irá desabilitar totalmente a proteção. Não faça isso no seu servidor de produção.
setenforce 0
Se você não tem mais o problema com o SELinux desligado, então esta é a causa raiz. Para o resolver, você terá que configurar o SELinux de acordo. Os seguintes tipos de contexto serão necessários :
para o diretório do cache Por exemplo, para atribuir o tipo de contexto
httpd_sys_content_t` ao diretório raiz do seu site, execute :semanage fcontext -a -t httpd_sys_content_t "/path/to/root(/.*)?"
restorecon -Rv /path/to/root
Se seu arquivo estiver em um diretório home, você também precisará ligar o booleano httpd_enable_homedirs
:
setsebool -P httpd_enable_homedirs 1
Em qualquer caso, pode haver uma variedade de razões pelas quais a SELinux negaria o acesso a um arquivo, dependendo das suas políticas. Portanto, você precisará averiguar isso. Aqui é um tutorial especificamente sobre a configuração do SELinux para um servidor web.
Se você está usando o Symfony, e experimentando esse erro ao fazer upload para um servidor, então pode ser que o cache do app's tenha sido reinicializado, ou porque app/cache
foi feito upload, ou que o cache tenha sido't sido limpo.
Você pode testar e corrigir isso executando o seguinte comando de console:
cache:clear
Aparentemente, este erro pode acontecer também ao chamar zip->close()
quando alguns arquivos dentro do zip têm caracteres não-ASCII em seu nome de arquivo, como "é".
Uma solução potencial é envolver o nome do arquivo em utf8_decode()
antes de criar o arquivo de destino.
Créditos para Fran Cano por identificar e sugerir uma solução para este problema.
https://secure.php.net/manual/en/ini.core.php#ini.include-path
Para adicionar à resposta (realmente boa) existente
O "openen_basedir" é aquele que pode atrapalhá-lo porque pode ser especificado na configuração de um servidor web. Embora isso seja facilmente corrigido se você rodar seu próprio servidor dedicado, há alguns pacotes de software de hospedagem compartilhada por aí (como Plesk, cPanel, etc) que irão configurar uma diretiva de configuração por domínio. Como o software constrói o arquivo de configuração (i.e. httpd.conf
) você não pode alterar esse arquivo diretamente porque o software de hospedagem irá apenas sobrescrevê-lo quando ele for reiniciado.
Com Plesk, eles fornecem um lugar para substituir o httpd.conf
fornecido chamado vhost.conf
. Apenas o administrador do servidor pode escrever este ficheiro. A configuração para o Apache é algo parecido com isto
<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>
Peça ao administrador do seu servidor para consultar o manual do software de hospedagem e do servidor web que eles utilizam.
É importante notar que executar um arquivo através do seu servidor web é muito diferente de uma linha de comando ou execução de um cron job. A grande diferença é que o seu servidor web tem o seu próprio usuário e permissões. Por razões de segurança, esse usuário é bastante restrito. O Apache, por exemplo, é frequentemente apache
, www-data
ou httpd
(dependendo do seu servidor). Um cron job ou execução CLI tem quaisquer permissões que o usuário que o executa (ou seja, rodar um script PHP como root irá executar com permissões de root).
Muitas vezes as pessoas vão resolver um problema de permissões fazendo o seguinte (exemplo Linux)
chmod 777 /path/to/file
Esta não é uma idéia inteligente, porque o arquivo ou diretório agora pode ser escrito no mundo inteiro. Se você é dono do servidor e é o único usuário, então isto é'não é tão grande coisa, mas se você'está em um ambiente de hospedagem compartilhado você'acabou de dar acesso a todos no seu servidor.
O que você precisa fazer é determinar o(s) usuário(s) que precisam de acesso e dar acesso somente àqueles que precisam. Quando você souber quais usuários precisam de acesso você'vai querer ter certeza de que
Esse usuário é dono do arquivo e possivelmente do diretório pai (especialmente do diretório pai, se você quiser escrever arquivos). Na maioria dos ambientes de hospedagem compartilhada isso ganhou't é um problema, porque seu usuário deve ser dono de todos os arquivos abaixo da sua raiz. Um exemplo de Linux é mostrado abaixo
chown apache:apache /caminho/para/file
O usuário, e somente esse usuário, tem acesso. No Linux, uma boa prática seria chmod 600
(somente o dono pode ler e escrever) ou chmod 644
(o dono pode escrever mas todos podem ler).
Você pode ler uma discussão mais extensa sobre permissões e usuários do Linux/Unix aqui