cari

Rumah  >  Soal Jawab  >  teks badan

PHP - tidak boleh membuka strim: Tiada fail atau direktori sedemikian

<p>Dalam skrip PHP, sama ada anda memanggil <code>include()</code>, <code>require()</code>, <code>fopen()</code> atau kelas terbitannya, seperti <code> include_once</code>, <code>require_once</code>, atau malah <code>move_uploaded_file()</code>, anda akan sering menghadapi ralat atau amaran: < /p> <blockquote> <p>Tidak dapat membuka strim: Tiada fail atau direktori sedemikian. </p> </blockquote> <p>Apakah proses yang baik untuk mencari punca masalah dengan cepat? </p>
P粉145543872P粉145543872461 hari yang lalu589

membalas semua(2)saya akan balas

  • P粉362071992

    P粉3620719922023-08-24 12:18:48

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

    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 biasanya apachewww-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 fail dan 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 ialah chmod 600(只有所有者可以读写)或 chmod 644 (pemilik boleh menulis, tetapi semua orang boleh membaca)

    Anda boleh membaca perbincangan yang lebih luas tentang Kebenaran dan Pengguna Linux/Unix di sini

    balas
    0
  • P粉268654873

    P粉2686548732023-08-24 00:48:10

    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 panggilan require*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 <file path pasted>


    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

        dalam config.php

        define('SITE_ROOT', __DIR__);

      • Dalam setiap fail yang anda ingin rujuk folder akar tapak, masukkan

        , kemudian gunakan pemalar config.php,然后在任意位置使用 SITE_ROOT di mana-mana sahaja:

        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 laluan serta. 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 menggunakan posix_getpwuid< /一>:

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

    Untuk mencari kebenaran fail, taip arahan berikut dalam terminal:

    ls -l <path/to/file>

    Dan lihat notasi 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 menghubungi phpinfo()phpinfo() 或使用 ini_get("open_basedir") atau menggunakan ini_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 yang masih 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 menggunakan ini_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 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.

    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_t untuk fail yang anda mahu pelayan boleh membaca
    • httpd_sys_rw_content_t untuk fail yang anda mahu akses baca dan tulis
    • httpd_log_t untuk fail log
    • httpd_cache_t untuk direktori cache

    Sebagai contoh, untuk menetapkan jenis konteks httpd_sys_content_t kepada 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 membuka httpd_enable_homedirs Boolean:

    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 sini ialah 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:

    cache:clear


    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 kepada Fran Cano kerana mengenal pasti isu ini dan mencadangkan penyelesaian< /p>

    balas
    0
  • Batalbalas