sudoが常にシェルサブプロセスを生成しないのはなぜですか?

sudoが常にシェルサブプロセスを生成しないのはなぜですか?

呼び出し時に特定のシェルが特別な扱いを受けているように見える理由を理解しようとしています。Sudo。たとえば、2つの可能な動作があるようです。

「暗黙的」グループ(うん直系存続Sudo、中間にシェル無し):

$ sudo pstree -s $$
systemd───login───bash───sudo───pstree
$ sudo bash -c 'pstree -s $$'
systemd───login───bash───sudo───pstree
$ sudo zsh -c 'pstree -s $$'
systemd───login───bash───sudo───pstree
$ sudo dash -c 'pstree -s $$'
systemd───login───bash───sudo───pstree

「明示的」グループ(シェルSudo):

$ sudo ksh -c 'pstree -s $$'
systemd───login───bash───sudo───ksh───pstree
$ sudo tcsh -c 'pstree -s $$'
systemd───login───bash───sudo───tcsh───pstree
$ sudo fish -c 'pstree -s $fish_pid'
systemd───login───bash───sudo───fish───pstree

明らかに、2つの間で一種の統合が行われたようですSudoといくつかのシェルがありますが、関連文書が見つかりません。私も2つのソースコードをgrepします。Sudoそして強く打つしかし、何の手がかりも見つかりませんでした。

この他の質問は関連しているようです。バックグラウンドで実行したときに(...)新しいサブプロセスを作成しないのはなぜですか?

私のバージョンSudoそして強く打つ例:

$ sudo --version
Sudo version 1.8.29
...
$ bash --version
GNU bash, version 5.1.16(1)-release (x86_64-pc-linux-gnu)
...

ベストアンサー1

いいえ、これはシェルとsudoの間の相互作用ではありません。これは、ユーザーが実行するコマンドに置き換えられるタスクの実行を担当するシェルです!

全体からsudoを削除すると、同じ結果が得られます。たとえば、alacritty端末でzshを実行します。

$> bash -c 'pstree -s $$'
systemd───alacritty───zsh───pstree

ここにはバッシュはありません!

次のコマンドを実行して、何が起こっているのかを確認できます。

$> strace -o /tmp/bash-pstree.strace bash -c 'pstree -s $$'
systemd───alacritty───zsh───pstree
$> bat /tmp/bash-pstree.strace # or just less /tmp/.... ; bat is just a nice code highlighter

私たちが見る場所

$> grep execve /tmp/bash-pstree.strace
execve("/usr/bin/bash", ["bash", "-c", "pstree -s $$"], 0x7ffc02c52d30 /* 102 vars */) = 0
execve("/usr/bin/pstree", ["pstree", "-s", "35735"], 0x55b90ec78d00 /* 102 vars */) = 

したがって、最初のexecveはbashが呼び出され、2番目のexecveはbashがpstreeに置き換えられます。それでは、もはや実際にbashはありません!その間に分岐/複製は発生しません。

もちろん、これは以下にのみ適用されます。最後命令体系の命令です。以前に実行したコマンドと置き換えると、それ以降は何もできません。実際にこれを非常に簡単に確認できます。

$> bash -c 'pstree -p -s $$; pstree -p -s $$'                                                                                                                                                                                                        
systemd(1)───alacritty(34604)───zsh(34609)───bash(39257)───pstree(39258)
systemd(1)───alacritty(34604)───zsh(34609)───pstree(39257)

ここで、最初のpstreeは実際にbashによって生成されたプロセスで実行され、2番目のpstreeはbashを置き換えるのと同じプロセスによって実行されます。

シェルを実行するプログラムに置き換えることは、リソースの観点から見るともちろん良いことです。すべてのファイルハンドル、メモリ、ロックなどをできるだけ早く作成します。

なぜ一部のシェルではこれを行い、他のシェルでは実行しないのかわかりません(指定されたコマンドを実行する前に独自のプロセスを使用または複製するforkことができます)。おそらく、これは開発者が決して考えなかった最適化です(例:シェルが起動されたプロセスに対していくつかの制御を維持するため、リリースは10年前でした!)。cloneexecvefishksh

おすすめ記事