web-dev-qa-db-ja.com

共有ホスティング環境のsys_get_temp_dir

注:これはスーパーユーザーにも当てはまる可能性があります。

各ユーザーが別のユーザーのファイルを表示または変更できないように、Apache2 mpmitkおよびopen_basedirを使用して共有ホストにPHP 5.3.10を設定しています。Apache2vhost設定で、ユーザーを制限するために適切なエントリを追加します。

_    AssignUserId     userA userA
    php_admin_value  open_basedir      /home/userA/www/
    php_admin_value  upload_tmp_dir    /home/userA/www/tmp/
    php_admin_value  session.save_path /home/userA/www/tmp/
    SetEnv           TMPDIR            /home/userA/www/tmp/
_

ここで、最初の行はLinuxユーザーをApache2に使用するように設定し、次の3行は、basedir、アップロードディレクトリ、およびセッションの保存パスをユーザーディレクトリに定義します。すぐに最後の行に戻ります。

ここで問題が発生しました。sys_get_temp_dir()はphpの一時ディレクトリを返す必要があります。これは、Linuxシステムではデフォルトの/ tmpです。セキュリティ上の理由から、このディレクトリはuserAのopen_basedirに存在する必要があります。 5.3.10のphp-sourceによると、sys_get_temp_dir()- functionは環境変数TMPDIRを使用してこのディレクトリを取得します。

