PHP - Gagal membuka streaming: Tidak ada file atau direktori tersebut

166

Dalam skrip PHP, apakah menelepon include(), require(), fopen(), atau turunannya seperti include_once, require_once, atau bahkan, move_uploaded_file(), satu sering berjalan ke kesalahan atau peringatan:

Gagal membuka aliran: Tidak ada file atau direktori seperti itu.

Apa proses yang baik untuk menemukan akar penyebab masalah dengan cepat?

Vic Seedoubleyew
sumber
5
Saya telah membersihkan komentar di luar topik pada posting ini. Harap simpan diskusi meta di meta. Namun, harap perhatikan bahwa pembahasan tentang pertanyaan kanonik telah dilakukan berulang kali. Lihat contoh di sini .
Hantu Madara
1
Saya mendapat masalah yang sama, satu-satunya solusi yang selalu bekerja adalah: -1 Buka file untuk memasukkan, kanan botton, properti, salin path lengkap Sebagai Contoh: C: / ............../ file.php 2- memasukkannya. Sebenarnya saya melihat bahwa pertanyaan ini dijawab, dan jawabannya divalidasi, tetapi bagi saya dalam beberapa kasus tidak berhasil, sampai saya menemukan cara yang dijelaskan di atas.
Rshad
@Rash, terima kasih telah berkontribusi. Sayangnya solusi Anda salah, karena akan menyebutkan nama path absolut, dan itu salah. Alasan mengapa ini salah, adalah karena saat Anda menyalin proyek Anda di tempat lain, atau memindahkannya ke dalam komputer Anda, semuanya akan rusak.
Vic Seedoubleyew

Jawaban:

259

Ada banyak alasan mengapa orang mungkin mengalami kesalahan ini dan dengan demikian daftar periksa yang baik tentang apa yang harus diperiksa terlebih dahulu sangat membantu.

Mari kita pertimbangkan bahwa kita memecahkan masalah pada baris berikut:

require "/path/to/file"


Daftar periksa


1. Periksa path file untuk kesalahan ketik

  • baik memeriksa secara manual (dengan memeriksa jalan secara visual)
  • atau memindahkan apa pun yang dipanggil oleh require*atau include*ke variabelnya sendiri, menggemakannya, menyalinnya, dan mencoba mengaksesnya dari terminal:

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

    Kemudian, di terminal:

    cat <file path pasted>


2. Periksa apakah jalur file benar tentang pertimbangan jalur relatif vs absolut

  • jika dimulai dengan garis miring "/" maka itu tidak merujuk ke akar folder situs web Anda (akar dokumen), tetapi ke akar server Anda.
    • misalnya, direktori situs web Anda mungkin /users/tony/htdocs
  • jika tidak dimulai dengan garis miring ke depan maka ia bisa mengandalkan jalur sertakan (lihat di bawah) atau jalur tersebut relatif. Jika relatif, maka PHP akan menghitung relatif ke jalur direktori kerja saat ini .
    • dengan demikian, tidak relatif terhadap jalur root situs web Anda, atau ke file tempat Anda mengetik
    • untuk alasan itu, selalu gunakan jalur file absolut

Praktik terbaik :

Untuk membuat skrip Anda tangguh jika Anda memindahkan banyak hal, sambil tetap menghasilkan path absolut saat runtime, Anda memiliki 2 opsi:

  1. gunakan require __DIR__ . "/relative/path/from/current/file". The __DIR__magic konstan mengembalikan direktori dari file saat ini.
  2. tentukan SITE_ROOTkonstanta sendiri:

    • di root direktori situs web Anda, buat file, mis config.php
    • di config.php, tulis

      define('SITE_ROOT', __DIR__);
    • di setiap file tempat Anda ingin mereferensikan folder root situs, sertakan config.php, dan kemudian gunakan SITE_ROOTkonstanta di mana pun Anda suka:

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

2 praktik ini juga membuat aplikasi Anda lebih portabel karena tidak bergantung pada pengaturan ini seperti jalur sertakan.


3. Periksa jalur sertakan Anda

Cara lain untuk memasukkan file, baik relatif maupun murni, adalah dengan mengandalkan path include . Ini sering terjadi untuk perpustakaan atau kerangka kerja seperti kerangka kerja Zend.

Inklusi seperti itu akan terlihat seperti ini:

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

Dalam hal ini, Anda harus memastikan bahwa folder tempat "Zend" berada, adalah bagian dari path include.

Anda dapat memeriksa jalur sertakan dengan:

echo get_include_path();

Anda dapat menambahkan folder ke dalamnya dengan:

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


