PHP - Falha ao abrir o fluxo: esse arquivo ou diretório não existe

166

Em scripts PHP, se chamando include(), require(), fopen(), ou seus derivados, tais como include_once, require_onceou até mesmo, move_uploaded_file(), um muitas vezes é executado em um erro ou aviso:

Falha ao abrir o fluxo: esse arquivo ou diretório não existe.

Qual é um bom processo para encontrar rapidamente a causa raiz do problema?

Vic Seedoubleyew
fonte
5
Limpei os comentários não relacionados a este post. Por favor, mantenha as meta discussões em meta. No entanto, observe que a discussão sobre a viabilidade de perguntas canônicas foi feita repetidas vezes. Veja o exemplo aqui .
Ghost de Madara
1
Eu tenho o mesmo problema, a única solução que sempre funcionou é: -1 Vá para o arquivo para incluir, botão direito, propriedades, copie o caminho completo Por exemplo: C: /......../ file.php 2- inclua. Na verdade, vi que essa pergunta é respondida e a resposta é validada, mas para mim, em alguns casos, não funcionou, até encontrar o caminho descrito acima.
Rshad
@Rash obrigado por contribuir. Infelizmente, sua solução está errada, porque mencionará o nome absoluto do caminho, e isso está errado. A razão pela qual isso está errado é que, no momento em que você copiar seu projeto para outro lugar ou movê-lo para dentro do computador, tudo será interrompido.
Vic Seedoubleyew

Respostas:

259

Há muitas razões pelas quais se pode encontrar esse erro e, portanto, uma boa lista de verificação do que verificar primeiro ajuda consideravelmente.

Vamos considerar que estamos solucionando problemas da seguinte linha:

require "/path/to/file"


Lista de controle


1. Verifique o caminho do arquivo para erros de digitação

  • verifique manualmente (verificando visualmente o caminho)
  • ou mova o que for chamado por require*ou include*para sua própria variável, faça eco, copie-o e tente acessá-lo a partir de um terminal:

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

    Então, em um terminal:

    cat <file path pasted>


2. Verifique se o caminho do arquivo está correto em relação às considerações sobre o caminho relativo versus o absoluto

  • se estiver iniciando por uma barra "/", não se refere à raiz da pasta do seu site (a raiz do documento), mas à raiz do seu servidor.
    • por exemplo, o diretório do seu site pode ser /users/tony/htdocs
  • se não estiver iniciando por uma barra, está contando com o caminho de inclusão (veja abaixo) ou o caminho é relativo. Se for relativo, o PHP calculará relativamente ao caminho do diretório de trabalho atual .
    • portanto, não é relativo ao caminho da raiz do seu site ou ao arquivo em que você está digitando
    • por esse motivo, sempre use caminhos de arquivo absolutos

Melhores Práticas :

Para tornar seu script robusto, caso você mova as coisas, enquanto ainda gera um caminho absoluto em tempo de execução, você tem 2 opções:

  1. use require __DIR__ . "/relative/path/from/current/file". A __DIR__constante mágica retorna o diretório do arquivo atual.
  2. defina uma SITE_ROOTconstante você mesmo:

    • na raiz do diretório do seu site, crie um arquivo, por exemplo config.php
    • em config.php, write

      define('SITE_ROOT', __DIR__);
    • em todos os arquivos nos quais você deseja referenciar a pasta raiz do site, inclua config.phpe use a SITE_ROOTconstante onde quiser:

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

Essas 2 práticas também tornam seu aplicativo mais portátil porque não depende de configurações ini, como o caminho de inclusão.


3. Verifique seu caminho de inclusão

Outra maneira de incluir arquivos, nem de maneira relativamente nem puramente absoluta, é confiar no caminho de inclusão . Geralmente é o caso de bibliotecas ou estruturas, como a estrutura Zend.

Essa inclusão terá a seguinte aparência:

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

Nesse caso, você deve certificar-se de que a pasta onde está o "Zend" faça 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 ela com:

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


