実験の目的で、$PATH
を出力し、次のようにwhich
を呼び出すバイナリを作成しました。
#include <stdlib.h>
#include <stdio.h>
int main() {
char *path = getenv("PATH");
if (path)
printf("got a path: %s\n", path);
else
printf("got no path\n");
system("which which");
return 0;
}
空の環境で実行すると
env -i ./printpath
次のプリントアウトが表示されます。
got no path
/usr/bin/which
私の質問は次のとおりです。$PATH
がない場合でも、正しいwhich
バイナリが呼び出されるのはなぜですか?
system
関数を使用したので、別のシェルを使用してコマンドwhich which
を実行します。 man system
から:
DESCRIPTION
system() executes a command specified in command by calling /bin/sh -c
command, and returns after the command has been completed. During exe‐
cution of the command, SIGCHLD will be blocked, and SIGINT and SIGQUIT
will be ignored.
which which
コマンドをecho $PATH
に変更した場合:
$ env -i ./a.out
got no path
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
execve
の代わりにsystem
を使用するようにコードを変更すると、期待どおりの出力が得られます。
#include <stdlib.h>
#include <stdio.h>
int main() {
char *path = getenv("PATH");
if (path)
printf("got a path: %s\n", path);
else
printf("got no path\n");
execve("echo $PATH");
return 0;
}
コンパイルして実行します。
$ gcc test.c && env -i ./a.out
got no path
空の環境では、フルパスを指定しない限り実行可能ファイルは見つかりません。 execvp
で試してみてください。
system
関数はシェルを呼び出します— Linux with Glibcでは、/bin/sh
を呼び出します(したがって、PATH
は必要ありません)。シェルは、環境からの変数に加えて、独自のいくつかの変数を定義します。 env -i /path/to/Shell -c set
を実行することで定義されているものと、env -i /path/to/Shell -c export
を実行することでエクスポートされるものを確認できます。特に、ダッシュとbashの両方(Linuxで/bin/sh
として検出される可能性が高い2つのシェル)は、環境に1つもない場合、PATH
を「正常な」デフォルトに設定します(ただし、エクスポートはしません)。 。シェルが異なれば、設定される値も異なるか、まったく設定されません。
$ env -i bash -c 'echo $PATH'
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
$ env -i dash -c 'echo $PATH'
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
$ env -i mksh -c 'echo $PATH'
/usr/bin:/bin
$ env -i ksh93 -c 'echo $PATH'
$ env -i zsh -c 'echo $PATH'
/bin:/usr/bin:/usr/ucb:/usr/local/bin
$ env -i csh -c 'echo $PATH'
PATH: Undefined variable.
$ env -i tcsh -c 'echo $PATH'
PATH: Undefined variable.
私のマシン(そして明らかにあなたのマシン)では、which
自体が/bin/sh
スクリプトです。 system
によって呼び出されたシェルは、独自のパス変数を使用してwhich
プログラムを検索しますが、それをエクスポートしません。 which
スクリプト自体を実行するシェルは、内部で使用するためにPATH
変数も定義します。