4. Pastikan server Anda memiliki akses ke file itu

Mungkin secara keseluruhan, pengguna yang menjalankan proses server (Apache atau PHP) sama sekali tidak memiliki izin untuk membaca atau menulis ke file itu.

Untuk memeriksa di bawah pengguna apa server berjalan Anda dapat menggunakan posix_getpwuid :

$user = posix_getpwuid(posix_geteuid());

var_dump($user);

Untuk mengetahui izin pada file, ketikkan perintah berikut di terminal:

ls -l <path/to/file>

dan lihat notasi simbolis izin


5. Periksa pengaturan PHP

Jika tidak ada di atas yang berfungsi, maka masalahnya mungkin beberapa pengaturan PHP melarangnya untuk mengakses file itu.

Tiga pengaturan mungkin relevan:

  1. open_basedir
    • Jika ini diatur, PHP tidak akan dapat mengakses file apa pun di luar direktori yang ditentukan (bahkan melalui tautan simbolik).
    • Namun, perilaku default adalah untuk tidak diatur dalam hal ini tidak ada batasan
    • Ini dapat diperiksa dengan menelepon phpinfo()atau menggunakanini_get("open_basedir")
    • Anda dapat mengubah pengaturan dengan mengedit file php.ini atau file httpd.conf Anda
  2. mode aman
    • jika ini diaktifkan pembatasan mungkin berlaku. Namun, ini telah dihapus dalam PHP 5.4. Jika Anda masih pada versi yang mendukung peningkatan mode aman ke versi PHP yang masih didukung .
  3. allow_url_fopen dan allow_url_include
    • ini hanya berlaku untuk memasukkan atau membuka file melalui proses jaringan seperti http: // tidak ketika mencoba untuk memasukkan file pada sistem file lokal
    • ini dapat diperiksa ini_get("allow_url_include")dan diatur denganini_set("allow_url_include", "1")


Kasus sudut

Jika tidak ada yang di atas diaktifkan untuk mendiagnosis masalah, berikut adalah beberapa situasi khusus yang dapat terjadi:


1. Dimasukkannya perpustakaan mengandalkan jalur sertakan

Ini bisa terjadi bahwa Anda menyertakan perpustakaan, misalnya, kerangka kerja Zend, menggunakan jalur relatif atau absolut. Sebagai contoh :

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

Tapi kemudian Anda masih mendapatkan jenis kesalahan yang sama.

Ini bisa terjadi karena file yang Anda miliki (berhasil) sertakan, memiliki sendiri pernyataan sertakan untuk file lain, dan pernyataan sertakan kedua mengasumsikan bahwa Anda telah menambahkan lintasan pustaka itu ke path sertakan.

Misalnya, file kerangka kerja Zend yang disebutkan sebelumnya dapat memiliki yang berikut ini termasuk:

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

yang bukan merupakan inklusi oleh jalur relatif, maupun oleh jalur absolut. Diasumsikan bahwa direktori framework Zend telah ditambahkan ke path include.

Dalam kasus seperti itu, satu-satunya solusi praktis adalah menambahkan direktori ke jalur sertakan Anda.


2. SELinux

Jika Anda menjalankan Linux yang Ditingkatkan Keamanan, maka itu mungkin menjadi alasan masalah, dengan menolak akses ke file dari server.

Untuk memeriksa apakah SELinux diaktifkan di sistem Anda, jalankan sestatusperintah di terminal. Jika perintah tidak ada, maka SELinux tidak ada di sistem Anda. Jika memang ada, maka harus memberi tahu Anda apakah itu dipaksakan atau tidak.

Untuk memeriksa apakah kebijakan SELinux adalah penyebab masalahnya, Anda dapat mematikannya sementara. Namun berhati-hatilah, karena ini akan menonaktifkan perlindungan sepenuhnya. Jangan lakukan ini di server produksi Anda.

setenforce 0

Jika Anda tidak lagi memiliki masalah dengan SELinux dimatikan, maka ini adalah akar penyebabnya.

Untuk mengatasinya , Anda harus mengkonfigurasi SELinux.

Jenis konteks berikut akan diperlukan:

  • httpd_sys_content_t untuk file yang Anda inginkan agar server Anda dapat membaca
  • httpd_sys_rw_content_t untuk file yang ingin Anda baca dan tulis aksesnya
  • httpd_log_t untuk file log
  • httpd_cache_t untuk direktori cache

Misalnya, untuk menetapkan httpd_sys_content_ttipe konteks ke direktori root situs web Anda, jalankan:

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

Jika file Anda ada di direktori home, Anda juga perlu mengaktifkan httpd_enable_homedirsboolean:

