为什么要这样运作?

为什么要这样运作?

我正在读索贝尔的书Linux 命令、编辑器和 Shell 编程实用指南、4e,我目前正在开始第 5 章的 shell 基础知识。

在第 135 页,索贝尔解释说

从命令行,您可以通过三种方式指定希望 shell 执行的文件名: 作为绝对路径名(以斜杠 [/] 开头;第 90 页),作为相对路径名(包括斜杠,但不以斜杠开头;第 91 页),或作为简单的文件名(无斜杠)。

此外,他写道

当您指定一个简单的文件名(无斜杠)时,shell 会在目录列表中搜索与指定名称匹配且您具有执行权限的文件名。 shell 不会查看所有目录,而只会查看由名为 PATH 的变量指定的目录。

重要的是,他指出工作目录通常是不是路径的一部分。

因此,我的问题是了解 shell 如何(为什么?)根据简单文件名是作为命令传递还是作为命令参数传递而表现出不同的行为。

直到本书的这一点,我已经将简单文件名理解为相对路径的特殊情况,其中我们不需要斜杠,因为给定文件直接是工作目录的子级。因此,例如,如果我foo的主目录中有一个名为的文件,并且我位于我的主目录中,那么

ls -l foo

将为我提供有关的详细信息foo(我已传递foo,一个简单的文件名,作为 的参数ls)。

现在看来,这种行为是不同的对于本身就是程序/文件/可执行文件的命令(我希望您会原谅我的天真和缺乏精确性)。当我简单地向命令行提供以下内容时,Sobell 似乎是在说 shell 会查找 PATH 中的目录,而不一定会查找工作目录(除非它是 PATH 的一部分):

ls

也就是说,在将简单文件名作为命令而不是参数给出的特定情况下,shell 在其外观方面的行为是不同的。这种理解正确吗?

答案1

是的。你的理解是正确的。

/tmp如果您移动到该目录并创建一个包含单词“text”的文本文件,您就会看到这一点:

cd /tmp
echo 'text' > file.txt

现在这些命令都是可以互换的:

cat /tmp/file.txt
cat ./file.txt
cat file.txt

每个命令都会显示文件的文本内容。

但!如果您现在创建一个可执行文件文件:

cd /tmp
printf '#!/usr/bin/env bash\n\necho "hi"\n' > executable
chmod a+x executable

您仍然可以像以前一样访问该文件,因为它仍然是一个文件:

cat /tmp/executable
cat ./executable
cat executable

但是,在 Bash shell 中,您只能像这样运行它:

/tmp/executable
./executable

您不能像这样运行该文件:

executable

这将导致 shell 在各个 $PATH 位置搜索匹配的可执行文件。由于没有,shell 将放弃并返回错误 127(“未找到命令‘可执行文件’”)。

为什么要这样运作?

这是一个有意识的安全决定!如果黑客在您的目录中放置一个可执行文件/tmp,其名称与日常 shell 命令之一(例如命令ls)相匹配,那么您可能会在不知情的情况下运行恶意命令。

解决方案是让 shell 仅执行您已安装在 $PATH 位置的那些受信任的命令。

如果有一个时候你如果想要从当前工作目录运行一次性脚本,您仍然可以通过指定可执行文件的路径(例如./executable/tmp/executable)来实现这一点。通过提供额外的路径信息,您就表明您确实希望在该位置运行可执行文件,并且没有被欺骗这样做!

相关内容