PHP - Akış açılamadı: Böyle bir dosya veya dizin yok


166

PHP komut olarak, çağıran olsun include(), require(), fopen()gibi, veya bunların türevleri include_once, require_oncehatta, move_uploaded_file()bir sıklıkla Hata veya uyarı içine çalıştırır:

Akış açılamadı: Böyle bir dosya veya dizin yok.

Sorunun temel nedenini hızlı bir şekilde bulmak için iyi bir süreç nedir?


5
Bu yayındaki konu dışı yorumları temizledim. Lütfen meta tartışmalarını meta olarak saklayın. Bununla birlikte, kanonik soruların uygulanabilirliğinin tartışmasının defalarca yapıldığını lütfen unutmayın. Buradaki örneğe bakın .
Madara'nın Hayaleti

1
Aynı sorunu aldım, her zaman çalışan tek çözüm: -1 Dahil etmek için dosyaya gidin, sağ botton, özellikler, tam yolu kopyalayın Örneğin: C: /......../ file.php 2- ekleyin. Aslında bu sorunun cevaplandığını ve cevabın doğrulandığını gördüm, ancak bazı durumlarda benim için, yukarıda açıklanan yolu bulana kadar işe yaramadı.
Rshad

@ Katkıda bulunduğunuz için teşekkür ederiz. Ne yazık ki çözümünüz yanlış, çünkü mutlak yol adından bahsedecek ve bu yanlış. Bunun yanlış olmasının nedeni, projenizi başka bir yere kopyaladığınız veya bilgisayarınızın içine taşıdığınız an her şeyin kırılacağıdır.
Vic Seedoubleyew

Yanıtlar:


260

Birinin bu hatayla karşılaşmasının birçok nedeni vardır ve bu nedenle öncelikle neyin kontrol edileceğine dair iyi bir kontrol listesi önemli ölçüde yardımcı olur.

Aşağıdaki satırda sorun giderdiğimizi düşünelim:

require "/path/to/file"


Kontrol Listesi


1. Dosya yolunda yazım hatası olup olmadığını kontrol edin

  • manuel olarak kontrol et (yolu görsel olarak kontrol ederek)
  • tarafından çağrılan ne olursa olsun veya taşıma require*veya include*kendi değişkene, kopyalamak ve bir terminal onu erişmeyi deneyin, bunu yankı:

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

    Sonra bir terminalde:

    cat <file path pasted>


2. Dosya yolunun göreli ve mutlak yolla ilgili hususlar açısından doğru olup olmadığını kontrol edin

  • eğik çizgi "/" ile başlıyorsa, web sitenizin klasörünün kökünden (belge kökü) değil, sunucunuzun kökünden bahsetmektedir.
    • örneğin, web sitenizin dizini /users/tony/htdocs
  • eğik çizgi ile başlamıyorsa, içerme yoluna dayanır (aşağıya bakın) veya yol görecelidir. Göreli ise, PHP geçerli çalışma dizininin yolunu göreceli olarak hesaplar .
    • bu nedenle, web sitenizin kök yoluna veya yazdığınız dosyaya göre değil
    • bu nedenle her zaman mutlak dosya yolları kullanın

En iyi uygulamalar:

Bir şeyleri hareket ettirmeniz durumunda komut dosyanızı sağlam hale getirmek için, çalışma zamanında mutlak bir yol oluştururken 2 seçeneğiniz vardır:

  1. kullanın require __DIR__ . "/relative/path/from/current/file". __DIR__Sihirli sabit akım dosyanın dizinini döndürür.
  2. bir SITE_ROOTsabiti kendiniz tanımlayın :

    • web sitenizin dizininin kökünde bir dosya oluşturun, ör. config.php
    • içinde config.php, yaz

      define('SITE_ROOT', __DIR__);
    • site kök klasörüne başvurmak istediğiniz her dosyada config.php, SITE_ROOTsabiti ekleyin ve istediğiniz yerde sabit kullanın :

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

Bu 2 uygulama, uygulamanızı daha taşınabilir hale getirir, çünkü içerme yolu gibi ini ayarlarına dayanmaz.


3. Dahil etme yolunuzu kontrol edin

Ne görece ne de tamamen mutlak olarak dosyaları dahil etmenin bir başka yolu, içerme yoluna güvenmektir . Bu genellikle Zend çerçevesi gibi kütüphaneler veya çerçeveler için geçerlidir.

Böyle bir içerme şöyle görünecektir:

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

Bu durumda, "Zend" olan klasörün dahil etme yolunun bir parçası olduğundan emin olmak istersiniz.

Dahil etme yolunu aşağıdakilerle kontrol edebilirsiniz:

echo get_include_path();

