PHP - tidak boleh membuka strim: Tiada fail atau direktori sedemikian
P粉145543872
P粉145543872 2023-08-23 16:30:33
0
2
485

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?

P粉145543872
P粉145543872

membalas semua (2)
P粉362071992

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 tawarkanhttpd.conf(称为vhost.conf). Hanya pentadbir pelayan boleh menulis ke fail ini. Konfigurasi Apache kelihatan seperti ini

  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"  

Minta 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 biasanyaapachewww-datahttpd(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)

chmod 777 /path/to/file

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

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

    chown apache:apache /path/to/file
  2. Pengguna ini (dan hanya pengguna ini) mempunyai akses. Dalam Linux, amalan yang baik ialahchmod 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

    P粉268654873

    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:

    require "/path/to/file"


    Senarai semak


    1. Semak laluan fail untuk kesilapan menaip

    • Pemeriksaan manual (dengan memeriksa laluan secara visual)
    • Atau alihkan apa sahaja panggilanrequire*include*ke dalam pembolehubahnya sendiri, gemakannya, salinnya dan cuba aksesnya dari terminal:

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

      Kemudian, di terminal:

      cat 


    2. Semak sama ada laluan fail bagi pertimbangan laluan relatif dan mutlak adalah betul

    Amalan Terbaik:

    Untuk menjadikan skrip anda mantap apabila memindahkan kandungan sambil masih menjana laluan mutlak pada masa jalanan, anda mempunyai 2 pilihan:

      Gunakan
    1. pemalar ajaibrequire __DIR__ 。 “/相对/路径/来自/当前/文件”__DIR__untuk mengembalikan direktori fail semasa.
    2. Tentukan sendiri

      malar:SITE_ROOT

        Buat fail dalam akar direktori tapak web, contohnya
      • config.php
      • Tulis

        dalamconfig.php

        define('SITE_ROOT', __DIR__);
      • Dalam setiap fail yang anda ingin rujuk folder akar tapak, masukkan

        , kemudian gunakan pemalarconfig.php,然后在任意位置使用SITE_ROOTdi mana-mana sahaja: p>

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

    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:

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

    Dalam kes ini, anda perlu memastikan bahawa folder tempat "Zend" terletak adalah sebahagian daripada laluan sertakan.

    Anda boleh menyemak laluan sertakan menggunakan arahan berikut:

    echo get_include_path();

    Anda boleh menambah folder padanya menggunakan arahan berikut:

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


    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:

    $user = posix_getpwuid(posix_geteuid()); var_dump($user);

    Untuk mencari kebenaran fail, taip arahan berikut dalam terminal:

    ls -l 

    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:

    1. open_basedir
      • Jika ini ditetapkan, PHP tidak akan dapat mengakses mana-mana fail di luar direktori yang ditentukan (walaupun melalui pautan simbolik).
      • Walau bagaimanapun, tingkah laku lalai adalah untuk tidak menetapkannya, dalam hal ini tiada had
      • Boleh disemak dengan menghubungiphpinfo()phpinfo()进行检查>或使用ini_get("open_basedir")atau menggunakanini_get("open_basedir")
      • Anda boleh menukar tetapan dengan mengedit fail php.ini atau fail httpd.conf
    2. Mod Selamat
      • Ciri ini mungkin dihadkan jika didayakan. Walau bagaimanapun, ini telah dialih keluar dalam PHP 5.4. Jika anda masih menggunakan versi yang menyokong mod selamat, sila tingkatkan kepada versi PHP yangmasih disokong.
    3. izinkan_url_fopen dan izinkan_url_include
      • Ini hanya berfungsi apabila menyertakan atau membuka fail melalui proses rangkaian (cth. http://), bukan semasa cuba memasukkan fail pada sistem fail setempat anda
      • Boleh set menggunakanini_get("allow_url_include")检查并使用ini_set("allow_url_include", "1")Tetapan


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

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

    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:

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

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

    setenforce 0

    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_tuntuk fail yang anda mahu pelayan boleh membaca
    • httpd_sys_rw_content_tuntuk fail yang anda mahu akses baca dan tulis
    • httpd_log_tuntuk fail log
    • httpd_cache_tuntuk direktori cache

    Sebagai contoh, untuk menetapkan jenis kontekshttpd_sys_content_tkepada akar tapak web anda, jalankan:

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

    Jika fail anda terletak dalam direktori rumah anda, anda juga perlu membukahttpd_enable_homedirsBoolean:

    setsebool -P httpd_enable_homedirs 1

    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 sejakapp/cachetelah dimuat naik atau cache belum dikosongkan lagi.

    Anda boleh menguji dan membetulkan isu ini dengan menjalankan arahan konsol berikut:

    cache:clear


    4. Aksara bukan ACSII dalam fail Zip

    Nampaknya ralat ini juga berlaku semasa memanggilzip->close()apabila beberapa fail dalam zip mengandungi aksara bukan ASCII (cth. "é") dalam nama failnya.

    Penyelesaian yang mungkin adalah dengan membungkus nama fail dalamutf8_decode()sebelum mencipta fail sasaran.

    Terima kasih kepadaFran Canokerana mengenal pasti isu ini dan mencadangkan penyelesaian

      Muat turun terkini
      Lagi>
      kesan web
      Kod sumber laman web
      Bahan laman web
      Templat hujung hadapan
      Tentang kita Penafian Sitemap
      Laman web PHP Cina:Latihan PHP dalam talian kebajikan awam,Bantu pelajar PHP berkembang dengan cepat!