PHP-ストリームを開けませんでした:そのようなファイルまたはディレクトリはありません


166

PHPスクリプトでは、呼び出したかどうかinclude()require()fopen()、またはそれらの誘導体include_oncerequire_onceまたは、でも、move_uploaded_file()一つは、多くの場合、エラーや警告に実行されます。

ストリームを開けませんでした:そのようなファイルまたはディレクトリはありません。

問題の根本的な原因をすばやく見つけるための良いプロセスは何ですか?


5
この投稿のトピック外のコメントを整理しました。メタディスカッションはメタに保管してください。ただし、標準的な質問の実行可能性についての議論は何度も何度も行われていることに注意してください。こちらの例をご覧ください
マダラのゴースト

1
同じ問題が発生しましたが、常に機能する唯一の解決策は次のとおりです:-1含めるファイルに移動し、右ボタン、プロパティ、完全なパスをコピーします。 2-含めます。実際、私はこの質問が答えられ、答えが検証されているのを見ましたが、私にとっては、上記の方法が見つかるまでうまくいかない場合がありました。
Rshad

@Rash貢献に感謝します。残念ながら、絶対パス名について言及するため、ソリューションは間違っています。これが間違っている理由は、プロジェクトを別の場所にコピーしたり、コンピューター内に移動したりすると、すべてが壊れるからです。
Vic Seedoubleyew 2018年

回答:


259

このエラーが発生する理由はたくさんあります。最初に何をチェックすべきかについての適切なチェックリストは、かなり役に立ちます。

次の行をトラブルシューティングしているとしましょう:

require "/path/to/file"


チェックリスト


1.タイプミスがないかファイルパスを確認します

  • 手動でチェックする(パスを視覚的にチェックする)
  • 呼び出されているものか、移動require*またはinclude*独自の変数には、それをコピーして、端末からアクセスしてみてください、それをエコーします。

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

    次に、ターミナルで:

    cat <file path pasted>


2.相対パスと絶対パスの考慮事項に関して、ファイルパスが正しいことを確認します

  • スラッシュ「/」で始まっている場合は、Webサイトのフォルダーのルート(ドキュメントルート)ではなく、サーバーのルートを指します。
    • たとえば、あなたのウェブサイトのディレクトリは /users/tony/htdocs
  • スラッシュで始まっていない場合は、インクルードパス(以下を参照)に依存しているか、パスが相対パスです。相対パスの場合、PHPは現在の作業ディレクトリのパスに対して相対的に計算します。
    • したがって、Webサイトのルートのパスや、入力しているファイルへの相対パスではありません
    • そのため、常に絶対ファイルパスを使用してください

ベストプラクティス :

移動時に絶対パスを生成しながらスクリプトを堅牢にするために、2つのオプションがあります。

  1. 使用しますrequire __DIR__ . "/relative/path/from/current/file"__DIR__魔法の定数は、現在のファイルのディレクトリを返します。
  2. SITE_ROOT定数を自分で定義する:

    • ウェブサイトのディレクトリのルートで、ファイルを作成します、例えば config.php
    • config.php、書く

      define('SITE_ROOT', __DIR__);
    • サイトのルートフォルダーを参照するすべてのファイルにを含めてconfig.phpから、SITE_ROOT定数を好きな場所で使用します。

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

これらの2つの方法は、インクルードパスなどのini設定に依存しないため、アプリケーションの移植性も向上します。


3.インクルードパスを確認する

比較的または完全にではなく、ファイルをインクルードする別の方法は、インクルードパスに依存することです。これは、Zendフレームワークなどのライブラリまたはフレームワークの場合によく見られます。

このような包含は次のようになります。

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

その場合、「Zend」があるフォルダーがインクルードパスの一部であることを確認する必要があります。

インクルードパスは次のようにして確認できます。

echo get_include_path();

あなたはそれにフォルダを追加することができます:

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


4.サーバーがそのファイルにアクセスできることを確認します

