很长一段时间我都觉得* NIX shell不支持通过相对于当前目录的路径运行可执行文件。此外还有一些帖子解释了为什么在路径中使用工作目录是一种不好的做法。仍然很容易看到以下示例有效:
% cat<<EOF > temp/a
? #!/bin/sh
? echo "Hello looser!"
? EOF
% chmod 750 temp/a
% temp/a
Hello looser!
(我在CentOS和OSX测试过。)
为什么会这样?
更新:它不是纯粹的学术问题,我遇到了二进制文件通过完整路径运行并且上述方式以不同方式工作的情况。
更新2:libc execv
同时接受绝对和相对路径,没有任何问题。因此,在subpath/exe
未能运行时对exe
的支持看起来像bash和tcsh常见的shell特性。它背后肯定有一些逻辑?
答案 0 :(得分:1)
您始终可以通过指定程序的相对路径来执行程序。不要求您必须使用绝对路径。实际上,你执行程序的方式很常见。
答案 1 :(得分:1)
如果您编写command
而没有/
,则shell会在$PATH
中搜索该命令。
如果您使用相对目录撰写dir/command
,则会有/
而shell 不会搜索$PATH
。它相对于当前目录解释它。 dir/command
始终解析为./dir/command
。
将.
放入$PATH
是危险的,因为您可以键入command
打算运行/usr/bin/command
,但如果当前存在./command
,则实际获得.
目录。事实上,不只是$PATH
这是危险的:任何相对路径都是危险的。 $PATH
应该只包含绝对路径。
所以,你说的是相对路径应该隐含地以当前目录作为前缀,当相对路径为空时应被视为在
dir/command
中搜索的方向的例外情况?
是的,你可以这么说。但我更愿意重新构建它。考虑它的更好方法是了解 shell 正在做什么以及内核正在做什么。
解释相对路径由内核隐式处理。当shell执行类似execve("dir/command", ...)
的系统调用来执行程序时,内核知道父进程的当前目录并相对于它解析$PATH
。 shell不必首先将路径转换为绝对路径。内核可以处理绝对路径和相对路径。
但内核对/
一无所知。这是一个shell构造。请记住,shell是一个更高级别的软件。 shell决定如果你键入一个没有cat
的简单命令名,它就不会简单地将该命令传递给内核。如果是,则输入./cat
只会执行/
。没有人想要那个。
相反,shell决定缺少$PATH
意味着它将在/bin
中搜索命令。它会搜索/usr/bin
,$HOME/bin
,.
等。如果您在$PATH
中列出./cat
,那么它也会搜索当前目录 - 不要'那样做!您不希望它运行$PATH
。不,先生。
如果shell在execve("/usr/bin/cat", ...)
中找到可执行文件,那么它会将其转换为绝对路径名并将其传递给内核。内核看到PATH
。
如果是这样,你从一些正式的规范中知道它,我会很感激参考。我确实需要确切地知道。
请参阅bash man page:
如果命令名称不包含斜杠,则shell会尝试找到它。 ...
如果名称...不包含斜杠,则bash会在
T
的每个元素中搜索包含该名称的可执行文件的目录。 ......如果搜索成功,或者命令名称包含一个或多个斜杠,则shell将执行指定的程序....
答案 2 :(得分:0)
这与执行无关。这是因为您可以使用绝对或相对名称命名文件,并且可执行文件只是普通文件。
为什么危险? (
.
)中的PATH
考虑调用cat foo
之类命令的脚本,如果路径中有.
,则可以在同一目录中创建命令cat
代替原来的。