私はDebian GNU / Linux 9を使用しています。わかりました/proc
非常に特別な、わかりました何/proc/self
ですか。
このコマンド
sh -c '/bin/cat /proc/self/comm - </proc/self/comm'
生産する
cat
sh
dash
代わりに使用するとパターンが似ていますsh
。しかしbash
、ksh
またはzsh
結果は次のとおりです。
cat
cat
代わりに、/proc/self/stat
私は両方が実際に同じプロセスであることを/proc/self/comm
確認できます。cat
明らかにフードの下の殻は異なります。大丈夫です。今私たちが持っていこう
sh -c '/bin/cat /proc/self/environ - </proc/self/environ'
上記を観察した後、sh
またはdash
私が見ると予想したものはcat
後でシェルの環境です。うまくいくようです(とにかく両方の環境は同じである可能性が高いので、どうかを言うのは難しいです)。すべて期待どおりに動作しますが、私のポイントはどちらもenviron
nullではないということです。
bash
、ksh
またはzsh
2回見ると予想した環境がありますが、cat
印刷のみです。一度。 2つの状況に分けられます。
bash -c '/bin/cat - </proc/self/environ'
何も印刷せず、environ
空のように動作します。bash -c '/bin/cat /proc/self/environ'
期待どおりに何かを印刷します。
どうしたの?comm
それともそうではありませんstat
。なぜ違うのenviron
?
$ uname -a
Linux barbaz 4.9.0-6-amd64 #1 SMP Debian 4.9.88-1 (2018-04-29) x86_64 GNU/Linux
答え1
シェル間の違いは、プロセス設定の違いによるものです。dash
ブランチの前にリダイレクトを設定して/proc/self
シェルをポイントbash
し、zsh
ブランチ後にこれを設定して/proc/self
新しいプロセスをポイントします。これが起こっているのを見ることができますstrace -f
:
strace -f dash -c '/bin/cat /proc/self/comm - </proc/self/comm'
煙(そして他の多く)open("/proc/self/comm", O_RDONLY) = 3 fcntl(0, F_DUPFD, 10) = 10 close(0) = 0 fcntl(10, F_SETFD, FD_CLOEXEC) = 0 dup2(3, 0) = 0 close(3) = 0 clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f12581299d0) = 7743 strace: Process 7743 attached [pid 7742] wait4(-1, <unfinished ...> [pid 7743] execve("/bin/cat", ["/bin/cat", "/proc/self/comm", "-"], [/* 43 vars */]) = 0
(システムコール
/proc/self/comm
の前に開かれclone
、プロセスがフォークされる場所です)。strace -f bash -c '/bin/cat /proc/self/comm - </proc/self/comm'
プログラムclone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7fb506bdee10) = 8106 strace: Process 8106 attached [... snip a ton of signal-handling setup ...] [pid 8106] open("/proc/self/comm", O_RDONLY) = 3 [pid 8106] dup2(3, 0) = 0 [pid 8106] close(3) = 0 [pid 8106] execve("/bin/cat", ["/bin/cat", "/proc/self/comm", "-"], [/* 43 vars */]) = 0
(子プロセスでの
/proc/self/comm
呼び出し後に開くclone
、8106)。
空のように見える理由を理解するには、environ
もう少し説明が必要です。いつ/proc/<pid>/environ
開くの?、カーネルポインターのコピーをジョブに保存mm_struct
、環境へのポインタを含みます。しかし、execve
、cat
プロセスを開始するために使用されます。mm_struct
プロセス用の新しいプロセスの作成。したがって、リダイレクトは最終的に古い情報を指すようになり、cat
入力を読むときに実際の環境を見ることはできません。環境を作り出すするseeは親環境のコピーと見なされますが、execve
新しい環境を分岐して設定する前にそれをクリーンアップするシェルが含まれています。