PHP什么时候我应该执行shell,vs内部PHP函数。性能?安全?

时间:2011-11-26 08:34:19

标签: php linux performance

我是Linux SysAdmin,并且一直在使用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);
?>

是否有更有效的方法来替换该循环?在我的情况下,性能确实很重要,这些将被制作成 snippet 之类的东西。

这是与系统相关的代码,不会采用任何类型的输入。甚至不是来自URL。此外,环境规模很大,所有系统都经过性能调整和分析。

所以尽可能做到最好的方式就是我正在寻找的东西。 我真的很感激任何意见,因为我的经验有点受限。

6 个答案:

答案 0 :(得分:3)

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

使用PHP的内置函数来执行这些操作可能 可能更快,因为我认为执行exec()会有一些开销。老实说,除非您在一个脚本中获得数千次目录列表,否则我认为您不会遇到性能问题。另外,如果你真的关心它的基准测试,但我认为你将进行微观优化,但没有取得重大进展。 (过早的优化是万恶之源!)

如果您接受用户输入并且未对其进行清理,则会出现安全问题。我会非常小心地清理输入然后传递给exec()。

答案 1 :(得分:2)

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

至于安全性:PHP的内置函数将通过shell启动进程的安全性问题较少。 (例如PHP的system函数。)如果你在shell命令中使用用户输入,那么启动shell是特别危险的事情:你必须确保无论用户输入什么,你都会知道你构造的shell命令会做! (这类似于SQL注入,如果您熟悉它。)PHP为此提供了功能,systemexec的手册页注意到它们。

也就是说,使用用户输入读取目录也有安全考虑(在一般情况下)。始终确保根据您的情况清理用户的输入。如果他们可以读取任何目录,opendir($the_users_input)可能就行了。如果他们只能阅读/foo/bar中的任何内容,那么您可能需要确保他们没有通过您../../etc/passwd

答案 2 :(得分:1)

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

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

答案 3 :(得分:1)

执行bash命令通常会慢一些 您可能需要调用外部bash命令的两种情况

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

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

  3. 正如其他人已经指出的那样,如果表现是一个问题,那么做基准并比较自己 如果担心安全性,执行外部bash命令的风险会更高。


    如果扫描dir真的是瓶颈,
    你应该考虑缓存到允许快速访问的存储,例如APC,memcache。

    您可以轻松创建一个挂钩/触发器,以使缓存在目录上存在写入活动时到期。

    一个例子

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

    通过这种典型的命中或错过技术,您的表现可以获得相当好的提升。

答案 4 :(得分:0)

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

我有2个有用的输入:

<强> 1。我最可靠的预感是坚持使用PHP调用而不是分离另一个进程:

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

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

<强> 2。 Ajreal的memcache建议听起来像是一个很好的第三解决方案

您可以随时使用inotify让脚本知道重要目录何时被修改并触摸(不一定是触摸工具)db(甚至是平面文件或内存缓存),让您知道它已被更改。

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

答案 5 :(得分:-1)

  

我想从系统命令而不是PHP内部函数

获取输出的原因

你自己命名 - 你熟悉它们 这就够了

至于表现并不重要。

看,你正在考虑系统的最小部分 要处理用户请求,Web服务器将执行数百次此类磁盘查找。为什么他们不关心你?但是你想要超级超级微观优化只优化这一个 你甚至不知道它是否是必需的。
这没有逻辑。