$ which echo
echo: shell built-in command.
$ which ls
/bin/ls
$ which cat
/bin/cat
为什么 echo 不是像 、 等那样的独立ls
实用ps
程序cat
?为什么它是特定于 shell 的?有什么好的理由吗?
答案1
有两类内置函数:
有些命令必须内置到 shell 程序本身中,因为如果它们是外部命令,则它们无法工作。
cd
就是这样,因为如果它是外部的,它只能更改自己的目录;它不会影响 shell 的当前工作目录。 (也可以看看:为什么cd
不是程序?)另一类命令被内置到 shell 中纯粹是为了提高效率。
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
.根据该文件中的时间戳,证明echo
1980 年肯定不在 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
作为内置是一个重要的安全带,因为将密码保存到文件的最明显的方法也应该有效。