_     // php-src/main/php_open_temporary_file.c:217-219
     /* On Unix use the (usual) TMPDIR environment variable. */
     {
             char* s = getenv("TMPDIR");
_

これは、上記の構成の5行目で実行する必要があることです。ただし、sys_get_temp_dir()は、環境変数($ _SERVERで完全に設定され、phpinfo()でも表示可能)を無視して、単にグローバルシステムディレクトリを返します。

そのディレクトリは_open_basedir_設定の外にあるため、これにより、sys_get_temp_dir()に依存するさまざまなソフトウェアでいくつかの厄介なバグが発生します。動作を変更せずに、変数を$ _ENVと$ _SERVERに直接設定しようとしました。 putenv('TMPDIR=/home/userA/www/tmp')を変更せずに試しました。

ただし、変数を/ etc/Apache2/envvarsに定義することで出力を変更できます。これは、各VHOSTに独自の一時フォルダーを持たせたいので、私には役に立ちません。

私がこれまでに見つけた唯一の解決策は、 runkit のような拡張機能を介して内部sys_get_temp_dir()を上書きし、 auto_prepend_file を介してその包含を強制することです。しかし、その解決策はとても汚いので、私は信じられません。これ以上の解決策はありません。

それで、私の質問:runkitで関数を再実装せずに、Apache2仮想ホスト設定で設定されるsys_get_temp_dir()の結果を変更する方法はありますか?

編集:Apacheのバージョンは2.2.22で、現在mod_phpを使用しています。すべてのユーザーを手動で追加する必要があるため、fcgiまたは同様のセットアップも可能です。

21
Lars

putenv('TMPDIR=/foo/bar')insidePHPを実行すると、sys_get_temp_dir()。_auto_prepend_file_ディレクティブを配置して、PHPの一部を実行し、TMPDIRを設定し、sys_get_temp_dir()

編集:また、putenv('TMPDIR='.ini_get('open_basedir').'/tmp')を使用して、一時ディレクトリを質問でレイアウトしたディレクトリ構造に簡単に設定できます。

おかしなことに、これも機能することがわかりました(Apache構成で_SetEnv TMPDIR /foo/bar_を保持している場合):

_putenv('TMPDIR='.getenv('TMPDIR'));
_

何もしないように見えますが、実際にはsys_get_temp_dir()に影響を及ぼします。私はこれがPHPの環境処理のバグであるに違いないと思い始めています。

23
lanzz

あなたはあなたの質問にタグを付けました cgi 、しかしあなたは利用しています

_ php_admin_value  open_basedir      /home/userA/www/
 ^^^^^^^^^^^^^^^
_

これは、PHPのApacheモジュールバージョンの設定ですMod_PHP。その場合、Webサーバーが起動するとPHPがロードされます。

次に、 SetEnv を利用します。

_ SetEnv           TMPDIR            /home/userA/www/tmp/
_

これは、内部環境変数を設定しています。他のApacheモジュールに渡されますが、仮想サーバーではなく、リクエストで必要になると思います。具体的にはわかりませんが、あなたの説明によれば、この環境変数はPHPスクリプトが呼び出される前にリセットされていると思います。

実際の答えよりもコメントの方が多いのですが、うまくいけば、いくつかのことを明確にするのに役立ちます。

私は通常、マルチユーザー環境でFCGIを使用して、ユーザーをより適切に分離できるようにしています。ユーザーごとに環境変数を設定することに問題はありませんでした。しかし、それは別のコメントです。あなたもそれを使わなければならないとは言いたくありません。スクリプトの実行時に(まだ)設定されるように環境変数を設定するには、Apache内の適切な場所を見つける必要があることを強調するだけです。


また、適切な環境変数を設定していない可能性があります。 環境変数に関するApacheドキュメント によると:

これらの変数は環境変数と呼ばれますが、基盤となるオペレーティングシステムによって制御される環境変数と同じではありません。代わりに、これらの変数は内部Apache構造に格納および操作されます。これらは、CGIスクリプトおよびサーバーサイドインクルードスクリプトに提供された場合にのみ、実際のオペレーティングシステム環境変数になります。サーバー自体が実行されているオペレーティングシステム環境を操作する場合は、オペレーティングシステムシェルが提供する標準の環境操作メカニズムを使用する必要があります。

PHPのオペレーティングシステム環境変数を設定します。ただし、設定しているのは内部環境変数のみです。

Mod_PHPはそれらをスクリプトにインポートする可能性があるため、getenv('TMPDIR')を使用すると、PHP SAPI固有実装が使用されます-これにより、これらの内部環境変数を確認できます-しかし、_php_get_temporary_directory_関数はそれを使用していません-のように見えます。

ApacheとPHPバージョンを質問に追加してください。

6
hakre

this-4歳-バグ によると、sys_get_temp_dir()は仮想ホストでは機能しません。そう

  • この問題を修正したライブラリのみを使用してみることができます(修正しなかった場合はバグを開きます)
  • または、/tmpopen_basedir(またはOSが使用するもの)を次のように追加します 複数のディレクトリを保持できますinclude_pathのように-Windowsでは;で区切り、それ以外の場合は:
5
pozs

PHPソース を見ると、sys_get_temp_dir()は次の優先度で機能します。

  1. その値が以前に計算されている場合は、キャッシュされた値が使用されます。
  2. _sys_temp_dir_はini構成でチェックされます。
  3. Windowsでは、 GetTempPathW Win32 APIメソッドが使用され、そのドキュメントによれば、以下が(この順序で)使用されます:
    1. TMP環境変数で指定されたパス。
    2. TEMP環境変数で指定されたパス。
    3. USERPROFILE環境変数で指定されたパス。
    4. Windowsディレクトリ。
  4. * nixでは、以下が(この順序で)使用されます:
    1. TMPDIR環境変数。
    2. _P_tmpdir_マクロ
    3. _/tmp_(情報源によると、これは決して起こらないはずの最後の努力です)。

これにより、_sys_get_temp_dir_の結果を制御するための十分なオプションが提供されます(たとえば、他の人が言及したようにini_set('sys_temp_dir', $tmpPath)またはputenv('TMPDIR=/foo/bar')Unless以前に計算されたものです。この場合、私が知る限り、あなたはSOLであり、キャッシュされた値が使用されます(ただし、PHPに関する知識はありません。そうでなければ聞いてみたい)。

4
Ohad Schneider

これはphp5.2のバグです--- php.iniでtemp dirを指定してください
5.5で修正されました
これを一時的な解決策として使用します。

<?php
putenv('TMPDIR=/path/to/your/tmp');
          ...your code here ...
?>
2
eugene

人々がここにたどり着いた場合、問題はputenvで解決されません...

...私にとっては、phpの sys_temp_dir を使用してini_setを次のように設定することができました:

$tmpPath = realpath(__DIR__.'/../app/tmp');
ini_set('sys_temp_dir', $tmpPath);

私はwindows8マシンでPHP 5.5.9(cli)を実行しています。

1
Andresch Serj

sys_get_temp_dir()によって返される値を変更できるようです。Apache2.4とphp5.6.27で試しました。

仮想ホストに_sys_temp_dir_を追加します。

_php_admin_value sys_temp_dir "/var/www/alternc/f/fser/tmp"
_

Apacheを再起動し、sys_get_temp_dir()を使用してWebページに値を出力します。

_<?php 
echo sys_get_temp_dir () ;
_

期待される出力を生成します:_/var/www/alternc/f/fser/tmp_。

0
Aif