回答:
承知しました!「ラッパー」プログラムの一般的なパターンは、さまざまなことを実行してから、exec
呼び出しのみ(フォークなし)で他のプログラムに置き換えます。
#!/bin/sh
export BLAH_API_KEY=blub
...
exec /the/thus/wrapped/program "$@"
これの実際の例は次のとおりですGIT_SSH
(ただし、上記のラッパープログラムメソッドを実行したくない場合にgit(1)
も提供されGIT_SSH_COMMAND
ます)。
フォークのみは、通常のワーカープロセス(たとえばhttpd
、フォークモードのApache)を生成するときに使用されます(ただし、フォークのみは、CPUを消費する必要があるプロセスに適しています。 )またはOpenBSD上の他のプログラムで使用される特権分離sshd
(execなし)
$ doas pkg_add pstree
...
$ pstree | grep sshd
|-+= 70995 root /usr/sbin/sshd
| \-+= 28571 root sshd: jhqdoe [priv] (sshd)
| \-+- 14625 jhqdoe sshd: jhqdoe@ttyp6 (sshd)
root
sshdがクライアント上で特権分離のために自身のコピー(28571)をフォークし、その後、別のコピー(14625)を接続しています。
たくさんあります。
fork()
なしで呼び出すプログラムexec()
は、通常、メインワーカープロセスとは別のプロセスでさまざまなタスクを実行する子ワーカープロセスを生成するパターンに従います。あなたは、など様々なプログラムでこれを見つけることができますdhclient
、php-fpm
とurxvtd
。
exec()
なしで呼び出すプログラムfork()
はチェーンロードであり、そのプロセスを別のプログラムイメージでオーバーレイします。特定の処理を行って状態を処理し、別のプログラムを実行してその改訂された処理状態で実行するチェーンロードユーティリティのサブカルチャー全体があります。このようなユーティリティは、daemontoolsファミリーのサービスおよびシステム管理ツールセットで一般的ですが、これらに限定されません。いくつかの例:
chpst
Gerrit Papeのrunitからs6-softlimit
そしてs6-envdir
ローランBercotさんからS6local-reaper
そしてmove-to-control-group
私の私のツールセットからrdprio
そしてidprio
FreeBSDnumactl
FreeBSDおよびLinuxdaemontoolsファミリのツールセットには、そのようなツールが多数含まれmachineenv
てfind-matching-jvm
いruntool
ます。
他の回答に加えて、デバッガは、を使用してptrace
、通常、fork
との間のギャップを利用しますexec
。デバッグ対象はPTRACE_TRACEME
、親プロセスであるデバッガによってトレースされていることを示すために、自分自身をマークする必要があります。これは、デバッガに必要な権限を与えるためです。
そのため、デバッガは最初に自身をフォークします。子供はで電話ptrace
をかけPTRACE_TRACEME
、次にを呼び出しますexec
。子execのどのプログラムでも、親が追跡できるようになります。
そのようなことをしたいと思う理由は少なくとも2つあります。
これは、すべてのデーモンが起動されるたびに(実際には2回)実行することです。これはいくつかのことを行いますが、その中でもシェルはハングせず(シェルが待機する元のプロセスが終了するため)、デーモンはターミナルによって制御されなくなるため、シェルウィンドウを閉じてもデーモンは終了しません。
もう1つの一般的な使用法は、25年ほど前にapache Webサーバーで有名になったforking worker childrenです(最近では、雷鳴の群れの問題が発生しやすいため、これは最新技術とは見なされていませんが、可能な限り最もシンプルで最も堅牢なサーバーです)。
さらに別の一般的な用途は、一貫したスナップショットを作成することです。fork
プロセスを作成するだけでなく、アドレススペースもコピーします(理論的には、実際にはコピーオンライトページのみをマークします)。これにより、(原子的に)完全なプログラムデータのスナップショットが作成され、親は変更できなくなります。
それを利用するプログラムもあります。たとえば、redisはデータを(整合性のある状態で)ディスクに保存すると同時に、データセットを同時に変更します。これはfork
、親プロセスによって加えられた変更を認識しない一貫したスナップショットを作成したためにのみ機能します。