Dalam skrip PHP, sama ada anda memanggil include()
, require()
, fopen()
atau kelas terbitannya, seperti include_once
, require_once
, atau malah move_uploaded_file()
, anda akan sering menghadapi ralat atau amaran: < /p>
Tidak dapat membuka strim: Tiada fail atau direktori sedemikian.
Apakah proses yang baik untuk mencari punca masalah dengan cepat?
Ditambah pada (sangat baik) jawapan sedia ada
Perisian Pengehosan Dikongsi
open_basedir
可能会难倒您,因为它可以在 Web 服务器配置中指定。虽然如果您运行自己的专用服务器,这很容易解决,但有一些共享托管软件包(如 Plesk、cPanel 等)可以在每个域的基础上配置配置指令。由于该软件会构建配置文件(即httpd.conf
), jadi anda tidak boleh menukar fail itu secara langsung kerana perisian pengehosan hanya akan menimpanya semasa but semula.Dengan Plesk, mereka menyediakan lokasi untuk menampung apa yang mereka tawarkan
httpd.conf
(称为vhost.conf
). Hanya pentadbir pelayan boleh menulis ke fail ini. Konfigurasi Apache kelihatan seperti iniMinta pentadbir pelayan anda untuk merujuk manual untuk perisian pengehosan dan pelayan web yang mereka gunakan.
Kebenaran Fail
Adalah penting untuk ambil perhatian bahawa melaksanakan fail melalui pelayan web adalah sangat berbeza daripada baris arahan atau pelaksanaan tugas cron. Perbezaan terbesar ialah pelayan web anda mempunyai pengguna dan kebenarannya sendiri. Pengguna ini sangat dihadkan atas sebab keselamatan. Contohnya, Apache biasanya
apache
、www-data
或httpd
(bergantung pada pelayan anda). Tugas cron atau pelaksanaan CLI mempunyai apa sahaja kebenaran yang dimiliki oleh pengguna yang menjalankannya (iaitu skrip PHP yang dijalankan sebagai root akan dilaksanakan dengan kebenaran root).Banyak kali orang menyelesaikan masalah kebenaran dengan melakukan perkara berikut (contoh Linux)
Ini bukan idea yang bijak kerana fail atau direktori kini boleh ditulis secara global. Jika anda memiliki pelayan dan merupakan satu-satunya pengguna, ini bukan masalah besar, tetapi jika anda berada dalam persekitaran pengehosan yang dikongsi, anda memberikan akses kepada semua orang pada pelayan.
Apa yang anda perlu lakukan ialah mengenal pasti pengguna yang memerlukan akses dan berikan akses kepada mereka sahaja. Sebaik sahaja anda mengetahui pengguna mana yang memerlukan akses, anda perlu memastikan
Pengguna ini memiliki faildan berkemungkinan memiliki direktori induk(terutamanya direktori induk jika anda menulis ke fail). Dalam kebanyakan persekitaran pengehosan yang dikongsi ini tidak akan menjadi masalah kerana pengguna anda harus memiliki semua fail dalam direktori akar. Contoh Linux ditunjukkan di bawah
Pengguna ini (dan hanya pengguna ini) mempunyai akses. Dalam Linux, amalan yang baik ialah
chmod 600
(只有所有者可以读写)或chmod 644
(pemilik boleh menulis, tetapi semua orang boleh membaca)Anda bolehmembaca perbincangan yang lebih luas tentang Kebenaran dan Pengguna Linux/Unix di sini
Terdapat banyak sebab mengapa anda mungkin menghadapi ralat ini, jadi senarai semak yang baik tentang perkara yang perlu diperiksa dahulu boleh membantu.
Andaikan kami sedang menyelesaikan masalah baris berikut:
Senarai semak
1. Semak laluan fail untuk kesilapan menaip
Atau alihkan apa sahaja panggilan
require*
或include*
ke dalam pembolehubahnya sendiri, gemakannya, salinnya dan cuba aksesnya dari terminal:Kemudian, di terminal:
2. Semak sama ada laluan fail bagi pertimbangan laluan relatif dan mutlak adalah betul
/users/tony/htdocs
Jadi ia tiada kaitan dengan laluan ke akar laman web atau laluan ke fail yang anda taip Jadi sentiasa gunakan laluan fail mutlak
Gunakan- pemalar ajaib
- Tentukan sendiri
require __DIR__ 。 “/相对/路径/来自/当前/文件”
。__DIR__
untuk mengembalikan direktori fail semasa.malar:
SITE_ROOT
Buat fail dalam akar direktori tapak web, contohnya
- Tulis
- Dalam setiap fail yang anda ingin rujuk folder akar tapak, masukkan
config.php
dalam
config.php
, kemudian gunakan pemalar
config.php
,然后在任意位置使用SITE_ROOT
di mana-mana sahaja: p>2 amalan ini juga menjadikan aplikasi anda lebih mudah alih kerana ia tidak bergantung pada tetapan ini seperti laluan sertakan.
3. Semak laluan sertakan anda
Cara lain untuk memasukkan fail, yang bukan relatif atau mutlak semata-mata, adalah dengan bergantung pada laluanserta. Ini selalunya berlaku dengan perpustakaan atau rangka kerja seperti Rangka Kerja Zend.
Pemasukan sedemikian akan kelihatan seperti ini:
Dalam kes ini, anda perlu memastikan bahawa folder tempat "Zend" terletak adalah sebahagian daripada laluan sertakan.
Anda boleh menyemak laluan sertakan menggunakan arahan berikut:
Anda boleh menambah folder padanya menggunakan arahan berikut:
4. Semak sama ada pelayan anda mempunyai akses kepada fail
Untuk meringkaskan, pengguna yang menjalankan proses pelayan (Apache atau PHP) mungkin tidak mempunyai kebenaran untuk membaca atau menulis fail sama sekali.
Untuk menyemak pengguna mana pelayan sedang berjalan, anda boleh menggunakanposix_getpwuid:
Untuk mencari kebenaran fail, taip arahan berikut dalam terminal:
Dan lihatnotasi kebenaran
5. Semak tetapan PHP
Jika tiada kaedah di atas berfungsi, masalahnya mungkin beberapa tetapan PHP menghalangnya daripada mengakses fail.
Tiga tetapan mungkin berkaitan:
phpinfo()
phpinfo()
进行检查>或使用ini_get("open_basedir")
atau menggunakanini_get("open_basedir")
ini_get("allow_url_include")
检查并使用ini_set("allow_url_include", "1")
TetapanSituasi melampau
Jika tiada kaedah di atas dapat mendiagnosis masalah, beberapa situasi khas berikut mungkin berlaku:
1. Kemasukan perpustakaan yang bergantung pada termasuk laluan
Anda mungkin menyertakan perpustakaan, seperti rangka kerja Zend, menggunakan laluan relatif atau mutlak. Contohnya:
Tetapi anda masih akan menghadapi jenis ralat yang sama.
Ini berlaku kerana fail yang anda (berjaya) sertakan sendiri mempunyai pernyataan include daripada fail lain, dan pernyataan include kedua menganggap bahawa anda telah menambahkan laluan ke pustaka ke laluan include.
Sebagai contoh, fail rangka kerja Zend yang dinyatakan sebelum ini mungkin mengandungi perkara berikut:
Tidak disertakan melalui laluan relatif atau disertakan melalui laluan mutlak. Diandaikan bahawa direktori rangka kerja Zend telah ditambahkan pada laluan termasuk.
Dalam kes ini, satu-satunya penyelesaian praktikal ialah menambah direktori pada laluan sertakan.
2. SELinux
Jika anda menjalankan Linux yang dipertingkatkan keselamatan, maka ini mungkin punca masalah, kerana akses kepada fail daripada pelayan dinafikan.
Untuk menyemak sama ada SELinux didayakan pada sistem anda, jalankan arahan
sestatus
dalam terminal. Jika arahan ini tidak wujud, SELinux tidak wujud pada sistem anda. Jika ia wujud, maka ia harus memberitahu anda sama ada ia dikuatkuasakan.Untuk menyemak sama ada polisi SELinux adalah punca masalah, anda boleh cuba mematikannya buat sementara waktu. Tetapi berhati-hati kerana ini akan melumpuhkan perlindungan sepenuhnya. Jangan lakukan ini pada pelayan pengeluaran.
Jika anda tidak lagi menghadapi masalah selepas mematikan SELinux, maka inilah puncanya.
Untuk menyelesaikan isu ini, anda mesti mengkonfigurasi SELinux dengan sewajarnya.
Jenis konteks berikut diperlukan:
httpd_sys_content_t
untuk fail yang anda mahu pelayan boleh membacahttpd_sys_rw_content_t
untuk fail yang anda mahu akses baca dan tulishttpd_log_t
untuk fail loghttpd_cache_t
untuk direktori cacheSebagai contoh, untuk menetapkan jenis konteks
httpd_sys_content_t
kepada akar tapak web anda, jalankan:Jika fail anda terletak dalam direktori rumah anda, anda juga perlu membuka
httpd_enable_homedirs
Boolean:Apapun, mungkin terdapat beberapa sebab mengapa SELinux menafikan akses kepada fail, bergantung pada strategi anda. Jadi anda perlu menyiasat perkara ini.Di siniialah tutorial khusus untuk mengkonfigurasi SELinux untuk pelayan web anda.
3. Simfoni
Jika anda menggunakan Symfony dan anda menghadapi ralat ini semasa memuat naik ke pelayan, mungkin cache apl anda belum ditetapkan semula sejak
app/cache
telah dimuat naik atau cache belum dikosongkan lagi.Anda boleh menguji dan membetulkan isu ini dengan menjalankan arahan konsol berikut:
4. Aksara bukan ACSII dalam fail Zip
Nampaknya ralat ini juga berlaku semasa memanggil
zip->close()
apabila beberapa fail dalam zip mengandungi aksara bukan ASCII (cth. "é") dalam nama failnya.Penyelesaian yang mungkin adalah dengan membungkus nama fail dalam
utf8_decode()
sebelum mencipta fail sasaran.Terima kasih kepadaFran Canokerana mengenal pasti isu ini dan mencadangkan penyelesaian