了解 shell 内置命令

了解 shell 内置命令

在在bash手册, 上面写着

Builtin commands are contained >>> within <<< the shell itself

还,答案指出

A built-in command is simply a command that the shell carries out itself,
instead of interpreting it as a request to load and run some
>>> other program <<<

当我运行时compgen -bbash 4.4我收到所有 shell 内置命令的列表。例如,我看到[kill被列为 shell 内置函数。但他们的实际位置是:

/usr/bin/[
/bin/kill

我认为这意味着builtin命令被编译成/bin/bash可执行文件。那么真正让我困惑的是:请纠正我,但是builtin当它实际上不是 shell 的一部分时,它怎么可能是 a 呢?

答案1

内置到 shell 中的命令通常是内置的,因为这可以提高性能。呼叫外部的 printf例如,比使用内置的printf.

由于某些实用程序不需要内置,除非它们是特殊的,例如cd,它们也提供为外部的公用事业。这样,如果脚本由不提供内置等效项的 shell 解释,则脚本不会中断。

某些 shell 的内置命令还提供对外部等效命令的扩展。例如, Bashprintf能够做到

$ printf -v message 'Hello %s' "world"
$ echo "$message"
Hello world

(打印到变量)外部/usr/bin/printf根本无法执行此操作,因为它无权访问当前 shell 会话中的 shell 变量(并且无法更改它们)。

内置实用程序也可以不是其扩展命令行必须短于一定长度。正在做

printf '%s\n' *

printf因此,如果是 shell 内置命令,则是安全的。命令行长度的限制来自于execve()用于执行外部命令的C库函数。如果命令行和当前环境大于ARG_MAX字节(参见getconf ARG_MAXshell),调用execve()将会失败。如果该实用程序内置于 shell 中,execve()则不必调用。

内置实用程序优先于$PATH.要禁用 中的内置命令bash,请使用例如

enable -n printf

有一个简短的实用程序列表需要内置到 shell 中(取自 POSIX 标准特殊内置列表

break
colon (:)
continue
dot (.)
eval
exec
exit
export
readonly
return
set
shift
times
trap
unset

这些需要内置,因为它们直接操作当前 shell 会话的环境和程序流程。外部实用程序无法做到这一点。

有趣的是,cd不是这个列表的一部分,而是 POSIX说以下关于那个:

由于cd影响当前 shell 执行环境,因此它始终作为 shell 常规内置提供。如果在子 shell 或单独的实用程序执行环境中调用它,例如以下之一:

(cd /tmp)
nohup cd
find . -exec cd {} \;

它不会影响调用者环境的工作目录。

因此,我假设“特殊”内置程序不能有外部对应项,而cd理论上可以有(但它不会做太多事情)。

答案2

您(非常可以理解)对某些内置函数的存在感到困惑两个都作为内置函数作为外部命令。因此,虽然您是对的,例如有一个/bin/[命令,但这并不意味着它的“实际位置”位于/bin.

任何简单的测试方法都是使用type开关运行-a,它将显示命令的所有可用实例。在我的 Arch 系统上,显示:

$ type -a [
[ is a shell builtin
[ is /sbin/[
[ is /usr/sbin/[
[ is /usr/bin/[

请注意/sbin, 、/usr/sbin/bin都是指向 的符号链接/usr/bin,因此只有一个外部[

$ readlink -f /usr/sbin /sbin /bin/
/usr/bin
/usr/bin
/usr/bin

正如您所看到的,[它既是一个内置命令,也是一个外部命令,其他各种 shell 内置命令也是如此。然而,这并没有改变这样的事实:它们也是 shell 内置函数,编译到 shell 本身中。

相关内容