4. Verifique se o seu servidor tem acesso a esse arquivo

Pode ser que, juntos, o usuário executando o processo do servidor (Apache ou PHP) simplesmente não tenha permissão para ler ou gravar nesse arquivo.

Para verificar em qual usuário o servidor está executando, você pode usar posix_getpwuid :

$user = posix_getpwuid(posix_geteuid());

var_dump($user);

Para descobrir as permissões no arquivo, digite o seguinte comando no terminal:

ls -l <path/to/file>

e veja a notação simbólica de permissão


5. Verifique as configurações do PHP

Se nenhuma das opções acima funcionou, provavelmente o problema é que algumas configurações do PHP proíbem o acesso a esse arquivo.

Três configurações podem ser relevantes:

  1. open_basedir
    • Se isso estiver definido, o PHP não poderá acessar nenhum arquivo fora do diretório especificado (nem mesmo através de um link simbólico).
    • No entanto, o comportamento padrão é que não seja definido e, nesse caso, não há restrição
    • Isso pode ser verificado ligando phpinfo()ou usandoini_get("open_basedir")
    • Você pode alterar a configuração editando o arquivo php.ini ou o arquivo httpd.conf
  2. modo de segurança
    • se estiver ativado, podem ser aplicadas restrições. No entanto, isso foi removido no PHP 5.4. Se você ainda está em uma versão que suporta o modo de segurança, atualize para uma versão PHP que ainda está sendo suportada .
  3. allow_url_fopen e allow_url_include
    • isso se aplica apenas à inclusão ou abertura de arquivos por meio de um processo de rede, como http: //, não ao tentar incluir arquivos no sistema de arquivos local
    • isso pode ser verificado ini_get("allow_url_include")e definido comini_set("allow_url_include", "1")


Caixas de canto

Se nenhuma das opções acima estiver ativada para diagnosticar o problema, aqui estão algumas situações especiais que podem ocorrer:


1. A inclusão de biblioteca que se baseia no caminho de inclusão

Pode acontecer que você inclua uma biblioteca, por exemplo, a estrutura do Zend, usando um caminho relativo ou absoluto. Por exemplo :

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

Mas você ainda recebe o mesmo tipo de erro.

Isso pode acontecer porque o arquivo que você incluiu (com êxito), possui uma instrução de inclusão para outro arquivo, e a segunda instrução de inclusão assume que você adicionou o caminho dessa biblioteca ao caminho de inclusão.

Por exemplo, o arquivo de estrutura do Zend mencionado anteriormente pode ter o seguinte:

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

que não é uma inclusão por caminho relativo, nem por caminho absoluto. Supõe-se que o diretório da estrutura do Zend tenha sido adicionado ao caminho de inclusão.

Nesse caso, a única solução prática é adicionar o diretório ao seu caminho de inclusão.


2. SELinux

Se você estiver executando o Linux com segurança avançada, pode ser o motivo do problema, negando o acesso ao arquivo do servidor.

Para verificar se o SELinux está ativado no seu sistema, execute o sestatuscomando em um terminal. Se o comando não existir, o SELinux não estará no seu sistema. Se existir, deve informar se é aplicado ou não.

Para verificar se as políticas do SELinux são o motivo do problema, tente desativá-lo temporariamente. No entanto, tenha cuidado, pois isso desativará completamente a proteção. Não faça isso no seu servidor de produção.

setenforce 0

Se você não tiver mais o problema com o SELinux desativado, essa é a causa raiz.

Para resolvê-lo , você precisará configurar o SELinux de acordo.

Os seguintes tipos de contexto serão necessários:

  • httpd_sys_content_t para arquivos que você deseja que seu servidor possa ler
  • httpd_sys_rw_content_t para arquivos nos quais você deseja acesso de leitura e gravação
  • httpd_log_t para arquivos de log
  • httpd_cache_t para o diretório de cache

Por exemplo, para atribuir o httpd_sys_content_ttipo de contexto ao diretório raiz do site, execute:

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

