/usr/bin/which 返回神秘错误“which: no ls in ((null))”

/usr/bin/which 返回神秘错误“which: no ls in ((null))”

我正在编写一个简单的 shell 程序。当我在 mac osx 和 ubuntu 中将 /usr/bin/which 与我的 shell 一起使用时,它运行正常。当我在 Red Hat Enterprise Linux Client 6.3 版(圣地亚哥)上使用完全相同的命令时,出现以下错误:“which: no ANYCOMMANDHERE in ((null))”。

这有什么直觉吗?我什至找不到错误的含义(请告诉我显示我的来源是否有帮助)。

编辑:我的路径是(从外壳内部):

$ echo $PATH
/usr/lib64/qt-3.3/bin:/usr/local/bin:/bin:/usr/bin

谢谢,乔恩

答案1

当相应的参数是 NULL 指针时,字符串(null)被一些 C 库替换为 printf 的%s(字符串)转换说明符的参数,例如

 char *path = 0; /* This would normally be = getenv("PATH"). */
 printf ("which: no foobar in (%s)\n", path);

您的 PATH 环境变量似乎未设置或未导出。在这些情况下getenv("PATH")返回 0。最后一种可能性是,您的which实用程序可能存在严重错误。

如果你说它能正常工作吗export PATH

答案2

实际上,这里所有其他人已经回答的问题 - 未设置 PATH,在某种程度上是正确的,但在另一种方面是错误的。

我遇到了同样的问题(使用 bash)。看来,bash“功能”变成了缺失功能:Bash 创建一个 shell 变量(不是环境变量!) PATH,然后将其用于查找。

所以,情况是:存在一个名为 PATH 的 shell 变量。但这不是环境变量。这意味着,它不会导出到新创建的子进程。我们应该从中吸取教训的一件事是,使用 echo $PATH 无法确定是否环境变量 PATH 已设置。与 set | 相同的问题grep "^PATH=" 但是,一种方法是使用外部的命令环境:env | grep "^路径="

shell 会话示例:

$ env -i bash
# A new shell is started with empty environment.
# What follows happens in this new shell:
$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
$ set | grep "^PATH="
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
$ env | grep "^PATH="
$ which ls
which: no ls in ((null))
$ export PATH
$ env | grep "^PATH="
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
$ which ls
/bin/ls

根据您想要实现的目标,您可以要求 shell 充当登录 shell,对于 bash,它是 -l。这样, /etc/profile 和其他文件是默认情况下正确设置 PATH 的源:

$ env -i bash -l
$ which ls
/bin/ls

另一种方法是导出 PATH,请参见上文。

答案3

我可以从 tcsh 重现相同的输出:

env -u PATH which ls
which: no ls in ((null))

在 csh 和 tcsh 中,环境变量(对所有进程通用)和 shell 变量(对 shell 的当前调用而言是本地的)之间存在区别。它使用相同的语法来引用两者,例如$PATH。如果有一个 shell 变量和一个同名的环境变量,则$PATH引用该 shell 变量。

[t]csh 使用不同的语法来shell 与环境变量:

set shell_var = foo
setenv env_var bar

(基于 Bourne 的 shell,例如 bash,具有不同的语法和不同的术语;环境变量是“导出”的 shell 变量,或者是从调用进程继承的 shell 变量。)

根据您描述的症状,您有一个 shell 变量$PATH(无用),但没有同名的环境变量。这通常不应该发生。检查您的.cshrc.tcshrc和/或.login文件中设置 的语句$PATH

您应该能够像这样解决眼前的问题:

setenv PATH "$PATH"   # set the environment variable
unset PATH            # unset the shell variable, just to avoid confusion

unset PATH(在确认一切正常之前,请勿执行此操作。)

只是为了增加一点乐趣,[t]csh 有一个特殊的变量$path(注意小写);它的值是一个由环境变量:的分隔组件组成的数组$PATH。设置其中一个将自动更新另一个:

 setenv PATH /usr/bin:/bin # sets $path to ( /usr/bin /bin )
 set path = ( /usr/local/bin $path ) # sets $PATH to '/usr/local/bin:/usr/bin:/bin'

这可能很方便,但如果您愿意,您可以忽略$path并处理$PATH.只需确保您设置的是环境变量$PATH(使用setenv),而不是无用的同名 shell 变量。

答案4

事实证明,这个问题是 Redhat 和分叉机制特有的。子进程没有被赋予默认的环境变量,而在 ubuntu 和 mac osx 中却有。这意味着我必须显式地将 envp 设置为父级的(在对 execve 的调用中)。

对我的问题中的误导性措辞表示歉意(尽管很难准确指出这些类型的事情)。

感谢您的帮助!乔恩

相关内容