这有效
sh /opt/gap-4.11.1/bin/gap.sh
这不起作用
sh gap.sh
并返回错误信息
sh: 0: Can't open gap.sh
但所需的目录位于$PATH
,如确认echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/gap-4.11.1/bin
怎么了?
答案1
虽然 POSIX 允许sh
实现在当前工作目录中找不到何时查找file
,因为这就是(规范所基于的子集)所做的,但它并不需要它,而且现在大多数实现都不需要它(甚至不)因为这是不可取的。$PATH
sh file
file
ksh
sh
sh
mksh
事实上 POSIX 允许这样做并且某些实现确实会导致相反的问题:
sh -- "$file"
POSIX 不保证解释路径存储在 中的文件$file
,因此您必须执行以下操作:
case $file in
('') echo >&2 error;;
(*/*) sh -- "$file";;
(*) sh "./$file";;
esac
可移植地解决它。
这也是为什么你看到人们使用:
sh ./file
当他们想要确保它是file
在当前目录中被解释并且不冒解释$PATH
iffile
碰巧丢失的一些完全不相关的脚本的风险时,就像您在当前工作目录而不是在当前工作目录中./ls
运行命令一样ls
在$PATH
。
该实用程序也存在类似的问题,.
该实用$PATH
程序在$file
不包含/
.虽然 POSIX 不允许$PATH
在未处于 sh 模式时在 bash 或 zsh中找到该文件,但不允许回退到解释当前目录中的文件。 csh
' 相当于.
:source
不进行$PATH
查找。在 中zsh
,source
退回到$PATH
查找。在 中bash
,source
行为类似于.
。
在这里,由于您的脚本位于 中$PATH
,并且假设您具有它的执行权限,因此您只需输入:
gap.sh
为了gap.sh
在 中查找$PATH
。如果脚本没有 shebang,则应由sh
符合 POSIX 的解释器进行解释。
如果你有读权限但没有执行权限,你可以这样做:
sh -c '. gap.sh' sh arguments for gap.sh
如上所示,它将进行$PATH
查找。
作为历史记录,on 过去ksh file
常常首先ksh
进行$PATH
查找。这是支持 setuid 脚本的系统上的一个安全漏洞,您可以这样做:
ln -s /path/to/some/setuid/ksh/script /tmp/file
echo sh > ~/bin/file
PATH=$PATH:~/bin
cd /tmp
并且exec("file", ...)
使用 shebang 调用 which#! /bin/ksh -
将会 /bin/ksh - file
以 setuid 用户身份运行,并且ksh
最终会进行解释~/bin/file
而不是/tmp/file
,因此如果脚本是 setuid root,您将获得 root shell。
答案2
PATH
在本例中,将考虑正在执行的程序sh
。
正如/bin:/opt/gap-4.11.1/bin
您的 中一样PATH
,您应该能够“直接”运行它,运行:
gap.sh
只要有执行权限就可以。