PHP何时应该执行到shell, vs内部PHP函数.性能?安全


PHP when should I exec to shell, vs internal PHP functions. Performance? Security?

我是Linux系统管理员,总是在Bash中工作。我非常有经验的管理PHP,但相当新的编写PHP脚本。

为什么我想从系统命令而不是PHP内部函数中获得输出?我假定您有可移植性方面的问题,尽管这对我来说不是问题。

例如,

我可以得到一个带有ls的目录列表,以及一个exec风格的函数。或者使用opendir('.')和一个循环。

性能考虑因素是什么?

这是我现在的文件,

<?php
// Directory Open
$myDirectory = opendir('/media/ARCHIVE/Documents/conf/web_confs');
// Array of Elements
while($entryName = readdir($myDirectory)) {
$dirArray[] = $entryName;
}
// Directory Close
closedir($myDirectory);
// Sort Array
sort($dirArray);
?>

有没有更有效的方法来代替这个循环?在我的情况下,性能很重要,这些将被做成代码段之类的东西。

这是与系统相关的代码,不接受任何类型的输入。甚至连URL都没有。此外,环境规模很大,所有系统都进行了性能调整,并经常进行概要分析。

所以做最好的方式可能一次是我所寻找的。我真的很感谢任何建议,因为我的经验有些有限。

对于这种特殊情况,我将使用scandir (http://www.php.net/manual/en/function.scandir.php)。

它的可能更快使用PHP的内置函数做这些事情,因为我猜做exec()有一些开销。老实说,我不认为您会有性能问题,除非您在一个脚本中获得数千次目录列表。此外,如果您真的关心的话,可以对其进行基准测试,但我认为您将进行微优化,而这些优化不会产生显著的改进。(过早优化是万恶之源!)

如果您接受用户输入而不对其进行消毒,则会出现安全问题。我会非常小心地对传递给exec()的输入进行消毒。

对于您的读取目录的示例,在PHP中执行它肯定会比让操作系统加载过程更快。

至于安全性:PHP内置函数的安全性问题比通过shell启动进程要少。(比如PHP的system函数。)如果您在shell命令中使用用户输入,那么启动shell的风险尤其大:您必须确保无论用户可能输入什么,您都知道您构建的shell命令将做什么!(这类似于SQL注入,如果您熟悉的话。)PHP提供了这样的函数,systemexec的手册页都有注释。

也就是说,使用用户的输入读取目录也有安全方面的考虑(在一般情况下)。始终确保根据您的情况对用户输入进行了适当的处理。如果它们可以读取任何目录,那么opendir($the_users_input)可能是可以的。如果它们应该只能读取/foo/bar中的任何内容,那么您可能需要确保它们不会传递../../etc/passwd .

我不会真的说PHP函数较慢,因为它们大多映射到底层C库函数。自定义可执行文件当然是另一回事了。

使用exec意味着通过复制整个进程内存来分叉进程(我知道这里跳过了vfork),并用新的可执行文件替换进程内存。后者实际上相当快。我想说,普通的C2D系统每秒可以处理几千个执行。

执行bash命令一般会比较慢。
有两种情况可能需要调用外部bash命令

  1. 当PHP没有内置库支持时(或者需要安装PECL包)。比如rsync, wget, seige, mysqldump, ab (apache benchmark)。此时,您会发现执行外部命令更容易

  2. bash脚本可以获得比PHP内置函数更好的结果,例如您的示例。或者另一个例子:- du -h $dir | sort -nr

正如其他人已经指出的那样,如果您关心性能,请进行基准测试并进行比较。
如果考虑安全性,执行外部bash命令风险较大。


如果扫描目录确实是瓶颈,
您应该考虑将缓存到允许快速访问的存储中,例如APC, memcache。

你可以很容易地创建一个钩子/触发器来过期在目录上有写活动的缓存。

一个例子
if ( cache_found())
{
  // return results from cache
}
else
{
  // scan dir
  // set the scan result into cache
  // return scan result;
}

使用这种典型的不命中即失败的技术,您的性能可以得到相当好的提升。

TechZilla -听起来你和YCS有误会。我会忽略它。

我有两个有用的输入:

1。我最可靠的预感是坚持使用PHP调用,而不是派生另一个进程:


创建一个新进程会做各种有趣的事情:文件句柄和状态副本,整个堆栈的备份,寄存器状态的备份,内存位置的重新定位,从磁盘加载新的可执行文件,加载每个尚未加载的共享库,为内存位置补丁跳转指令和数据寄存器数千次(这意味着很多可能的cpu内存缓存丢失!),一个巨大的头痛


函数调用(即使是对C绑定)只是堆栈上的一点额外空间和一些指令指针跳转。在你的应用程序第一次加载时,它将处理加载任何依赖库(上文定义的头痛问题),但这些库会留在内存中。没有什么大不了的。你不能对整个程序做同样的事情。

2。Ajreal的memcache建议听起来像是不错的第三个解决方案

当一个重要的目录被修改时,你总是可以使用通知让脚本知道,并触摸(不一定是触摸工具)一个数据库(甚至是平面文件或memcache),让你知道它被修改了。

所有检查目录内容的代码都可以检查缓存,除非另有通知。Linux文件系统缓存将非常有效地检查互斥锁文件:仅限内存,除非对其进行了更改,否则不会触及磁盘。

为什么我想从系统命令而不是PHP内部函数中获得输出

你自己给他们起的名字——你对他们很熟悉。
够了

就性能而言,这并不重要。

看,你关心的是系统中最小的部分。
为了处理一个用户请求,网络服务器将进行数百次这样的磁盘查找。你为什么不关心他们?但是你只需要对这一个进行超级超级微观的优化。
你甚至不知道它是否是必需的。
这没有任何逻辑可言。