PHPスクリプトでは、呼び出したかどうかinclude()
、require()
、fopen()
、またはそれらの誘導体include_once
、require_once
または、でも、move_uploaded_file()
一つは、多くの場合、エラーや警告に実行されます。
ストリームを開けませんでした:そのようなファイルまたはディレクトリはありません。
問題の根本的な原因をすばやく見つけるための良いプロセスは何ですか?
PHPスクリプトでは、呼び出したかどうかinclude()
、require()
、fopen()
、またはそれらの誘導体include_once
、require_once
または、でも、move_uploaded_file()
一つは、多くの場合、エラーや警告に実行されます。
ストリームを開けませんでした:そのようなファイルまたはディレクトリはありません。
問題の根本的な原因をすばやく見つけるための良いプロセスは何ですか?
回答:
このエラーが発生する理由はたくさんあります。最初に何をチェックすべきかについての適切なチェックリストは、かなり役に立ちます。
次の行をトラブルシューティングしているとしましょう:
require "/path/to/file"
呼び出されているものか、移動require*
またはinclude*
独自の変数には、それをコピーして、端末からアクセスしてみてください、それをエコーします。
$path = "/path/to/file";
echo "Path : $path";
require "$path";
次に、ターミナルで:
cat <file path pasted>
/users/tony/htdocs
ベストプラクティス :
移動時に絶対パスを生成しながらスクリプトを堅牢にするために、2つのオプションがあります。
require __DIR__ . "/relative/path/from/current/file"
。__DIR__
魔法の定数は、現在のファイルのディレクトリを返します。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設定に依存しないため、アプリケーションの移植性も向上します。
比較的または完全にではなく、ファイルをインクルードする別の方法は、インクルードパスに依存することです。これは、Zendフレームワークなどのライブラリまたはフレームワークの場合によく見られます。
このような包含は次のようになります。
include "Zend/Mail/Protocol/Imap.php"
その場合、「Zend」があるフォルダーがインクルードパスの一部であることを確認する必要があります。
インクルードパスは次のようにして確認できます。
echo get_include_path();
あなたはそれにフォルダを追加することができます:
set_include_path(get_include_path().":"."/path/to/new/folder");
全体として、サーバープロセス(ApacheまたはPHP)を実行しているユーザーには、単にそのファイルの読み取りまたは書き込みの権限がない可能性があります。
サーバーが実行しているユーザーを確認するには、posix_getpwuidを使用できます。
$user = posix_getpwuid(posix_geteuid());
var_dump($user);
ファイルの権限を確認するには、ターミナルで次のコマンドを入力します。
ls -l <path/to/file>
許可の記号表記を見てください
上記のいずれも機能しない場合、問題はおそらく一部のPHP設定がそのファイルへのアクセスを禁止していることです。
3つの設定が関連する可能性があります。
phpinfo()
か、またはini_get("open_basedir")
ini_get("allow_url_include")
および設定できますini_set("allow_url_include", "1")
上記のいずれでも問題の診断が有効になっていない場合は、次のような特殊な状況が発生する可能性があります。
相対パスまたは絶対パスを使用して、ライブラリ(Zendフレームワークなど)を含める場合があります。例えば :
require "/usr/share/php/libzend-framework-php/Zend/Mail/Protocol/Imap.php"
しかし、それでも同じ種類のエラーが発生します。
これは、(正常に)インクルードしたファイル自体に別のファイルのインクルードステートメントがあり、2番目のインクルードステートメントがそのライブラリのパスをインクルードパスに追加したと想定しているために発生する可能性があります。
たとえば、前述のZendフレームワークファイルには、次のインクルードがあります。
include "Zend/Mail/Protocol/Exception.php"
これは、相対パスまたは絶対パスによる包含ではありません。Zendフレームワークディレクトリがインクルードパスに追加されていることを前提としています。
このような場合、唯一の実用的な解決策は、ディレクトリをインクルードパスに追加することです。
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を構成するためのチュートリアルです。
Symfonyを使用していて、サーバーにアップロードするときにこのエラーが発生する場合は、アップロードapp/cache
されたか、キャッシュがクリアされていないため、アプリのキャッシュがリセットされていない可能性があります。
これをテストして修正するには、次のコンソールコマンドを実行します。
cache:clear
明らかに、このエラーはzip->close()
、zip内の一部のファイルのファイル名に「é」などの非ASCII文字が含まれている場合にも、呼び出し時に発生する可能性があります。
可能な解決策はutf8_decode()
、ターゲットファイルを作成する前にファイル名をラップすることです。
クレジットフランカノ、この問題に対する解決策を特定し、示唆のために
selinux
することは良い考えかもしれません。httpd_sys_content_t
インクルードされたファイルに対する権限(Apacheで使用される読み取り専用のディレクトリとファイル)が少なくとも必要です。
(本当に良い)既存の回答に追加するには
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はしばしばapache
、www-data
またはhttpd
(サーバーによって異なります)です。cronジョブまたはCLIの実行には、それを実行しているユーザーが持つすべての権限があります(つまり、PHPスクリプトをrootとして実行すると、rootの権限で実行されます)。
多くの場合、人々は次のようにすることで許可の問題を解決します(Linuxの例)
chmod 777 /path/to/file
これは、ファイルまたはディレクトリが誰でも書き込み可能であるため、賢いアイデアではありません。サーバーを所有していて、それが唯一のユーザーである場合、これはそれほど大きな問題ではありませんが、共有ホスティング環境を使用している場合は、サーバーのすべてのユーザーにアクセス権を付与します。
あなたがする必要があるのは、アクセスを必要とするユーザーを決定し、それらのユーザーのみにアクセスを許可することです。アクセスが必要なユーザーがわかったら、次のことを確認します。
そのユーザーはファイルを所有し、場合によっては親ディレクトリー(特に、ファイルを書き込みたい場合は親ディレクトリー)を所有します。ほとんどの共有ホスティング環境では、ユーザーはルートの下にあるすべてのファイルを所有する必要があるため、これは問題になりません。Linuxの例を以下に示します
chown apache:apache /path/to/file
ユーザーは、そのユーザーのみがアクセスできます。Linuxでは、(所有者だけが読み書きできるchmod 600
)またはchmod 644
(所有者は書けますが、誰でも読むことができます)をお勧めします。
私のコードはすべてのマシンで正常に機能しましたが、このマシンでのみ問題が発生し始めました(これは以前は機能していたと思います)。デバッグに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で同じコードを実行しましたが、すべて正常に動作しました。これが誰かを助けることを願っています。
それは私の場合でした。実際には質問#4485874にリンクしていますが、ここで簡単に説明します。
を要求しようとするとpath/to/script.php?parameter=value
、script.php?parameter=value
UNIXではこのようなパスを使用できるため、PHPはという名前のファイルを探します。
含まれているスクリプトにデータを渡す必要がある場合は、そのように$variable=...
、$GLOBALS[]=...
または他の方法で宣言してください。
Sambaシェア
Linuxテストサーバーがあり、Windowsクライアントから作業している場合、Samba共有がchmodコマンドを妨害します。だから、たとえあなたが使ったとしても:
chmod -R 777 myfolder
Linux側では、Unix Group \ www-dataにまだ書き込みアクセス権がない可能性があります。Windows管理者がルートにマップされるように共有が設定されている場合の1つの有効なソリューション:Windowsから、[アクセス許可]を開き、コピーを使用してフォルダーの継承を無効にしてから、www-dataにフルアクセスを許可します。
別の考えられる原因:テキストエディターでファイルの名前を変更または移動します。このエラーをスローし続けるファイルを削除して新しいファイルを作成するまで、上記のすべての手順を成功させずに問題を修正しました。