Klasöre aşağıdakilerle bir klasör ekleyebilirsiniz:

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


4. Sunucunuzun bu dosyaya erişimi olup olmadığını kontrol edin

Hep birlikte, sunucu işlemini (Apache veya PHP) çalıştıran kullanıcının bu dosyadan okuma veya yazma iznine sahip olmaması olabilir.

Sunucunun hangi kullanıcıyı çalıştırdığını kontrol etmek için posix_getpwuid kullanabilirsiniz :

$user = posix_getpwuid(posix_geteuid());

var_dump($user);

Dosyadaki izinleri bulmak için uçbirime aşağıdaki komutu yazın:

ls -l <path/to/file>

ve izin sembolik notasyonuna bakın


5. PHP ayarlarını kontrol edin

Yukarıdakilerin hiçbiri işe yaramadıysa, sorun muhtemelen bazı PHP ayarlarının bu dosyaya erişmesini yasaklamasıdır.

Üç ayar alakalı olabilir:

  1. open_basedir
    • Bu ayarlanırsa, PHP belirtilen dizinin dışındaki herhangi bir dosyaya erişemez (sembolik bir bağlantı üzerinden bile olsa).
    • Ancak, varsayılan davranış ayarlanmaması içindir, bu durumda herhangi bir kısıtlama yoktur
    • Bu, çağrılarak phpinfo()veya kullanılarak kontrol edilebilir.ini_get("open_basedir")
    • Php.ini dosyanızı veya httpd.conf dosyanızı düzenleyerek ayarı değiştirebilirsiniz.
  2. güvenli mod
    • bu açıksa kısıtlamalar uygulanabilir. Ancak, bu PHP 5.4 kaldırıldı. Hala güvenli modun desteklenmesini destekleyen bir sürümdeyseniz, hala desteklenmekte olan bir PHP sürümüne yükseltme yapın .
  3. allow_url_fopen ve allow_url_include
    • Bu, yalnızca yerel dosya sistemine dosya eklemeye çalışırken değil, http: // gibi bir ağ işlemi yoluyla dosya eklemek veya açmak için geçerlidir
    • bu ile kontrol edilebilir ini_get("allow_url_include")veini_set("allow_url_include", "1")


Köşe dolapları

Yukarıdakilerin hiçbiri sorunu teşhis etmeyi etkinleştirmediyse, olabilecek bazı özel durumlar şunlardır:


1. Dahil etme yoluna dayanan kütüphanenin dahil edilmesi

Göreli veya mutlak bir yol kullanarak bir kitaplık, örneğin Zend çerçevesi dahil edebilirsiniz. Örneğin :

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

Ama yine de aynı tür bir hata alıyorsunuz.

Bunun nedeni, (başarıyla) eklediğiniz dosyanın kendisine başka bir dosya için bir include deyimi olması ve bu ikinci include deyiminin söz konusu kitaplığın yolunu ekleme yoluna eklediğinizi varsayması olabilir.

Örneğin, daha önce bahsedilen Zend çerçeve dosyası aşağıdakileri içerebilir:

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

ne göreceli yolun ne de mutlak yolun içerdiği bir şeydir. Zend çerçeve dizininin dahil etme yoluna eklendiğini varsayar.

Böyle bir durumda, tek pratik çözüm dizini içerme yolunuza eklemektir.


2. SELinux

Security-Enhanced Linux çalıştırıyorsanız, sunucudan dosyaya erişimi reddederek sorunun nedeni olabilir.

SELinux'un sisteminizde etkin olup olmadığını kontrol etmek için sestatuskomutu bir terminalde çalıştırın . Komut yoksa, SELinux sisteminizde değildir. Varsa, size uygulanıp uygulanmayacağını söylemelidir.

SELinux politikalarının sorunun nedeni olup olmadığını kontrol etmek için geçici olarak kapatmayı deneyebilirsiniz. Ancak dikkatli olun, çünkü bu korumayı tamamen devre dışı bırakacaktır. Bunu üretim sunucunuzda yapmayın.

setenforce 0

SELinux ile ilgili sorununuz artık kapalıysa, bu temel nedendir.

Bunu çözmek için SELinux'u buna göre yapılandırmanız gerekecektir.

Aşağıdaki bağlam türleri gerekli olacaktır:

  • httpd_sys_content_t sunucunuzun okuyabilmesini istediğiniz dosyalar için
  • httpd_sys_rw_content_t okuma ve yazma erişimi istediğiniz dosyalar için
  • httpd_log_t günlük dosyaları için
  • httpd_cache_t önbellek dizini için

Örneğin, httpd_sys_content_tbağlam türünü web sitenizin kök dizinine atamak için şunu çalıştırın:

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

