点空间与点斜杠之间的文件执行 [英] File execution with dot space versus dot slash
问题描述
我正在尝试使用现有的代码库,但是遇到了问题.简而言之,我执行一个shell脚本(我们称其为A
),其第一个动作是调用另一个脚本(B
).脚本B
在我当前的目录中(我正在使用的程序的要求).该软件手册引用了bash
,但是A
中的注释表明它是在ksh
中开发的.到目前为止,我一直在bash
中进行操作.
I am attempting to work with an existing library of code but have encountered an issue. In short, I execute a shell script (let's call this one A
) whose first act is to call another script (B
). Script B
is in my current directory (a requirement of the program I'm using). The software's manual makes reference to bash
, however comments in A
suggest it was developed in ksh
. I've been operating in bash
so far.
在A
内,执行B
的行很简单:
Inside A
, the line to execute B
is simply:
. B
它使用点空格"语法来调用程序.它不会像sudo
那样执行任何异常操作.
It uses the "dot space" syntax to call the program. It doesn't do anything unusual like sudo
.
当我不使用点空间语法调用A
时,即:
When I call A
without dot space syntax, i.e.:
./A
总是出错,提示它找不到文件B
.我在A
中添加了pwd
,ls
,whoami
,echo $SHELL
和echo $PATH
行以进行调试,并确认B
实际上就在其中,脚本正在使用相同的$PATH
.我还验证了是否可以这样做:
it always errors saying it cannot find the file B
. I added pwd
, ls
, whoami
, echo $SHELL
, and echo $PATH
lines to A
to debug and confirmed that B
is in fact right there, the script is running with the same $SHELL
as I am at the command prompt, the script is the same user as I am, and the script has the same search path $PATH
as I do. I also verified if I do:
. B
在命令行中
正常工作.但是,如果我将A
中的语法更改为:
at the command line, it works just fine. But, if I change the syntax inside A
to:
./B
代替,然后A
成功执行.
instead, then A
executes successfully.
类似地,如果我使用点空间语法执行A
,那么. B
和./B
都可以工作.
Similarly, if I execute A
with dot space syntax, then both . B
and ./B
work.
总结:
./A
仅在A
包含./B
语法的情况下有效.
. A
适用于使用./B
或. B
语法的A
.
Summarizing:
./A
only works if A
contains ./B
syntax.
. A
works for A
with either ./B
or . B
syntax.
我知道使用点空间(即. A
)语法无需分叉到子外壳即可执行,但是鉴于文件显然就在那儿,因此我看不到这将如何导致我观察到的行为.关于语法或父/子流程工作区的细微差别,我缺少什么吗?魔法?
I understand that using dot space (i.e. . A
) syntax executes without forking to a subshell, but I don't see how this could result in the behavior I'm observing given that the file is clearly right there. Is there something I'm missing about the nuances of syntax or parent/child process workspaces? Magic?
UPDATE1 :添加了表明该脚本可能是在bash
中开发的信息,而我正在使用bash
.
UPDATE2 :添加了检查以确认$PATH
是否相同.
UPDATE1: Added info indicating that the script may have been developed in ksh
, while I'm using bash
.
UPDATE2: Added checking to verify $PATH
is the same.
UPDATE3 :脚本说它是为ksh
编写的,但是正在bash
中运行.响应Kenster的回答,我发现在命令行上运行bash -posix
然后. B
失败.这表明命令行和脚本之间的环境差异在于脚本和脚本以POSIX兼容模式运行bash
,而命令行不是.再往前看,我在bash
man
页面中看到了这一点:
UPDATE3: The script says it was written for ksh
, but it is running in bash
. In response to Kenster's answer, I found that running bash -posix
then . B
fails at the command line. That indicates that the difference in environments between the command line and the script is that the latter is running bash
in a POSIX-compliant mode, whereas the command line is not. Looking a little closer, I see this in the bash
man
page:
以sh调用时,bash在读取启动文件后进入posix模式.
When invoked as sh, bash enters posix mode after the startup files are read.
A
的shebang
确实是#!/bin/sh
.
总而言之,当我在不使用点空间语法的情况下运行A
时,它将分叉到其自己的子外壳,该子外壳处于POSIX兼容模式,因为shebang
是#!/bin/sh
(而不是例如#!/bin/bash
.
In summary, when I run A
without dot space syntax, it's forking to its own subshell, which is in POSIX-compliant mode because the shebang
is #!/bin/sh
(instead of, e.g., #!/bin/bash
. This is the critical difference between the command line and script runtime environments that leads to A
being unable to find B
.
推荐答案
让我们从命令路径的工作方式和使用时间开始.当您运行以下命令时:
Let's start with how the command path works and when it's used. When you run a command like:
ls /tmp
此处的ls
不包含/字符,因此外壳程序会在命令路径(PATH环境变量的值)中的目录中搜索名为ls
的文件.如果找到一个,它将执行该文件.对于ls
,它通常位于/bin
或/usr/bin
中,并且这两个目录通常都在您的路径中.
The ls
here doesn't contain a / character, so the shell searches the directories in your command path (the value of the PATH environment variable) for a file named ls
. If it finds one, it executes that file. In the case of ls
, it's usually in /bin
or /usr/bin
, and both of those directories are typically in your path.
在命令字中使用/发出命令时:
When you issue a command with a / in the command word:
/bin/ls /tmp
shell不会搜索命令路径.它专门查找文件/bin/ls
并执行.
The shell doesn't search the command path. It looks specifically for the file /bin/ls
and executes that.
运行./A
是运行名称中带有/的命令的示例.外壳程序不搜索命令路径;它不会搜索命令路径.它专门查找名为./A
的文件并执行该文件. ."是当前工作目录的简写,因此./A
指的是应该在当前工作目录中的文件.如果文件存在,它将像其他任何命令一样运行.例如:
Running ./A
is an example of running a command with a / in its name. The shell doesn't search the command path; it looks specifically for the file named ./A
and executes that. "." is shorthand for your current working directory, so ./A
refers to a file that ought to be in your current working directory. If the file exists, it's run like any other command. For example:
cd /bin
./ls
可以运行/bin/ls
.
运行. A
是 sourcing 文件的示例.源文件必须是包含shell命令的文本文件.它由当前shell执行,而无需启动新进程.查找源文件的方式与找到命令的方式相同.如果文件名包含/,则外壳程序将读取您命名的特定文件.如果文件名不包含/,则外壳程序会在命令路径中查找它.
Running . A
is an example of sourcing a file. The file being sourced must be a text file containing shell commands. It is executed by the current shell, without starting a new process. The file to be sourced is found in the same way that commands are found. If the name of the file contains a /, then the shell reads the specific file that you named. If the name of the file doesn't contain a /, then the shell looks for it in the command path.
. A # Looks for A using the command path, so might source /bin/A for example
. ./A # Specifically sources ./A
因此,即使当前目录中有一个名为B
的文件,您的脚本也会尝试执行. B
并无法声明B
不存在.如上所述,shell将在命令路径中搜索B
,因为B
不包含任何/字符.搜索命令时,shell不会自动搜索当前目录.如果该目录是命令路径的一部分,则仅搜索当前目录.
So, your script tries to execute . B
and fails claiming that B
doesn't exist, even though there's a file named B
right there in your current directory. As discussed above, the shell would have searched your command path for B
because B
didn't contain any / characters. When searching for a command, the shell doesn't automatically search the current directory. It only searches the current directory if that directory is part of the command path.
简而言之,. B
可能由于没有."而失败. (当前目录)在您的命令路径中,并且试图获取B
的脚本假定为.".是你的道路的一部分.我认为,这是脚本中的错误.很多人都没有.".在他们的路径中,脚本不应该依赖于此.
In short, . B
is probably failing because you don't have "." (current directory) in your command path, and the script which is trying to source B
is assuming that "." is part of your path. In my opinion, this is a bug in the script. Lots of people run without "." in their path, and the script shouldn't depend on that.
您说脚本在使用bash
时使用了ksh
. Ksh遵循POSIX标准-实际上,KSH是POSIX标准的基础-始终按照我所描述的那样搜索命令路径. Bash具有一个称为"POSIX模式"的标志,该标志控制其严格遵循POSIX标准的程度.如果不在POSIX模式下(人们通常会使用它),则bash会在命令路径中找不到该文件的情况下,检查当前目录中的源文件.
You say the script uses ksh
, while you are using bash
. Ksh follows the POSIX standard--actually, KSH was the basis for the POSIX standard--and always searches the command path as I described. Bash has a flag called "POSIX mode" which controls how strictly it follows the POSIX standard. When not in POSIX mode--which is how people generally use it--bash will check the current directory for the file to be sourced if it doesn't find the file in the command path.
如果要在该bash实例中运行bash -posix
并运行. B
,应该会发现它不起作用.
If you were to run bash -posix
and run . B
within that bash instance, you should find that it won't work.
这篇关于点空间与点斜杠之间的文件执行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!