在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语法的情况下才有效.
.一个用于./B或. B语法.
我明白,使用点空格(即A)语法执行,而不分拣到子shell,但是我看不到这可能导致我遵守的行为,因为该文件显然在那里.有没有关于语法或父/子进程工作空间细微差别的东西?魔法?
UPDATE1:当我使用bash时,添加了指示脚本可能已经在ksh中开发的信息.
UPDATE2:添加检查以验证$PATH是一样的.
UPDATE3:该脚本说它是为ksh编写的,但它正在bash中运行.为了回应Kenster的答案,我发现运行bash -posix. B在命令行失败.这表示命令行和脚本之间的环境差异在于后者以符合POSIX的模式运行bash,而命令行不是.看起来更近一点,我在bash手册页面看到这一点:
When invoked as sh,bash enters posix mode after the startup files are read.
A的shebang确实是#!/ bin / sh.
总而言之,当我运行A没有点空间语法,它是分支到自己的subshell,这是符合POSIX的模式,因为shebang是#!/ bin / sh(而不是例如#!/ bin / bash.是导致A无法找到B的命令行和脚本运行时环境之间的关键区别.
解决方法
ls /tmp
这里的ls不包含/字符,因此shell会在名为ls的文件中搜索命令路径中的目录(PATH环境变量的值).如果找到一个,它将执行该文件.在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的脚本假定为“.”是你的路径的一部分.在我看来,这是脚本中的一个错误.许多人没有运行.在他们的路上,脚本不应该依赖于这一点.
编辑:
你说脚本使用ksh,而你正在使用bash. Ksh遵循POSIX标准 – 实际上,KSH是POSIX标准的基础 – 并且总是按照我所描述的方式搜索命令路径. Bash有一个名为“POSIX模式”的标志,它控制了POSIX标准的严格程度.当不在POSIX模式下 – 人们通常使用它时,如果在命令路径中找不到该文件,bash将检查要获取的文件的当前目录.
如果你要运行bash -posix并运行.在Bash实例中,你应该会发现它不行.