Se o seu arquivo estiver em um diretório inicial, você também precisará ativar o httpd_enable_homedirsbooleano:

setsebool -P httpd_enable_homedirs 1

De qualquer forma, pode haver vários motivos pelos quais o SELinux negaria o acesso a um arquivo, dependendo de suas políticas. Então, você precisará investigar isso. Aqui está um tutorial especificamente sobre a configuração do SELinux para um servidor da web.


3. Symfony

Se você estiver usando o Symfony e tiver esse erro ao fazer o upload para um servidor, pode ser que o cache do aplicativo não tenha sido redefinido, porque app/cachefoi feito o upload ou esse cache não foi limpo.

Você pode testar e corrigir isso executando o seguinte comando do console:

cache:clear


4. Caracteres não ACSII dentro do arquivo Zip

Aparentemente, esse erro pode ocorrer também ao chamar zip->close()quando alguns arquivos dentro do zip têm caracteres não ASCII em seus nomes de arquivo, como "é".

Uma solução potencial é envolver o nome do arquivo utf8_decode()antes de criar o arquivo de destino.

Créditos a Fran Cano por identificar e sugerir uma solução para esse problema

Vic Seedoubleyew
fonte
4
Eu acho que mencionar selinuxpode ser uma boa idéia aqui. você precisará pelo menos httpd_sys_content_t(diretórios e arquivos somente leitura usados ​​pelo Apache) nos arquivos incluídos.
bansi
Muito obrigado pela sugestão. Como não estou familiarizado com o SELinux, fiz algumas leituras e tentei responder a este caso. Sinta-se à vontade para comentar ou sugerir algumas edições, se não estiver correto. Mais uma vez obrigado pelo comentário !
Vic Seedoubleyew
chconé temporário e não sobreviverá a restoreconuma reinicialização. pode ser necessário usar semanagepara alterar o contexto do arquivo. Aqui está um bom tutorial simples para web site
bansi
Outra possibilidade de adicionar: cache do realpath: lyte.id.au/2014/05/01/what-the-hell-php
chrishiestand
@chrishiestand muito obrigado! Esse artigo é realmente interessante! Você se lembra qual foi o curso dos eventos que levaram a esse erro? Inicialmente, o usuário não tinha acesso de leitura a um arquivo e foi alterado, mas o cache ainda considerou que não era legível, e lançou esse erro ao abrir o arquivo?
Vic Seedoubleyew
16

Para adicionar à (realmente boa) resposta existente

Software de hospedagem compartilhada

open_basediré aquele que pode te surpreender porque pode ser especificado em uma configuração de servidor da web. Embora isso seja facilmente remediado se você executar seu próprio servidor dedicado, existem alguns pacotes de software de hospedagem compartilhados por aí (como Plesk, cPanel, etc) que configuram uma diretiva de configuração por domínio. Como o software cria o arquivo de configuração (ou seja httpd.conf), você não pode alterá-lo diretamente, porque o software de hospedagem o substituirá apenas quando reiniciar.

Com o Plesk, eles fornecem um lugar para substituir o httpd.confchamado chamado vhost.conf. Somente o administrador do servidor pode gravar este arquivo. A configuração do Apache se parece com isso

<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 servidor que consulte o manual do software de hospedagem e servidor da Web que eles usam.

Permissões de arquivo

É importante observar que a execução de um arquivo por meio do servidor da Web é muito diferente de uma linha de comando ou execução de tarefa cron. A grande diferença é que seu servidor da web tem 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-dataou httpd(dependendo do seu servidor). Um trabalho cron ou a execução da CLI possui as permissões que o usuário que o executa (por exemplo, executar um script PHP como root, executa com permissões de root).

Muitas vezes as pessoas resolvem um problema de permissões fazendo o seguinte (exemplo do Linux)

chmod 777 /path/to/file

Esta não é uma idéia inteligente, porque o arquivo ou diretório agora é gravável em todo o mundo. Se você possui o servidor e é o único usuário, isso não é tão importante, mas se você estiver em um ambiente de hospedagem compartilhada, você acabou de dar acesso a todos no servidor.

