为什么我们在 Linux/UNIX 中使用“./”(点斜线)来执行文件?

Ren*_*h G 112 command-line executable

为什么我们./filename在linux中使用执行文件?

为什么不像其他命令一样输入它gccls等等...

mat*_*tdm 122

其他人给出的字面答案是:因为当前目录不在您的$PATH.

为什么?简而言之,就是为了安全。如果您正在查看其他人的主目录(或 /tmp),并仅键入gccls,您想知道您正在运行真实的主目录,而不是您的恶作剧朋友编写的删除您所有文件的恶意版本。另一个例子是testor [,如果你的 shell 没有内置命令,它可能会覆盖 shell 脚本中的这些命令。

.作为最后一个在你的路径条目是比较安全,但也有其他的攻击,这使得利用这一点。一个简单的方法是利用常见的拼写错误,例如slls-l。或者,找到一个碰巧没有安装在这个系统上的通用命令——vim例如,因为系统管理员有高于平均水平的可能性来输入。

这听起来太理论化了吗?它在很大程度上是,但它肯定会在现实中发生,尤其是在多用户系统上。事实上,这里有一个来自该站点的示例,其中管理员切换到用户的主目录并发现ps被该名称的可执行文件屏蔽。


bad*_*adp 99

在 Linux、UNIX 及相关操作系统中,.表示当前目录。由于要在当前目录运行文件和目录不在你的$PATH,你需要的./位告诉外壳,其中可执行文件。因此,./foo意味着运行foo此目录中调用的可执行文件。

您可以使用typewhich获取在您的$PATH.

  • @Michael security and sanity:如果它首先在 `.` 中搜索,那么这将是一个安全问题,例如,您或其他人可以替换 `ls`(一个简单的病毒/特洛伊木马:使用名为 `ls 的可执行文件制作一个 zip 文件` 在其中,当有人搜索时,他们运行这个可执行文件,那个……)。如果它最后在 `.` 中搜索,那么你可能会花很长时间发疯,不知道为什么你的程序不工作(例如,你制作了一个名为 test 的程序,而不是运行你的程序,它运行系统测试程序。它不产生任何输出)。 (29认同)
  • 在当前目录中执行程序是很常见的。为什么 shell 不在那里搜索?它首先在 . 中搜索,然后在 $PATH 中搜索。 (8认同)
  • 还有一些 `alias` 可能会妨碍你,而不仅仅是 `$PATH`。 (2认同)
  • @jcubic 这是个坏主意。请参阅上面的评论。过去 DOS 会在当前目录中进行搜索,并且这种行为会被带到 Windows cmd 中,这会带来很多安全问题。MS 在 PowerShell 中修复了该问题,现在您必须使用 .\ 在当前目录中运行该程序 (2认同)
  • @ctrl-alt-delor:八十年代末我在大学时,这是一种常见的(被禁止的)策略。编写一个“ls”程序并将其放在您的主文件夹中,以防其他人窥探。该程序被称为“get shell”IIRC。它会尝试获取运行该命令的用户的凭据 - 然后可能会打印一个虚假的目录列表以使他们不知情。 (2认同)

Sim*_*ker 45

如果您的意思是,为什么在开始时需要 ./ - 那是因为(与在 Windows 中不同),默认情况下当前目录不是您路径的一部分。如果你运行:

$ ls
Run Code Online (Sandbox Code Playgroud)

您的 shellls在 PATH 环境变量中的目录中查找(echo $PATH查看它),并运行ls它找到的第一个名为的可执行文件。如果您键入:

$ a.out
Run Code Online (Sandbox Code Playgroud)

shell 也会这样做 - 但它可能找不到名为 a.out 的可执行文件。您需要告诉外壳 a.out 在哪里 - 它在当前目录 (.) 中,然后路径是./a.out.

如果你问为什么它被称为“a.out”,那只是 gcc 的默认输出文件名。您可以使用 -o 命令行参数更改它。例如:

$ gcc test.c -o test
$ ./test
Run Code Online (Sandbox Code Playgroud)

  • / 是 Linux 中的路径分隔符,因此您可以使用它来分隔目录 (.) 和文件名 (a.out)。没有它,您将拥有 .a.out,它本身就是一个有效的文件名。(试试 `touch .a.out; ls -lA` 来看看这个。) (8认同)
  • 这就是你在 Unix 中指定路径的方式,`<dir>/<file>` 所以你基本上是说在当前目录中执行一个文件,它由 `./test` 表示 (5认同)
  • 红帽 Linux 9?是时候升级了! (3认同)

小智 6

您可以尝试添加:.到 $PATH 变量中。

尝试 ALT+F2 并输入:gksudo gedit /etc/environment如果运行 Linux/GTK(如果使用 Ubuntu,这是您所拥有的)。

但是,我强烈建议您不要这样做。很糟糕很糟糕很糟糕。

您知道,自 1970 年以来,此类事情就这样运作了。当前目录未包含在 $PATH 中是有原因的。

. 是当前目录

.something将是一个隐藏文件(键入“ALT+”使它们出现在 Nautilus 中,或尝试“ ls -la”。

./someProgram.sh 是您键入以在当前目录中运行可执行文件 someProgram.sh 的内容。

.somethingElse 这意味着您在当前目录中有一个隐藏的可执行文件,这是一个坏主意。


Cir*_*郝海东 5

更完整的规则实际上是:如果/路径中有斜杠,则不搜索PATH

在我们讨论基本原理之前,您应该首先了解这个事实:运行以下任一:

bin/someprog
Run Code Online (Sandbox Code Playgroud)

或者:

/bin/someprog
Run Code Online (Sandbox Code Playgroud)

或者:

cd bin
./myexec
Run Code Online (Sandbox Code Playgroud)

执行时bin/someprog无需搜索PATH变量,原因完全相同:全部bin/someprog,/bin/someprog且其中./someprog有斜杠。/

someprogalone 没有斜杠/,因此仅在 中搜索PATH

POSIX 7在以下位置指定了此规则:http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_09_01_01

小路

[...] 如果正在查找的路径名包含<slash>,则不应执行通过路径前缀的搜索。

/POSIX PATH 规则的基本原理

假设运行:

someprog
Run Code Online (Sandbox Code Playgroud)

会搜索:

  • 首先相对于 CWD
  • 相对于 PATH 之后

然后,如果你想从你的发行版运行/bin/someprog,你就这样做了:

someprog
Run Code Online (Sandbox Code Playgroud)

它有时会起作用,但有时会失败,因为您可能位于包含另一个不相关程序的目录中someprog

因此,您很快就会发现这是不可靠的,当您想要使用 PATH 时,您最终将始终使用绝对路径,从而违背了 PATH 的目的。

这也是为什么在 PATH 中包含相对路径是一个非常糟糕的主意。我在看着你,node_modules/bin

相反,假设运行:

./someprog
Run Code Online (Sandbox Code Playgroud)

会搜索:

  • 首先相对于 PATH
  • 相对于 CWD 之后

然后,如果您刚刚someprog从 git 存储库下载了一个脚本并想从 CWD 运行它,您将永远无法确定这是将运行的实际程序,因为您的发行版可能有:

/bin/someprog
Run Code Online (Sandbox Code Playgroud)

这是你去年圣诞节后喝太多酒后安装的某个软件包的 PATH 路径。

因此,您将再次被迫始终使用完整路径运行相对于 CWD 的本地脚本,以了解您正在运行的内容:

"$(pwd)/someprog"
Run Code Online (Sandbox Code Playgroud)

这也会非常烦人。

您可能会想出的另一条规则是:

相对路径仅使用 PATH,绝对路径仅使用 CWD

但这再次迫使用户始终对非 PATH 脚本使用绝对路径"$(pwd)/someprog"

路径/搜索规则为 about 问题提供了一个简单易记的解决方案:

  • 斜线:不使用PATH
  • 无斜线:仅使用PATH

通过当前目录中的文件可以表示为 或 ,这使得始终了解您正在运行的内容变得非常容易./somefilesomefile因此它赋予其中之一特殊的含义。

有时,有点烦人,您无法搜索some/prog相对于 的内容PATH,但我没有看到更明智的解决方案。