这个问题的目的是为了满足好奇心,而不是解决特定的计算问题。问题是:为什么 POSIX 强制实用程序通常不内置到 shell 实现中?
例如,我有一个脚本,它基本上读取一些小文本文件并检查它们的格式是否正确,但由于大量的字符串操作,在我的计算机上运行需要 27 秒。这种字符串操作通过调用各种实用程序来创建数千个新进程,因此速度很慢。我非常有信心,如果内置了一些实用程序,即grep
、sed
、cut
、tr
和expr
,那么脚本将在一秒或更短的时间内运行(根据我在 C 方面的经验)。
似乎在很多情况下,构建这些实用程序会影响 shell 脚本中的解决方案是否具有可接受的性能。
显然,选择不内置这些实用程序是有原因的。也许在系统级别使用一个实用程序版本可以避免各种 shell 使用该实用程序的多个不同版本。我真的想不出许多其他原因来保持创建如此多新进程的开销,并且 POSIX 对实用程序进行了足够的定义,因此拥有不同的实现似乎并不是什么大问题,只要它们都是 POSIX符合。至少没有像拥有如此多流程的低效率那么大的问题。
答案1
为什么 POSIX 强制实用程序没有内置到 shell 中?
因为要符合 POSIX 标准,系统必须是必需的1以独立命令的形式提供大多数实用程序。
将它们内置意味着它们必须存在于两个不同的位置,即外壳内部和外壳外部。当然,可以通过使用内置的 shell 脚本包装器来实现外部版本,但这会对调用实用程序的非 shell 应用程序不利。
注意忙碌盒通过在内部实现许多命令并使用自身链接提供独立变体,采用了您建议的路径。一个问题是,虽然命令集可能非常大,但实现通常是标准的子集,因此不兼容。
还要注意的是,至少ksh93
,bash
并zsh
进一步为正在运行的 shell 提供自定义方法,以从共享库动态加载内置函数。从技术上讲,没有什么可以阻止所有 POSIX 实用程序的实现并作为内置程序提供。
最后,使用现代操作系统生成新进程已成为相当快的操作。如果您确实遇到性能问题,可能会进行一些改进以使您的脚本运行得更快。
然而,所有标准实用程序,包括表中的常规内置函数,但不包括特殊内置实用程序中描述的特殊内置函数,应以某种方式实现,以便可以通过 exec 函数族访问它们如 POSIX.1-2008 的系统接口卷中所定义,可以由需要它的标准实用程序(env、find、nice、nohup、time、xargs)直接调用。
答案2
Shell 脚本预计不会以这种速度运行。如果您想提高脚本的速度,请在 perl 中尝试。如果仍然太慢,那么您将不得不转向静态类型语言,例如 java 或 c,或者为 perl 编写一个 C 模块来运行太慢的部分。
Shell 是原型设计的第一级,如果你能用 shell 证明这个概念,那么就转向更好的脚本语言,它可以做更多的边界检查,这将占用大量的 shell。
Unix 操作系统预计将包含许多小程序,这些程序执行明确定义的任务,从而构成更大的画面。这是一件好事,因为它划分了更大的程序。例如,看一下 qmail,并将其与 sendmail 进行比较。 qmail 由许多程序组成:
http://www.nrg4u.com/qmail/the-big-qmail-picture-103-p1.gif
利用网络守护进程不会帮助您利用队列管理器。
答案3
来自BASH 参考手册,
内置命令对于实现使用单独的实用程序不可能或不方便获得的功能是必需的。
我相信您已经听说过,UNIX 理念严重依赖于多个功能有限的应用程序。每个内置项都有一个很好的内置理由。其他的则不然。我认为一类更有趣的问题是“到底为什么是 pwd
内置?”
答案4
因此,我们没有调动资源来优化原始工具来满足每个特定的需求。我想我们需要解释的是,实现这个特定的愿望需要多少成本。
POSIX 对实用程序的定义足够多,因此不同的实现似乎并不是什么大问题。
这是一个糟糕的假设:-P。
后 POSIX 系统继续变得更加强大和方便,这是有充分理由的;作为事后标准,它实际上从未跟上。
Ubuntu 开始努力切换到精简的 POSIX shell 脚本,以优化旧的 System V init 启动过程。我并不是说它失败了,但它确实引发了许多必须清理的错误:“bashisms”,/bin/sh
在假设bash
功能可用的情况下运行的脚本。
POSIX sh 不是一种好的通用编程语言。它是基本的目的是作为交互式 shell 正常工作。一旦开始将命令保存到脚本中,请注意您正在接近图灵油坑。例如,这是不可能的检测正常管道中间的故障。 为此bash
添加set -o pipefail
,但这不在 POSIX 中。
几乎所有比 更复杂的实用程序都提供了类似的有用但非标准化的功能true
。
对于您概述的任务类别,您可以粗略地了解 Awk、Perl 和现在的 Python。不同的工具被创建并独立发展。您是否期望 GNU Awk 被纳入 libutilposixextended 中?
我并不是说我们现在有一种可以向您指出的普遍更好的方法。我对 Python 情有独钟。尽管我对 GNU Awk 特有的某些功能感到沮丧,但 Awk 的功能却出人意料地强大。但关键是,单独处理大量字符串(可能来自文件行)并不是 POSIX shell 的设计目标。