O que você precisa fazer é determinar o (s) usuário (s) que precisam acessar e conceder somente a eles. Depois de saber quais usuários precisam acessar, verifique se

  1. Esse usuário possui o arquivo e, possivelmente, o diretório pai (especialmente o diretório pai, se você deseja gravar arquivos). Na maioria dos ambientes de hospedagem compartilhada, isso não será um problema, pois o usuário deve possuir todos os arquivos abaixo da raiz. Um exemplo do Linux é mostrado abaixo

     chown apache:apache /path/to/file
  2. O usuário, e somente esse usuário, tem acesso. No Linux, uma boa prática seria chmod 600(apenas o proprietário pode ler e escrever) ou chmod 644(o proprietário pode escrever, mas todos podem ler)

Você pode ler uma discussão mais extensa sobre permissões e usuários do Linux / Unix aqui

Machavity
fonte
7
  1. Veja o erro exato

Meu código funcionou bem em todas as máquinas, mas apenas nessa começou a dar problema (que costumava funcionar, acho que eu acho). Utilizado o caminho "document_root" de eco para depuração e também olhou atentamente para o erro, encontrou este

Aviso: include ( D: /MyProjects/testproject//functions/connections.php ): falha ao abrir o fluxo:

Você pode ver facilmente onde estão os problemas. Os problemas são // antes das funções

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

Portanto, basta remover o lading / de include e ele deve funcionar bem. O interessante é que esses comportamentos são diferentes em versões diferentes. Eu corro o mesmo código no laptop, Macbook Pro e neste PC, tudo funcionou bem até. Espero que isso ajude alguém.

  1. Copie além do local do arquivo no navegador para garantir que ele exista. Às vezes, os arquivos são excluídos inesperadamente (aconteceu comigo) e também foi o problema no meu caso.
Hammad Khan
fonte
Qual é a diferença da etapa 1 da lista de verificação abaixo?
Vic Seedoubleyew
Etapa 2: uma verificação adicional, não relacionada à etapa 1. Simplesmente navegue até o caminho proposto no navegador e veja se o arquivo está lá (não no Windows Explorer, mas no navegador).
Hammad Khan
2

Adicionar script com parâmetros de consulta

Esse foi o meu caso. Na verdade, ele vincula à pergunta # 4485874 , mas vou explicá-la aqui em breve.
Quando você tenta exigir path/to/script.php?parameter=value, o PHP procura pelo arquivo nomeado script.php?parameter=value, porque o UNIX permite que você tenha caminhos como este.
Se você realmente precisar passar alguns dados para o script incluído, apenas declare-o como $variable=...ou $GLOBALS[]=...ou da maneira que desejar.

Paul Lynn
fonte
2

Ações de Samba

Se você possui um servidor de teste Linux e trabalha em um cliente Windows, o compartilhamento Samba interfere no comando chmod . Então, mesmo se você usar:

chmod -R 777 myfolder

no lado do Linux, é perfeitamente possível que o grupo Unix \ www-data ainda não tenha acesso de gravação. Uma solução funcional se o seu compartilhamento estiver configurado para que os administradores do Windows sejam mapeados para raiz: no Windows, abra as Permissões, desative Herança da sua pasta com cópia e conceda acesso total a www-data.

Stephan Brunker
fonte
1

Outra causa possível: Renomear e / ou mover arquivos enquanto estiver em um editor de texto. Eu segui todas as etapas acima sem êxito até excluir o arquivo que continuava lançando esse erro e criar um novo, que corrigia o problema.

zMeadz
fonte
1
se eu entendi o que você quis dizer corretamente, isso teria ocorrido instantaneamente na primeira verificação da lista
Vic Seedoubleyew
# 1 não é explícito sobre causas potenciais
zMeadz
sim, mas você não se importa com as causas, se preocupa em encontrar a maneira de corrigir o problema. Mais importante ainda, o passo número 1 teria resolvido o seu problema
Vic Seedoubleyew