区分用户定义的可执行文件与预先存在的可执行文件

区分用户定义的可执行文件与预先存在的可执行文件

cp诸如和 之类的命令ls位于/bin或下/usr/bin

假设我们创建了另一个同名的可执行文件,Linux 将如何区分它们?

答案1

TL;DR:一旦找到要运行的东西,shell 就会停止查找。


你问Linux 将如何区分它们? 你可能指的是 Linux 的内核,它能够理解,例如,神奇数字,并且通常知道如何执行可执行文件。

我将把这个话题留给其他人,并假设你询问当 shell 运行以多种形式存在的命令时会发生什么。


一个原因,似乎是你要问的,为什么可能有两个同名的命令,是因为两个文件可以有相同的基本名称,例如:

/usr/bin/foo
/bin/foo

我们总是可以通过它们的完整路径来区分两个文件,因为文件系统中的两个文件不可能具有相同的完整路径。cmak.fr 发表评论指出了这一点

如果你安装或编写自己的可执行文件,你可能选择将它们放在~/bin或 中/usr/local/bin。这些位置位于 Ubuntu 中的默认 PATH 中。/usr/local/bin位于默认 PATH 的开头:

$ grep PATH /etc/environment
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games"

如果 PATH 存在的话,则~/bin添加到 PATH 前面:

$ grep -A3 bin ~/.profile
# set PATH so it includes user's private bin if it exists
if [ -d "$HOME/bin" ] ; then
    PATH="$HOME/bin:$PATH"
fi

所以我最终选择了这条路径...

$ echo $PATH
/home/zanna/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games

由于在我的 PATH/home/zanna/bin/bin,如果我将名为 的命令放入chmod其中~/bin并运行,则将运行chmod该可执行文件而不是,因为~/bin/chmod/bin/chmod一旦找到东西,shell 就会停止查找,如果我想要运行/bin/chmod,我必须这样做:输入我想要运行的程序的完整路径。

这实际上是一个我们还没有提到开头的故事的结束,因为路径查找是 shell 在尝试执行命令时做的最后一件事,并且有两个同名的文件并不是有两个同名命令的唯一方式。

我在这里要讨论的是 Bash,因为它是我唯一比较熟悉的 shell。据我所知,其他 shell 也会遵循类似的程序。但需要注意的是,Ubuntu 上的许多实用程序调用的/bin/sh不是 Bash,虽然/bin/sh可能通过符号链接到/bin/bash,但在 Ubuntu 上默认是/bin/dash,并且可以是任何已安装的 shell 程序。

命令的第一个字是 shell 尝试执行的内容 - 后续字是它的参数(可能是选项,也可能不是必需的)。

注意别名扩展在所有其他扩展之前执行在将命令分解成单词的阶段,在命令执行之前的几个阶段。这意味着别名总是优先于其他命令可能具有相同的名称。

在标记化和所有扩展完成后,重定向已设置,变量赋值已完成,命令执行开始。

如果第一个单词包含/,则 shell 会假定该单词是路径,并尝试执行(据我所知,让内核让 CPU 执行它或调用它的解释器,或者如果其他方法都失败,则将其作为 shell 脚本运行)该路径上的文件。如果该路径上的文件不存在,则获取no such file or directory

如果第一个单词不包含/,shell 将按照此顺序继续查找命令,并执行找到的第一件事然后停止寻找

  1. 是否有一个同名的 shell 函数?
  2. 是否有一个同名的内置 shell?
  3. 是否有命令哈希表用这个名字?
  4. 任何 PATH 目录中是否有同名的命令?

因此,搜索 PATH 是最后的手段。请注意,PATH 是按从左到右的顺序搜索的。PATH 中的第一个目录在最后一个目录之前被搜索,因此第一个目录中与第二个目录中同名的命令将被执行,而不是第二个目录中的命令。

还要注意,当您使用时sudo,它会将 PATH 设置为在 中定义的/etc/sudoersPATH secure_path

如果您安装/创建与现有可执行文件同名的可执行文件,则应注意这可能会影响其他程序,而不仅仅是您在交互式 shell 中执行的操作。一个典型的例子是 Anaconda,它会安装一个版本的 Python 并将其bin目录添加到 PATH 中。调用python并期望输入某些内容的系统程序/usr/bin可能会因为输入错误而中断python。通常,请创建具有不同名称的可执行文件。

定义 shell 函数和别名通常可以避免此问题,因为只有读取(或定义它们的任何文件)的 shell 才知道这些~/.bashrc,即交互式(Bash)shell。

您可以看到使用内置命令执行命令时可能运行的所有程序type(假设您尚未定义别名或名为type! 的 shell 函数)。运行 with-a以按 shell 找到它们的顺序查看具有此名称的所有可能命令。

$ type type
type is a shell builtin
$ type -a echo
echo is a shell builtin
echo is /bin/echo
$ type -a ls
ls is aliased to `ls --color=auto'
ls is /bin/ls

因此,一般来说,命令是根据 shell 如何识别它们来区分的,命令其中 shell 尝试执行它所知道的可执行文件。要知道并控制在存在多种可能性时将运行哪个命令,您必须了解调用它的 shell 是如何工作的。


非常感谢伊莱亚·卡根为了在聊天中向我解释这些事情

相关内容