我正在尝试使用现有的代码库,但遇到了问题。 总之,我执行一个shell脚本(我们称之为A
),其第一个行为是调用另一个脚本( B
)。 脚本B
在我的当前目录(我正在使用的程序的要求)。 该软件的手册引用了bash
,但是A
中的注释表明它是用ksh
开发的。 我一直在bash
运行。
在A
里面,执行B
的行很简单:
. B
它使用“点空间”语法来调用程序。 它不会像sudo
一样做任何exception的事情。
当我打电话没有点空间语法,即:
./A
它总是错误,说它找不到文件B
我添加了pwd
, ls
, whoami
, echo $SHELL
,并将echo $PATH
行回显为A
进行debugging,并确认B
实际上就在那里,脚本运行时与我在命令提示符下的$SHELL
相同,脚本是和我一样的用户,并且脚本和我一样具有相同的searchpath$PATH
。 我也validation,如果我这样做:
. B
在命令行,它工作得很好。 但是,如果我将A
内部的语法更改为:
./B
相反,然后A
执行成功。
同样,如果我用点空间语法执行A
,那么两者都是. B
. B
和./B
工作。
总结 :
./A
仅在A
包含./B
语法时才有效。
. A
. A
与./B
或. B
. B
语法。
我明白,使用点空间(即. A
)语法执行时不会分叉到一个子shell,但我不明白这可能会导致我观察到的行为,因为该文件显然是在那里。 有什么我缺less的语法或父/子过程工作区的细微差别? 魔法?
更新1 :添加信息,指示脚本可能已经在ksh
开发,而我正在使用bash
。
更新2 :添加检查来validation$PATH
是相同的。
UPDATE3 :脚本说它是为ksh
编写的,但是它在bash
运行。 为了回应Kenster的回答,我发现那时正在运行bash -posix
. B
. B
在命令行失败。 这表明命令行和脚本之间的环境差异在于后者在符合POSIX标准的模式下运行bash
,而命令行却不是。 仔细看,我在bash
man
页中看到这个:
当作为sh调用时,bash在读取启动文件后进入posix模式。
A
的shebang
确实是#!/bin/sh
。
总而言之,当我运行没有点空间语法的A
时,它分叉到自己的子shell,它是POSIX兼容模式,因为shebang
是#!/bin/sh
(而不是,例如#!/bin/bash
。是导致A
无法findB
的命令行和脚本运行时环境之间的关键区别。
让我们从命令路径的工作原理和使用时间开始。 当你运行一个像这样的命令:
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
. 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
不存在,即使当前目录中有一个名为B
的文件。 正如上面所讨论的那样,shell会搜索你的B
的命令路径,因为B
没有包含任何/字符。 搜索命令时,shell不会自动搜索当前目录。 它只搜索当前目录,如果该目录是命令路径的一部分。
总之, . B
. B
可能失败,因为你没有“。” (当前目录)在您的命令路径中,而试图源B
的脚本假定“。” 是你的路径的一部分。 在我看来,这是脚本中的一个错误。 很多人跑没有“。” 在他们的道路上,脚本不应该依赖于此。
编辑:
你说这个脚本使用ksh
,而你正在使用bash
。 Ksh遵循POSIX标准 – 实际上,KSH是POSIX标准的基础 – 并且总是像我所描述的那样搜索命令路径。 Bash有一个叫做“POSIX模式”的标志,它控制着POSIX标准的严格程度。 当不在POSIX模式下 – 人们普遍使用它的方式 – 如果在命令路径中没有找到文件,bash将检查当前目录中的文件来源。
如果你要运行bash -posix
并运行. B
. B
在这个bash实例中,你会发现它不起作用。