setsebool -P httpd_enable_homedirs 1

Bagaimanapun, mungkin ada berbagai alasan mengapa SELinux akan menolak akses ke file, tergantung pada kebijakan Anda. Jadi, Anda perlu menanyakan hal itu. Berikut ini adalah tutorial khusus tentang mengkonfigurasi SELinux untuk server web.


3. Symfony

Jika Anda menggunakan Symfony, dan mengalami kesalahan ini saat mengunggah ke server, bisa jadi cache aplikasi belum disetel ulang, baik karena app/cachetelah diunggah, atau cache itu belum dihapus.

Anda dapat menguji dan memperbaikinya dengan menjalankan perintah konsol berikut:

cache:clear


4. Non ACSII karakter di dalam file Zip

Rupanya, kesalahan ini dapat terjadi juga saat memanggil zip->close()ketika beberapa file di dalam zip memiliki karakter non-ASCII dalam nama file mereka, seperti "é".

Solusi potensial adalah membungkus nama file utf8_decode()sebelum membuat file target.

Penghargaan kepada Fran Cano untuk mengidentifikasi dan menyarankan solusi untuk masalah ini

Vic Seedoubleyew
sumber
4
Saya pikir menyebutkan selinuxmungkin ide yang bagus di sini. Anda setidaknya akan membutuhkan httpd_sys_content_t(direktori Read-only dan file yang digunakan oleh Apache) izin pada file yang disertakan.
bansi
Terima kasih banyak atas sarannya. Karena saya tidak terbiasa dengan SELinux, saya membaca dan mencoba menjawab kasus ini. Silakan memberi umpan balik atau menyarankan beberapa pengeditan jika tidak benar. Sekali lagi terima kasih atas komentarnya!
Vic Seedoubleyew
chconbersifat sementara dan tidak akan bertahan restoreconatau reboot. Anda mungkin perlu menggunakan semanageuntuk mengubah konteks file. Berikut ini adalah tutorial sederhana yang
bansi
Kemungkinan lain untuk ditambahkan: caching realpath: lyte.id.au/2014/05/01/what-the-hell-php
chrishiestand
@ chrishiestand terima kasih banyak! Artikel itu sangat menarik! Apakah Anda ingat peristiwa apa yang menyebabkan kesalahan itu? Apakah itu pada awalnya pengguna tidak memiliki akses baca ke file, kemudian berubah, tetapi cache masih menganggap itu tidak dapat dibaca, sehingga melemparkan kesalahan itu pada file yang terbuka?
Vic Seedoubleyew
16

Untuk menambah jawaban (sangat bagus) yang ada

Perangkat Lunak Hosting Bersama

open_basediradalah salah satu yang dapat membuat Anda bingung karena dapat ditentukan dalam konfigurasi server web. Meskipun hal ini mudah diperbaiki jika Anda menjalankan server khusus Anda, ada beberapa paket perangkat lunak hosting bersama di luar sana (seperti Plesk, cPanel, dll.) Yang akan mengonfigurasi arahan konfigurasi berdasarkan per-domain. Karena perangkat lunak membuat file konfigurasi (yaitu httpd.conf) Anda tidak dapat mengubah file itu secara langsung karena perangkat lunak hosting hanya akan menimpanya ketika restart.

Dengan Plesk, mereka menyediakan tempat untuk menimpa tersedia httpd.confdisebut vhost.conf. Hanya admin server yang dapat menulis file ini. Konfigurasi untuk Apache terlihat seperti ini

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

Mintalah admin server Anda membaca manual untuk hosting dan perangkat lunak server web yang mereka gunakan.

Izin File

Penting untuk dicatat bahwa mengeksekusi file melalui server web Anda sangat berbeda dari baris perintah atau eksekusi pekerjaan cron. Perbedaan besar adalah bahwa server web Anda memiliki pengguna dan izinnya sendiri. Demi keamanan, pengguna dibatasi. Apache, misalnya, sering apache, www-dataatau httpd(tergantung pada server Anda). Pekerjaan cron atau eksekusi CLI memiliki izin apa pun yang dijalankan pengguna (mis. Menjalankan skrip PHP sebagai root akan dijalankan dengan izin root).

Banyak kali orang akan memecahkan masalah izin dengan melakukan hal berikut (contoh Linux)

chmod 777 /path/to/file

Ini bukan ide yang cerdas, karena file atau direktori sekarang dapat ditulisi dunia. Jika Anda memiliki server dan merupakan satu-satunya pengguna maka ini bukan masalah besar, tetapi jika Anda berada di lingkungan hosting bersama, Anda baru saja memberi semua orang akses server Anda.