全体として、サーバープロセス(ApacheまたはPHP)を実行しているユーザーには、単にそのファイルの読み取りまたは書き込みの権限がない可能性があります。

サーバーが実行しているユーザーを確認するには、posix_getpwuidを使用できます。

$user = posix_getpwuid(posix_geteuid());

var_dump($user);

ファイルの権限を確認するには、ターミナルで次のコマンドを入力します。

ls -l <path/to/file>

許可の記号表記を見てください


5. PHP設定を確認する

上記のいずれも機能しない場合、問題はおそらく一部のPHP設定がそのファイルへのアクセスを禁止していることです。

3つの設定が関連する可能性があります。

  1. open_basedir
    • これが設定されている場合、PHPは(シンボリックリンクを介しても)指定されたディレクトリの外部のファイルにアクセスできません。
    • ただし、デフォルトの動作では設定されないため、制限はありません。
    • これは、を呼び出すphpinfo()か、またはini_get("open_basedir")
    • php.iniファイルまたはhttpd.confファイルを編集することにより、設定を変更できます
  2. セーフモード
    • これがオンになっている場合、制限が適用される可能性があります。ただし、これはPHP 5.4で削除されました。あなたはサポートセーフモードがされたPHPのバージョンにアップグレードすることをバージョンに残っている場合は、引き続きサポートされています
  3. allow_url_fopenおよびallow_url_include
    • これは、http://などのネットワークプロセスを介してファイルをインクルードまたはオープンする場合にのみ適用され、ローカルファイルシステムにファイルをインクルードしようとするときは適用されません。
    • これはで確認ini_get("allow_url_include")および設定できますini_set("allow_url_include", "1")


コーナーケース

上記のいずれでも問題の診断が有効になっていない場合は、次のような特殊な状況が発生する可能性があります。


1.インクルードパスに依存するライブラリを含める

相対パスまたは絶対パスを使用して、ライブラリ(Zendフレームワークなど)を含める場合があります。例えば ​​:

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

しかし、それでも同じ種類のエラーが発生します。

これは、(正常に)インクルードしたファイル自体に別のファイルのインクルードステートメントがあり、2番目のインクルードステートメントがそのライブラリのパスをインクルードパスに追加したと想定しているために発生する可能性があります。

たとえば、前述のZendフレームワークファイルには、次のインクルードがあります。

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

これは、相対パスまたは絶対パスによる包含ではありません。Zendフレームワークディレクトリがインクルードパスに追加されていることを前提としています。

このような場合、唯一の実用的な解決策は、ディレクトリをインクルードパスに追加することです。


2. SELinux

Security-Enhanced Linuxを実行している場合は、サーバーからのファイルへのアクセスを拒否することが問題の原因である可能性があります。

システムでSELinuxが有効になっているかどうかを確認するにsestatusは、ターミナルでコマンドを実行します。コマンドが存在しない場合、SELinuxはシステム上にありません。存在する場合は、強制されているかどうかが示されます。

SELinuxポリシーが問題の原因であるかどうかを確認するには、一時的にオフにしてみてください。ただし、保護が完全に無効になるため、注意が必要です。本番サーバーではこれを行わないでください。

setenforce 0

SELinuxをオフにしても問題が発生しなくなった場合は、これが根本的な原因です。

これを解決するにはそれに応じてSELinuxを設定する必要があります。

次のコンテキストタイプが必要です。

  • httpd_sys_content_t サーバーが読み取れるようにするファイル
  • httpd_sys_rw_content_t 読み取りおよび書き込みアクセスが必要なファイル
  • httpd_log_t ログファイル用
  • httpd_cache_t キャッシュディレクトリ

たとえば、httpd_sys_content_tコンテキストタイプをウェブサイトのルートディレクトリに割り当てるには、次のコマンドを実行します。

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

ファイルがホームディレクトリにある場合は、httpd_enable_homedirsブール値もオンにする必要があります。

