注意:这也适合超级用户。
我在apache2 mpm itk和open_basedir的共享主机上设置PHP 5.3.10,每个用户可能看不到或更改其他用户的文件。在apache2 vhost设置中,我添加了相应的条目来限制用户:
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,接下来的三行将basedir,upload目录和session savepath定义在用户目录中。我会在一秒钟内回到最后一行。
现在出现问题:sys_get_temp_dir()
应该回放php的临时目录,这是/ tmp在linux系统上的默认目录。出于安全原因,此目录应驻留在userA的open_basedir中。根据5.3.10的php-source,sys_get_temp_dir()
- 函数使用环境变量TMPDIR来获取这个目录:
// php-src/main/php_open_temporary_file.c:217-219
/* On Unix use the (usual) TMPDIR environment variable. */
{
char* s = getenv("TMPDIR");
这就是上面配置中的第五行应该做的事情。但是,sys_get_temp_dir()
只返回全局系统目录,忽略环境变量(在$ _SERVER中完美设置,也可通过phpinfo()
查看)。
由于该目录不在sys_get_temp_dir()
设置,因此会导致一些令人讨厌的错误,其中各种软件都依赖于open_basedir
。我试图将变量直接设置为$ _ENV和$ _SERVER而不改变行为。我试过了putenv('TMPDIR=/home/userA/www/tmp')
而没有改变。
但是,我可以通过将变量定义到/ etc / apache2 / envvars来更改输出 - 这对我来说没用,因为我希望每个VHOST都有自己的临时文件夹。
到目前为止,我找到的唯一解决方案是通过runkit这样的扩展程序覆盖内部sys_get_temp_dir()
,并通过auto_prepend_file强制将其包含在内。但是这个解决方案太脏了,我简直无法相信,周围没有更好的解决方案。
所以,我的问题:有没有办法在apache2 vhost设置中更改sys_get_temp_dir()
的结果,而不用runkit重新实现该功能?
编辑: apache版本是2.2.22,我目前使用的是mod_php。由于我必须手动添加所有用户,因此也可以使用fcgi或类似设置。
答案 0 :(得分:22)
在内部运行putenv('TMPDIR=/foo/bar')
PHP似乎能够影响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中的一些环境处理错误。
答案 1 :(得分:6)
您已标记了问题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中找到正确的位置来设置环境变量,以便在脚本执行时(仍然)设置它。
您也可能没有设置正确的环境变量。根据{{3}}:
虽然这些变量称为环境变量,但它们与底层操作系统控制的环境变量不同。相反,这些变量在内部Apache结构中存储和操作。它们仅在提供给CGI脚本和服务器端包含脚本时才成为实际的操作系统环境变量。如果您希望操作服务器本身运行的操作系统环境,则必须使用操作系统shell提供的标准环境操作机制。
您想为PHP设置操作系统环境变量。但是您只设置内部环境变量。
Mod_PHP 可能会将它们导入脚本,因此如果您使用getenv('TMPDIR')
,则使用PHP SAPI特定实现 - 这允许您查看这些内部环境变量 - 但php_get_temporary_directory
{{} 1}}函数没有使用它 - 看起来像。
请将您的Apache和PHP版本添加到您的问题中。
答案 2 :(得分:5)
根据this - 4 year old - bug,sys_get_temp_dir()
不适用于虚拟主机;所以
/tmp
(或操作系统使用的任何内容)附加到open_basedir
,it can hold multiple directories(如include_path
- 在Windows上将其与;
分开, :
否则)答案 3 :(得分:4)
查看PHP source,sys_get_temp_dir()
使用以下优先级:
sys_temp_dir
。TMP
环境变量指定的路径。TEMP
环境变量指定的路径。USERPROFILE
环境变量指定的路径。TMPDIR
环境变量。P_tmpdir
宏/tmp
(根据消息来源,这是一个不应该发生的最后努力)。这应该为您提供足够的选项来控制sys_get_temp_dir
的结果(例如ini_set('sys_temp_dir', $tmpPath)
或putenv('TMPDIR=/foo/bar')
,如其他人提到的那样)除非以前计算过,否则据我所知,在哪种情况下你会使用SOL,并且会使用缓存的值(但我对PHP没有任何知识,所以我很乐意听到其他情况)。
答案 4 :(得分:2)
这是php 5.2中的一个错误 - specify temp dir by php.ini
它固定在5.5
使用此作为临时解决方案:
<?php
putenv('TMPDIR=/path/to/your/tmp');
...your code here ...
?>
答案 5 :(得分:1)
万一人们到这里来了,问题没有用putenv解决......
...对我来说,使用php ini_set
设置sys_temp_dir
是这样的:
$tmpPath = realpath(__DIR__.'/../app/tmp');
ini_set('sys_temp_dir', $tmpPath);
我在windows8机器上运行PHP 5.5.9(cli)。
答案 6 :(得分:0)
看起来您可以更改sys_get_temp_dir()
返回的值,我刚刚尝试过apache 2.4和php 5.6.27。
在虚拟主机中添加sys_temp_dir
:
php_admin_value sys_temp_dir "/var/www/alternc/f/fser/tmp"
重新启动apache,并使用sys_get_temp_dir()
<?php
echo sys_get_temp_dir () ;
产生预期的输出:/var/www/alternc/f/fser/tmp
。