Laz*_*zer 39 command-line shell shell-builtin
$ which echo
echo: shell built-in command.
$ which ls
/bin/ls
$ which cat
/bin/cat
Run Code Online (Sandbox Code Playgroud)
为什么回声不喜欢一个独立的工具ls
,ps
,cat
等?为什么它是特定于外壳的?有什么好的理由吗?
War*_*ung 76
有两类内置函数:
某些命令必须内置到 shell 程序本身中,因为如果它们是外部的,它们将无法工作。
cd
就是这样,因为如果它是外部的,它只能更改自己的目录;它不会影响 shell 的当前工作目录。(另见:为什么cd
不是程序?)
另一类命令被内置到 shell 中纯粹是为了提高效率。
Unix 系统总是为第二类中的命令包含单独的可执行文件。这些单独的可执行文件在我使用过的每个 Unixy 系统上仍然可用,即使它们也内置在您可能使用的每个 shell 中。(POSIX实际上要求这些可执行文件存在。)
我相信echo
在 AT&T Unix System V Release 3.1 中已内置到 shell 中。我基于对 AT&Ts 3B1 系列 Unix 系统的两个不同版本手册的比较。有人好心地扫描了这些手册的 1986 年版本并将它们放到网上;这些对应于 SVR3 的原始版本。您可以看到它echo
不在UNIX System V User's Manual, Volume II 的第 523 页的列表中,如果命令内置在 shell 中,您会期望它出现在该列表中。在从1987年SVR3.1手册我的本地文件拷贝,echo
被列在本章节。
我很确定这不是AT&T 带回家的伯克利CSRG创新。4.3BSD 于 1986 年与 SVR3 同年问世,但如果您查看4.3BSD 的 sh.1 联机帮助页,您会发现它echo
不在“特殊命令”部分的内置命令列表中。如果 CSRG 这样做了,那我们就需要有文件证明的来源来证明这一点。
在这一点上,您可能想知道是否echo
早于 SVR3.1 就已内置到 shell 中,并且直到那时才记录这一事实。我可以使用的最新 SVR3 之前的 AT&T Unix 源代码位于PDP-11 System III tarball 中,您可以在其中找到 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..
*/
Run Code Online (Sandbox Code Playgroud)
小智 22
某些命令被内置还有第三个原因:它们可以在无法运行外部命令时使用。
有时系统会变得如此损坏,以至于ls
命令不起作用。在某些情况下, anecho *
仍然有效。
另一个(更重要的!)示例是kill
:如果系统用完可用的 PID,则无法运行/bin/kill
(因为它需要 PID :-),但是内置的kill
可以工作。
顺便说一句,which
是一个外部命令(至少在 bash 中它不是内部命令),因此它无法列出内部命令。例如:
$ which echo
/bin/echo
$ type -a echo
echo is a shell builtin
echo is /bin/echo
Run Code Online (Sandbox Code Playgroud)
Ste*_*ski 14
根据Bash 参考手册,这是为了方便。
Shell 还提供了一小组内置命令(builtins),实现了通过单独的实用程序不可能或不方便获得的功能。例如,cd、break、continue 和 exec) 不能在 shell 之外实现,因为它们直接操作 shell 本身。history、getopts、kill 或 pwd 等内置命令可以在单独的实用程序中实现,但作为内置命令使用它们更方便。所有的 shell 内置函数都在后续章节中描述。
该高级Bash脚本编程指南有一个更详细的解释:
“内置命令是包含在 Bash 工具集中的命令,字面上是内置的。这要么是出于性能原因——内置命令的执行速度比外部命令快,后者通常需要分叉 1 一个单独的进程——或者因为特定的内置命令需要直接访问外壳内部。”
另请注意,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
Run Code Online (Sandbox Code Playgroud)
echo
也可以作为内置程序使用,但显然我的脚本在 Mac 上使用 /bin/echo,在我的大多数 Linux 和 FreeBSD 系统上使用 Bash 内置程序。但这似乎并不重要,因为脚本在任何地方都可以正常工作。