为什么 echo 是内置命令的 shell?

为什么 echo 是内置命令的 shell?
$ which echo
echo: shell built-in command.
$ which ls
/bin/ls
$ which cat
/bin/cat

为什么 echo 不是像 、 等那样的独立ls实用ps程序cat?为什么它是特定于 shell 的?有什么好的理由吗?

答案1


有两类内置函数:

  1. 有些命令必须内置到 shell 程序本身中,因为如果它们是外部命令,则它们无法工作。

    cd就是这样,因为如果它是外部的,它只能更改自己的目录;它不会影响 shell 的当前工作目录。 (也可以看看:为什么cd不是程序?

  2. 另一类命令被内置到 shell 中纯粹是为了提高效率。

    dash 手册页有一个关于内置命令的部分,其中提到printfechotest作为此类中命令的示例。

Unix 系统始终包含第二类命令的单独可执行文件。这些单独的可执行文件在我使用过的每个 Unixy 系统上仍然可用,尽管它们也内置于您可能使用的每个 shell 中。 (POSIX实际上需要这些可执行文件存在。)

我相信echo已内置到 AT&T Unix System V Release 3.1 的 shell 中。我的结论基于对 AT&T 两个不同版本手册的比较3B1系列Unix系统。有人善意地扫描了这些手册的 1986 年版把它们放到网上;这些对应于 SVR3 的原始版本。您可以看到它echo不在第 523 页的列表中UNIX 系统 V 用户手册,第二卷,如果该命令内置于 shell 中,您会期望它。在我本地 1987 年 SVR3.1 手册的纸质副本中,echo 手册的本节中列出。

我很确定这不是伯克利中国南方研究集团AT&T 将创新带回国内。 4.3BSD 与 SVR3 同年发布,1986 年,但如果你看一下4.3BSD 的 sh.1 联机帮助页,您会看到它echo不在“特殊命令”部分的内置命令列表中。如果 CSRG 这样做了,我们就需要有记录的来源来证明这一点。

此时,您可能想知道是否echo早于 SVR3.1 就已内置到 shell 中,而这一事实根本就不是有记录的直到那时。我可以使用的最新 SVR3 之前的 AT&T Unix 源代码位于PDP-11 System III 压缩包,您将在其中找到 Bourne shell 源代码。您不会echo在内置命令表中找到该命令,该表位于/usr/src/cmd/sh/msg.c.根据该文件中的时间戳,证明echo1980 年肯定不在 shell 中。


琐事

同一目录还包含一个名为 的文件,builtin.c该文件不包含此问题的任何内容,但我们确实发现了这个有趣的评论:

/*      
    builtin commands are those that Bourne did not intend
    to be part of his shell.
    Redirection of i/o, or rather the lack of it, is still a
    problem..
*/      

答案2

某些命令是内置的还有第三个原因:当无法运行外部命令时可以使用它们。

有时系统会严重损坏,导致ls命令无法工作。在某些情况下,遗嘱echo *仍然有效。

另一个(更重要!)的例子是kill:如果系统用完了可用的 PID,则无法运行/bin/kill(因为它需要 PID :-),但内置的系统kill可以工作。

顺便说一句,which是一个外部命令(至少在 bash 中不是内部命令),因此它无法列出内部命令。例如:

$ which echo
/bin/echo
$ type -a echo
echo is a shell builtin
echo is /bin/echo

答案3

根据Bash 参考手册,这是为了方便。

Shell 还提供一小组内置命令 (builtins),实现通过单独的实用程序不可能或不方便获得的功能。例如,cd、break、Continue 和 exec)无法在 shell 外部实现,因为它们直接操作 shell 本身。历史记录、getopts、kill 或 pwd 内置命令等可以在单独的实用程序中实现,但它们作为内置命令使用更方便。所有 shell 内置函数将在后续部分中进行描述。

高级 Bash 脚本编写指南有更详细的解释:

“内置命令是 Bash 工具集中包含的命令,实际上是内置的。这要么是出于性能原因——内置命令比外部命令执行得更快,而外部命令通常需要分叉 1 一个单独的进程——或者因为特定的内置函数需要直接访问 shell 内部。”

另请注意,它echo在某些系统上确实作为独立实用程序存在。这是我的 Darwin 系统(MacOSX 10.5.8 - Leopard)上的内容

$ uname -a
Darwin host.foo.org 9.8.0 Darwin Kernel Version 9.8.0: Wed Jul 15 16:55:01 PDT 2009; root:xnu-1228.15.4~1/RELEASE_I386 i386
$ bash --version
GNU bash, version 3.2.17(1)-release (i386-apple-darwin9.0)
Copyright (C) 2005 Free Software Foundation, Inc.
$ which echo
/bin/echo

echo也可以作为内置程序使用,但显然我的脚本在我的 Mac 上使用 /bin/echo,并在我的大多数 Linux 和 FreeBSD 系统上使用 Bash 内置程序。但这似乎并不重要,因为脚本在任何地方仍然可以正常工作。

答案4

echo这是为什么应该是 shell 内置的真正原因:

假设您有一个密码$PASSWORD。如何将其写入文件./password?大多数程序员自然会这样写:

echo "$PASSWORD" >./password

然而,如果echo不是 shell 内置的,密码就会通过ps信息泄露给所有用户。

当然,如果你想聪明一点,你可以找到一种不使用 来存储密码的方法echo,也许可以利用一些其他 shell 功能:

cat >./password <<EOF
${PASSWORD}
EOF

然而,echo作为内置是一个重要的安全带,因为将密码保存到文件的最明显的方法也应该有效。

相关内容