![区分用户定义的可执行文件与预先存在的可执行文件](https://linux22.com/image/1156903/%E5%8C%BA%E5%88%86%E7%94%A8%E6%88%B7%E5%AE%9A%E4%B9%89%E7%9A%84%E5%8F%AF%E6%89%A7%E8%A1%8C%E6%96%87%E4%BB%B6%E4%B8%8E%E9%A2%84%E5%85%88%E5%AD%98%E5%9C%A8%E7%9A%84%E5%8F%AF%E6%89%A7%E8%A1%8C%E6%96%87%E4%BB%B6.png)
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 将按照此顺序继续查找命令,并执行找到的第一件事然后停止寻找:
- 是否有一个同名的 shell 函数?
- 是否有一个同名的内置 shell?
- 是否有命令哈希表用这个名字?
- 任何 PATH 目录中是否有同名的命令?
因此,搜索 PATH 是最后的手段。请注意,PATH 是按从左到右的顺序搜索的。PATH 中的第一个目录在最后一个目录之前被搜索,因此第一个目录中与第二个目录中同名的命令将被执行,而不是第二个目录中的命令。
还要注意,当您使用时sudo
,它会将 PATH 设置为在 中定义的/etc/sudoers
PATH 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 是如何工作的。
非常感谢伊莱亚·卡根为了在聊天中向我解释这些事情。