![/usr/bin/which 返回神秘错误“which: no ls in ((null))”](https://linux22.com/image/26223/%2Fusr%2Fbin%2Fwhich%20%E8%BF%94%E5%9B%9E%E7%A5%9E%E7%A7%98%E9%94%99%E8%AF%AF%E2%80%9Cwhich%3A%20no%20ls%20in%20((null))%E2%80%9D.png)
我正在编写一个简单的 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 的调用中)。
对我的问题中的误导性措辞表示歉意(尽管很难准确指出这些类型的事情)。
感谢您的帮助!乔恩