setsebool -P httpd_enable_homedirs 1

いずれの場合も、ポリシーによっては、SELinuxがファイルへのアクセスを拒否するさまざまな理由が考えられます。だからあなたはそれを調査する必要があります。以下は、特にWebサーバー用にSELinuxを構成するためのチュートリアルです。


3. symfony

Symfonyを使用していて、サーバーにアップロードするときにこのエラーが発生する場合は、アップロードapp/cacheされたか、キャッシュがクリアされていないため、アプリのキャッシュがリセットされていない可能性があります。

これをテストして修正するには、次のコンソールコマンドを実行します。

cache:clear


4. Zipファイル内のACSII以外の文字

明らかに、このエラーはzip->close()、zip内の一部のファイルのファイル名に「é」などの非ASCII文字が含まれている場合にも、呼び出し時に発生する可能性があります。

可能な解決策はutf8_decode()、ターゲットファイルを作成する前にファイル名をラップすることです。

クレジットフランカノ、この問題に対する解決策を特定し、示唆のために


4
ここで言及selinuxすることは良い考えかもしれません。httpd_sys_content_tインクルードされたファイルに対する権限(Apacheで使用される読み取り専用のディレクトリとファイル)が少なくとも必要です。
bansi

提案をありがとうございました。私はSELinuxに慣れていないので、少し読んでこのケースに答えようとしました。正しくない場合は、フィードバックを送信するか、一部の編集を提案してください。コメントありがとうございます!
Vic Seedoubleyew 16

chcon一時的なものでありrestorecon、再起動後は存続しません。semanageファイルのコンテキストを変更するために使用する必要がある場合があります。これがWebサイトの
bansi

追加する別の可能性:realpathキャッシング:lyte.id.au/2014/05/01/what-the-hell-php
chrishiestand

@chrishiestandありがとうございます!その記事は本当に面白いです!そのエラーの原因となったイベントの経過を覚えていますか?最初はユーザーがファイルへの読み取りアクセス権を持っていなかったのに変更されましたが、キャッシュはまだ読み取り可能ではないと見なしていたため、ファイルを開くとエラーが発生しましたか?
Vic Seedoubleyew 2018年

16

(本当に良い)既存の回答に追加するには

共有ホスティングソフトウェア

open_basedirこれは、Webサーバー構成で指定できるため、困惑する可能性があります。これは、独自の専用サーバーを実行すれば簡単に修正できますが、ドメインごとに構成ディレクティブを構成する共有ホスティングソフトウェアパッケージ(Plesk、cPanelなど)がいくつかあります。ソフトウェアが構成ファイル(つまりhttpd.conf)を構築するため、ホスティングソフトウェアは再起動時に上書きするだけなので、そのファイルを直接変更することはできません。

Pleskのでは、彼らが提供するオーバーライドする場所を提供httpd.conf呼ばれるがvhost.conf。サーバー管理者のみがこのファイルを書き込むことができます。Apacheの設定は次のようになります

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

サーバー管理者に、使用しているホスティングおよびWebサーバーソフトウェアのマニュアルを参照してもらいます。

ファイルのアクセス許可

Webサーバーを介したファイルの実行は、コマンドラインやcronジョブの実行とは非常に異なることに注意することが重要です。大きな違いは、Webサーバーには独自のユーザーと権限があることです。セキュリティ上の理由から、ユーザーはかなり制限されています。たとえば、Apacheはしばしばapachewww-dataまたはhttpd(サーバーによって異なります)です。cronジョブまたはCLIの実行には、それを実行しているユーザーが持つすべての権限があります(つまり、PHPスクリプトをrootとして実行すると、rootの権限で実行されます)。

多くの場合、人々は次のようにすることで許可の問題を解決します(Linuxの例)

chmod 777 /path/to/file

これは、ファイルまたはディレクトリが誰でも書き込み可能であるため、賢いアイデアではありません。サーバーを所有していて、それが唯一のユーザーである場合、これはそれほど大きな問題ではありませんが、共有ホスティング環境を使用している場合は、サーバーのすべてのユーザーにアクセス権を付与します。