Yang perlu Anda lakukan adalah menentukan pengguna yang membutuhkan akses dan hanya memberi mereka akses. Setelah Anda tahu pengguna mana yang membutuhkan akses, Anda ingin memastikannya

  1. Pengguna itu memiliki file dan mungkin direktori induk (terutama direktori induk jika Anda ingin menulis file). Di sebagian besar lingkungan hosting bersama, ini tidak akan menjadi masalah, karena pengguna Anda harus memiliki semua file di bawah root Anda. Contoh Linux ditunjukkan di bawah ini

     chown apache:apache /path/to/file
  2. Pengguna, dan hanya pengguna itu, yang memiliki akses. Di Linux, praktik yang baik adalah chmod 600(hanya pemilik yang dapat membaca dan menulis) atau chmod 644(pemilik dapat menulis tetapi semua orang dapat membaca)

Anda dapat membaca diskusi yang lebih luas tentang izin dan pengguna Linux / Unix di sini

Machavity
sumber
7
  1. Lihatlah kesalahan yang sebenarnya

Kode saya bekerja dengan baik pada semua mesin tetapi hanya yang ini mulai memberi masalah (yang dulu berfungsi saya kira). Digunakan jalur echo "document_root" untuk debug dan juga melihat dari dekat kesalahan, menemukan ini

Peringatan: termasuk ( D: /MyProjects/testproject//functions/connections.php ): gagal membuka aliran:

Anda dapat dengan mudah melihat di mana masalahnya. Masalahnya adalah // sebelum fungsi

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

Jadi cukup hapus lading / dari include dan itu akan berfungsi dengan baik. Yang menarik adalah perilaku ini berbeda pada versi yang berbeda. Saya menjalankan kode yang sama pada Laptop, Macbook Pro dan PC ini, semua berfungsi dengan baik sampai sekarang. Semoga ini bisa membantu seseorang.

  1. Salin melewati lokasi file di browser untuk memastikan file ada. Terkadang file terhapus secara tidak terduga (terjadi pada saya) dan itu juga masalah dalam kasus saya.
Hammad Khan
sumber
Apa bedanya dengan langkah 1 dari daftar periksa di bawah ini?
Vic Seedoubleyew
Langkah 2 pemeriksaan tambahan, tidak terkait dengan langkah 1. Cukup navigasikan ke jalur yang diusulkan di browser dan lihat apakah Anda melihat file di sana (tidak ada di windows explorer tetapi di browser).
Hammad Khan
2

Tambahkan skrip dengan parameter kueri

Itu kasus saya. Sebenarnya tautan ke pertanyaan # 4485874 , tapi saya akan menjelaskannya di sini segera.
Ketika Anda mencoba untuk meminta path/to/script.php?parameter=value, PHP mencari file bernama script.php?parameter=value, karena UNIX memungkinkan Anda untuk memiliki jalur seperti ini.
Jika Anda benar-benar harus lulus beberapa data script termasuk, hanya mendeklarasikan sebagai $variable=...atau $GLOBALS[]=...atau lainnya cara Anda seperti.

Paul Lynn
sumber
2

Saham Samba

Jika Anda memiliki server uji Linux dan Anda bekerja dari Klien Windows, berbagi Samba mengganggu perintah chmod . Jadi, bahkan jika Anda menggunakan:

chmod -R 777 myfolder

di sisi Linux sangat mungkin bahwa data Unix Group \ www masih tidak memiliki akses tulis. Satu solusi yang berfungsi jika bagian Anda disetel agar admin Windows dipetakan untuk di-root: Dari Windows, buka Izin, nonaktifkan Warisan untuk folder Anda dengan salinan, dan kemudian berikan akses penuh untuk data-www.

Stephan Brunker
sumber
1

Penyebab lain yang mungkin: Mengganti nama dan / atau memindahkan file saat berada di editor teks. Saya melewati semua langkah di atas tanpa berhasil sampai saya menghapus file yang terus melempar kesalahan ini dan membuat yang baru, yang memperbaiki masalah.

zMeadz
sumber
1
jika saya mengerti apa yang Anda maksud dengan benar, ini akan menjadi masalah langsung dengan cek pertama dalam daftar
Vic Seedoubleyew
# 1 tidak secara eksplisit tentang penyebab potensial
zMeadz
ya, tetapi Anda tidak peduli tentang penyebabnya, Anda peduli menemukan cara untuk memperbaiki masalah. Lebih penting lagi, langkah nomor 1 akan menyelesaikan masalah Anda
Vic Seedoubleyew