我正在尝试使用现有的代码库但遇到了问题。简而言之,我执行一个shell脚本(让我们称之为A
),其第一幕是调用另一个脚本(B
)。脚本B
位于我当前的目录中(我正在使用的程序的要求)。该软件的手册引用了bash
,但A
中的评论表明它是在ksh
中开发的。到目前为止,我一直在bash
开展工作。
在A
内,执行B
的行只是:
. B
它使用“点空间”语法来调用程序。它不像sudo
那样做任何不寻常的事情。
当我在没有点空格语法的情况下调用A
时,即:
./A
总是错误,说它无法找到文件B
。我将pwd
,ls
,whoami
,echo $SHELL
和echo $PATH
行添加到A
以进行调试并确认B
是事实上,在那里,脚本运行时与我在命令提示符下的$SHELL
相同,脚本与我的用户相同,并且脚本与我具有相同的搜索路径$PATH
做。我还验证了我是否:
. B
在命令行,它工作得很好。但是,如果我将A
内的语法更改为:
./B
相反,然后A
成功执行。
同样,如果我使用点空间语法执行A
,那么. B
和./B
都可以正常工作。
综述:
仅当./A
包含A
语法时,./B
才有效
. A
适用于A
语法的./B
或. B
。
据我所知,使用点空间(即. A
)语法执行时不会分支到子shell,但我不知道如果文件显然就在那里,这会导致我观察到的行为。对于语法或父/子进程工作空间的细微差别,我有什么遗漏吗?魔法?
UPDATE1 :添加了一些信息,表明该脚本可能是在ksh
中开发的,而我正在使用bash
。
UPDATE2 :添加了检查以验证$PATH
是否相同。
UPDATE3 :脚本说它是为ksh
编写的,但它在bash
中运行。在回答Kenster的回答时,我发现在命令行运行bash -posix
然后. B
失败。这表明命令行和脚本之间的环境差异是后者在POSIX兼容模式下运行bash
,而命令行则不是。仔细观察,我在bash
man
页面中看到了这一点:
当调用sh时,bash在读取启动文件后进入posix模式。
shebang
的{{1}}确实是A
。
总之,当我在没有点空间语法的情况下运行#!/bin/sh
时,它会分支到它自己的子shell,因为A
是shebang
,所以它处于POSIX兼容模式(而不是,例如,#!/bin/sh
。这是命令行和脚本运行时环境之间的关键区别,导致#!/bin/bash
无法找到A
。
答案 0 :(得分:22)
让我们从命令路径的工作原理以及何时使用它开始。当您运行如下命令时:
ls /tmp
此处ls
不包含/字符,因此shell会搜索命令路径中的目录(PATH环境变量的值)以查找名为ls
的文件。如果找到一个,则执行该文件。如果是ls
,则通常位于/bin
或/usr/bin
,这两个目录通常位于您的路径中。
在命令字中使用/发出命令时:
/bin/ls /tmp
shell不会搜索命令路径。它专门查找文件/bin/ls
并执行该文件。
运行./A
是运行名称中包含/的命令的示例。 shell不搜索命令路径;它专门查找名为./A
的文件并执行它。 ""是您当前工作目录的简写,因此./A
指的是应该位于当前工作目录中的文件。如果该文件存在,它将像任何其他命令一样运行。例如:
cd /bin
./ls
可以运行/bin/ls
。
正在运行. A
是采购文件的示例。源文件必须是包含shell命令的文本文件。它由当前shell执行,无需启动新进程。找到源文件的方式与找到命令的方式相同。如果文件名包含/,则shell将读取您指定的特定文件。如果文件的名称不包含/,则shell在命令路径中查找它。
. 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不会自动搜索当前目录。它只搜索当前目录,如果该目录是命令路径的一部分。
简而言之,. B
可能会失败,因为你没有"。"您的命令路径中的(当前目录),并且尝试源B
的脚本假定"。"是你的道路的一部分。在我看来,这是脚本中的一个错误。很多人没有"。#34;在他们的道路上,剧本不应该依赖于此。
编辑:
当您使用ksh
时,您说脚本使用bash
。 Ksh遵循POSIX标准 - 实际上,KSH是POSIX标准的基础 - 并且总是按照我的描述搜索命令路径。 Bash有一个名为" POSIX模式"它控制着它遵循POSIX标准的严格程度。当不处于POSIX模式时 - 人们通常使用它 - 如果在命令路径中找不到该文件,bash将检查当前目录中是否有源文件。
如果您要在该bash实例中运行bash -posix
并运行. B
,您会发现它无法正常工作。