sh 不考虑 $PATH

sh 不考虑 $PATH

这有效

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,因为这就是(规范所基于的子集)所做的,但它并不需要它,而且现在大多数实现都不需要它(甚至不)因为这是不可取的。$PATHsh filefilekshshshmksh

事实上 POSIX 允许这样做并且某些实现确实会导致相反的问题:

sh -- "$file"

POSIX 不保证解释路径存储在 中的文件$file,因此您必须执行以下操作:

case $file in
  ('') echo >&2 error;;
  (*/*) sh -- "$file";;
  (*) sh "./$file";;
esac

可移植地解决它。

这也是为什么你看到人们使用:

sh ./file

当他们想要确保它是file在当前目录中被解释并且不冒解释$PATHiffile碰巧丢失的一些完全不相关的脚本的风险时,就像您在当前工作目录而不是在当前工作目录中./ls运行命令一样ls$PATH

该实用程序也存在类似的问题,.该实用$PATH程序在$file不包含/.虽然 POSIX 不允许$PATH在未处于 sh 模式时在 bash 或 zsh中找到该文件,但不允许回退到解释当前目录中的文件。 csh' 相当于.source不进行$PATH查找。在 中zshsource退回到$PATH查找。在 中bashsource行为类似于.

在这里,由于您的脚本位于 中$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

只要有执行权限就可以。

相关内容