Dosyanız bir giriş dizinindeyse, boole'yi de açmanız gerekir httpd_enable_homedirs:

setsebool -P httpd_enable_homedirs 1

Her durumda, SELinux'un politikalarınıza bağlı olarak bir dosyaya erişimi reddetmesinin çeşitli nedenleri olabilir. Yani bunu sorgulamanız gerekecek. İşte bir web sunucusu için SELinux'u yapılandırmakla ilgili özel bir öğretici.


3. Symfony

Symfony kullanıyorsanız ve bir sunucuya yükleme yaparken bu hatayı yaşıyorsanız, uygulamanın önbelleği app/cacheyüklenmiş olmadığı için önbelleğin sıfırlanmamış olması veya önbelleğin temizlenmemiş olması olabilir.

Aşağıdaki konsol komutunu çalıştırarak bunu test edebilir ve düzeltebilirsiniz:

cache:clear


4. Zip dosyası içinde ACSII olmayan karakterler

Görünüşe göre, bu hata zip->close()zip içindeki bazı dosyalar dosya adlarında "é" gibi ASCII olmayan karakterlere sahip olduğunda da çağrılabilir.

Olası bir çözüm, utf8_decode()hedef dosyayı oluşturmadan önce dosya adını girmektir .

Fran Cano'ya bu konuya bir çözüm bulup önerdiği için verilen krediler


4
selinuxBurada bahsetmek iyi bir fikir olabilir. httpd_sys_content_tdahil edilen dosyalar için en azından (Salt okunur dizinler ve Apache tarafından kullanılan dosyalar) iznine ihtiyacınız olacaktır .
bansi

Öneri için çok teşekkürler. SELinux'a aşina olmadığım için biraz okuma yaptım ve bu davayı cevaplamaya çalıştım. Lütfen geribildirimden çekinmeyin veya doğru değilse bazı düzenlemeler önerin. Yorum için tekrar teşekkürler !
Vic Seedoubleyew

chcongeçicidir ve bir restoreconveya yeniden başlatılamaz. semanagedosyanın içeriğini değiştirmek için kullanmanız gerekebilir . İşte web sitesi için
bansi

Eklemek için başka bir olasılık: realpath önbellekleme: lyte.id.au/2014/05/01/what-the-hell-php
chrishiestand

@chrishiestand çok teşekkürler! Bu makale gerçekten ilginç! Bu hataya neden olan olayların seyrini hatırlıyor musunuz? Başlangıçta kullanıcının bir dosyaya okuma erişimi yoktu, o zaman değişti, ancak önbellek hala okunabilir olmadığını düşündü, bu yüzden dosya açıldığında bu hatayı attı mı?
Vic Seedoubleyew

16

Mevcut (gerçekten iyi) cevaba eklemek için

Paylaşımlı Hosting Yazılımı

open_basedirbir web sunucusu yapılandırmasında belirtilebileceği için sizi güdük. Kendi özel sunucunuzu çalıştırırsanız bu kolayca çözülebilir, ancak etki alanı başına bir yapılandırma yönergesi yapılandıracak bazı paylaşılan barındırma yazılım paketleri vardır (Plesk, cPanel, vb.). Yazılım yapılandırma dosyasını oluşturduğundan (yani httpd.conf) doğrudan barındırma yazılımı yeniden başlatıldığında üzerine yazılacağı için bu dosyayı doğrudan değiştiremezsiniz.

Plesk'e ile, Resim geçersiz kılmak için bir yer sağlamak httpd.confdenir vhost.conf. Bu dosyayı yalnızca sunucu yöneticisi yazabilir. Apache için yapılandırma şuna benzer

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

Sunucu yöneticinizin, kullandıkları barındırma ve web sunucusu yazılımı kılavuzuna bakmasını sağlayın.

Dosya İzinleri

Bir dosyayı web sunucunuz üzerinden yürütmenin bir komut satırından veya cron işi yürütmesinden çok farklı olduğunu unutmamak önemlidir. Büyük fark, web sunucunuzun kendi kullanıcısı ve izinleri olmasıdır. Güvenlik nedeniyle bu kullanıcı oldukça kısıtlıdır. Apache, örneğin, genellikle apache, www-dataya httpd(sunucunuzda bağlı olarak). Bir cron işi veya CLI yürütme, onu çalıştıran kullanıcının sahip olduğu izinlere sahiptir (yani root olarak bir PHP betiği çalıştırmak kök izinleriyle yürütülecektir).

Kullanıcılar bir izin sorununu aşağıdakileri yaparak çözecektir (Linux örneği)

chmod 777 /path/to/file

