点空间与点斜杠之间的文件执行 [英] File execution with dot space versus dot slash

查看:59
本文介绍了点空间与点斜杠之间的文件执行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用现有的代码库,但是遇到了问题.简而言之,我执行一个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中添加了pwdlswhoamiecho $SHELLecho $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.

Ashebang确实是#!/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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