あなたがする必要があるのは、アクセスを必要とするユーザーを決定し、それらのユーザーのみにアクセスを許可することです。アクセスが必要なユーザーがわかったら、次のことを確認します。

  1. そのユーザーはファイル所有し、場合によっては親ディレクトリー(特に、ファイルを書き込みたい場合は親ディレクトリー)を所有します。ほとんどの共有ホスティング環境では、ユーザーはルートの下にあるすべてのファイルを所有する必要があるため、これは問題になりません。Linuxの例を以下に示します

     chown apache:apache /path/to/file
  2. ユーザーは、そのユーザーのみがアクセスできます。Linuxでは、(所有者だけが読み書きできるchmod 600)またはchmod 644(所有者は書けますが、誰でも読むことができます)をお勧めします。

あなたはできるのLinux / Unixの権限とユーザーのより拡張された議論をここで読みます


7
  1. 正確なエラーを見てください

私のコードはすべてのマシンで正常に機能しましたが、このマシンでのみ問題が発生し始めました(これは以前は機能していたと思います)。デバッグにecho "document_root"パスを使用し、エラーを詳しく調べたところ、これが見つかりました

警告:include(D:/MyProjects/testproject//functions/connections.php):ストリームを開けませんでした:

問題がどこにあるかを簡単に確認できます。問題は//関数の前です

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

したがって、インクルード/をインクルードから削除するだけで正常に動作します。興味深いのは、この動作がバージョンによって異なることです。私はラップトップ、Macbook Pro、このPCで同じコードを実行しましたが、すべて正常に動作しました。これが誰かを助けることを願っています。

  1. ブラウザでファイルの場所をコピーして、ファイルが存在することを確認します。ときどきファイルが予期せず削除されて(私と一緒に起こった)、それは私の場合も問題でした。

以下のチェックリストのステップ1とどう違うのですか?
Vic Seedoubleyew 2018

ステップ2ステップ1に関連しない追加のチェック。ブラウザーで提案されたパスに移動し、そこにファイルが表示されるかどうかを確認します(Windowsエクスプローラーではなくブラウザーで)。
Hammad Khan 2018

2

クエリパラメータを含むスクリプトを追加する

それは私の場合でした。実際には質問#4485874にリンクしていますが、ここで簡単に説明します。
を要求しようとするとpath/to/script.php?parameter=valuescript.php?parameter=valueUNIXではこのようなパスを使用できるため、PHPはという名前のファイルを探します。
含まれているスクリプトにデータを渡す必要がある場合は、そのように$variable=...$GLOBALS[]=...または他の方法で宣言してください。


2

Sambaシェア

Linuxテストサーバーがあり、Windowsクライアントから作業している場合、Samba共有がchmodコマンドを妨害します。だから、たとえあなたが使ったとしても:

chmod -R 777 myfolder

Linux側では、Unix Group \ www-dataにまだ書き込みアクセス権がない可能性があります。Windows管理者がルートにマップされるように共有が設定されている場合の1つの有効なソリューション:Windowsから、[アクセス許可]を開き、コピーを使用してフォルダーの継承を無効にしてから、www-dataにフルアクセスを許可します。


1

別の考えられる原因:テキストエディターでファイルの名前を変更または移動します。このエラーをスローし続けるファイルを削除して新しいファイルを作成するまで、上記のすべての手順を成功させずに問題を修正しました。


1
私があなたの正確な意味を理解していれば、これはリストの最初のチェックで即座にトラブルシューティングされたでしょう
Vic Seedoubleyew

#1は潜在的な原因について明確ではありません
zMeadz 2018年

はい、しかし原因は気にせず、問題を修正する方法を見つけることを気にします。さらに重要なのは、ステップ番号1はあなたの問題を解決しているだろう
ヴィックSeedoubleyew
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.