Bu akıllıca bir fikir değil, çünkü dosya veya dizin artık dünya tarafından yazılabilir. Sunucunun sahibi sizseniz ve tek kullanıcıysanız, bu büyük bir anlaşma değildir, ancak paylaşılan bir barındırma ortamındaysanız, sunucu erişiminizdeki herkese vermiş olursunuz.

Yapmanız gereken, erişmesi gereken kullanıcıları belirlemek ve yalnızca onlara erişmelerini sağlamaktır. Hangi kullanıcıların erişime ihtiyacı olduğunu öğrendikten sonra,

  1. Söz konusu kullanıcı dosyanın ve muhtemelen üst dizinin (özellikle dosya yazmak istiyorsanız üst dizinin) sahibidir . Paylaşılan barındırma ortamlarının çoğunda bu bir sorun oluşturmaz, çünkü kullanıcı kökünüzün altındaki tüm dosyalara sahip olmalıdır. Linux örneği aşağıda gösterilmiştir

     chown apache:apache /path/to/file
  2. Kullanıcı ve yalnızca o kullanıcının erişimi vardır. Linux'ta iyi bir uygulama chmod 600(sadece sahip okuyabilir ve yazabilir) veya chmod 644(sahip yazabilir ama herkes okuyabilir)

Linux / Unix izinleri ve kullanıcıları hakkında daha geniş bir tartışmayı buradan okuyabilirsiniz


7
  1. Bak tam hata

Kodum tüm makinelerde iyi çalıştı ama sadece bu bir sorun vermeye başladı (ki işe kullanılan bulmak sanırım). Hata ayıklama yankı "document_root" yolu kullanılan ve aynı zamanda hata yakından baktı, bu bulundu

Uyarı: include ( D: /MyProjects/testproject//functions/connections.php ): akış açılamadı:

Sorunların nerede olduğunu kolayca görebilirsiniz. Sorunlar // fonksiyonlardan önce

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

Bu yüzden konşimentoyu / eklentiden çıkarın ve iyi çalışması gerekir. İlginç olan bu davranışların farklı versiyonlarda farklı olmasıdır. Laptop, Macbook Pro ve bu bilgisayarda aynı kodu çalıştırıyorum, hepsi kadar iyi çalıştı. Umarım bu birine yardımcı olur.

  1. Dosyanın var olduğundan emin olmak için tarayıcıdaki dosya konumunu geçerek kopyalayın. Bazen dosyalar beklenmedik bir şekilde silinir (benimle oldu) ve benim durumumda da sorun vardı.

Aşağıdaki kontrol listesinin 1. adımından farkı nedir?
Vic Seedoubleyew

Adım 2, adım 1 ile ilgili olmayan ek bir kontrol. Tarayıcıda önerilen yola gidin ve dosyayı orada görüp görmediğinize bakın (windows explorer'da değil, tarayıcıda).
Hammad Khan

2

Sorgu parametreleriyle komut dosyası ekle

Benim durumum buydu. Aslında # 4485874 sorusuna bağlantı veriyor , ancak burada kısaca açıklayacağım.
Gereksinim duymaya çalıştığınızda path/to/script.php?parameter=value, PHP script.php?parameter=valueUNIX'in böyle yollara sahip olmasına izin verdiği için dosyayı adlandırır .
Gerçekten dahil komut dosyasına bazı verileri geçmeleri gerekiyor ise tıpkı ilan $variable=...veya $GLOBALS[]=...sizin gibi ya da başka bir şekilde.


2

Samba Payları

Bir Linux test sunucunuz varsa ve bir Windows İstemcisinden çalışıyorsanız, Samba paylaşımı chmod komutunu engeller . Yani, kullansanız bile:

chmod -R 777 myfolder

Linux tarafında ise Unix Group \ www-data 'nın hala yazma erişimine sahip olmaması mümkündür. Paylaşımınız Windows yöneticilerinin kök dizinine eşlenecek şekilde ayarlanmışsa çalışan bir çözüm: Windows'dan İzinler'i açın, kopyala klasörünüz için Devralmayı devre dışı bırakın ve sonra www-verileri için tam erişim verin.


1

Başka bir olası neden: Bir metin düzenleyicideyken dosyaları yeniden adlandırma ve / veya taşıma. Bu hatayı atmaya devam eden dosyayı silene ve sorunu düzelten yeni bir tane oluşturana kadar yukarıdaki tüm adımları başarılı olmadan geçtim.


1
doğru bir şekilde ne demek istediğinizi
anlarsam

# 1 potansiyel nedenler hakkında açık değil
zMeadz

Evet, ancak nedenleri umursamıyorsunuz, sorunu çözmenin yolunu bulmayı önemsiyorsunuz. Daha da önemlisi, 1. adım sorununuzu
çözerdi
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.