/usr/bin/ "which: no ls in ((null))" という不思議なエラーを返します。

/usr/bin/ "which: no ls in ((null))" という不思議なエラーを返します。

私は単純なシェルプログラムを書いています。 Mac osxとubuntuのシェルで/usr/bin/whichを使うとうまくいきます。 Red Hat Enterprise Linuxクライアントバージョン6.3(San Diego)で同じコマンドを使用すると、「which:no ANYCOMMANDHERE in((null))」エラーが発生します。

これの後ろにどんな直感がありますか?エラーが何を意味するのかさえ見つかりません(私のソースを表示すると役に立つかどうか教えてください)。

編集:私のパスは(シェル内で)次のようになります。

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

ありがとう、ジョン

答え1

文字列は、その引数がNULLポインタの場合、printfの(文字列)変換指定子(null)への引数として一部のCライブラリに置き換えられます。%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はシェル変数(環境変数ではありません!)PATHを生成して照会に使用します。

問題は次のとおりです。 PATHという名前のシェル変数があります。しかし、これは環境変数ではありません。これは、新しく作成されたサブプロセスにエクスポートされないことを意味します。ここで学ぶべきことの一つは、echo $PATHを使うと環境変数PATHが設定されました。 set | grep "^PATH=" と同じ問題がありますが、1 つの方法は以下を使用することです。外部コマンド環境: grep "^path="

シェルセッションの例:

$ 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

達成する目的に応じて、シェルにログインシェルとして機能するように依頼できます。 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では、環境変数(すべてのプロセスに共通)とシェル変数(現在のシェル呼び出しにローカル)が区別されます。両方を参照するために同じ構文を使用します(例:)$PATH。同じ名前のシェル変数と環境変数がある場合は、$PATHシェル変数が引用されます。

[t]cshは別の構文を使用しています置くシェルと環境変数:

set shell_var = foo
setenv env_var bar

(BashなどのBourneベースのシェルは構文と用語が異なります。環境変数は「エクスポートされた」シェル変数、または呼び出しプロセスから継承されたシェル変数です。)

説明する症状によると、シェル変数$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。 1つを設定すると、もう1つが自動的に更新されます。

 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確認してください。$PATHsetenv

答え4

この問題はRedhatとフォークのメカニズムに固有のものであることがわかりました。サブプロセスには、ubuntuやmac osxと同様に、デフォルトの環境変数は提供されません。これは、明示的にenvpを親のenvpに設定する必要があることを意味します(execve呼び出しで)。

私の質問に誤解を招く表現についてお詫び申し上げます。

ご協力ありがとうございます!ジョン

関連情報