実験目的で、次のように$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
私の質問は次のとおりですwhich
そうでなくても正しいバイナリが呼び出されるのはなぜですか$PATH
?
答え1
functionを使用したので、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
答え2
空の環境では、フルパスを指定しないと実行可能ファイルが見つかりません。試してみてくださいexecvp
。
このsystem
関数はシェルを呼び出します。 Linuxでは、Glibcを使用してシェルを呼び出します/bin/sh
(したがってPATH
必要ありません)。環境の変数に加えて、シェルは独自の変数の一部を定義します。これを実行して定義した内容とenv -i /path/to/shell -c set
実行してエクスポートする内容を表示できますenv -i /path/to/shell -c export
。具体的には、dash と bash (Linux で見つけることができる 2 つのシェル) は、/bin/sh
環境にない場合は「一般」デフォルトに設定されます (エクスポートできません)。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