bashはCのfork()と同様にフォークをサポートしていますか?


25

ある時点で分岐したいスクリプトがあるので、同じスクリプトの2つのコピーが実行されています。

たとえば、次のbashスクリプトが存在するようにします。

echo $$
do_fork()
echo $$

このbashスクリプトが本当に存在する場合、予想される出力は次のようになります。

<ProcessA PID>
<ProcessB PID>
<ProcessA PID>

または

<ProcessA PID>
<ProcessA PID>
<ProcessB PID>

この種の出力を取得するため、またはbashスクリプトにCのようなフォークを実行させるために、「do_fork()」の代わりに配置できるものはありますか?

回答:


23

はい。フォークは綴られます&

echo child & echo parent

混乱を招く可能性があるの$$は、それがシェルプロセスのPIDではなく、元のシェルプロセスのPIDであるということです。このようにすることのポイントは$$、シェルスクリプトの特定のインスタンスの一意の識別子であることです。スクリプトの実行中に変更されず、$$同時に実行される他のスクリプトとは異なります。シェルプロセスの実際のPIDを取得する1つの方法はsh -c 'echo $PPID'です。

シェルでの制御フローはCと同じではありません。Cで記述した場合

first(); fork(); second(); third();

シェルの等価物は

after_fork () { second; third; }
first; after_fork & after_fork

単純なシェル形式first; child & parentは、通常のCイディオムに対応します

first(); if (fork()) parent(); else child();

&そして$$存在し、すべてのBourneスタイルのシェルにし、(T)cshの中でこのように振る舞います。$PPID元のBourneシェルには存在しませんでしたが、POSIXにあります(したがって、ash、bash、ksh、zshなどにあります)。


3
しかし、それは基本的に「fork + exec」であり、単なるforkではありません。
mattdm

@mattdm:え?&フォークです、関与するexecはありません。Fork + execは、外部コマンドを起動するときです。
ジル 'SO-悪であるのをやめる'

@mattdm:ああ、私はコーリーが何を得ているのか見ていると思う。ありませんexecが、2つの言語には異なる制御フローがあります。
ジル 'SO-悪である停止

1
@Gilles:bash制御オペレーター&は、指定されたコマンドが実行されるサブシェルを開始します。フォーク+ exec。&実行する前のコマンドなしで置くことはできません。
mattdm

5
さて、もし「フォークが綴られている」が本当の陳述なら、あなたは&それ自身で線を引くことができます。しかし、できません。「ここに分岐する」という意味ではありません。「サブシェルのバックグラウンドで先行するコマンドを実行する」ことを意味します。
mattdm

10

はい、サブシェルと呼ばれます。括弧内のシェルコードは、サブシェル(フォーク)として実行されます。ただし、最初のシェルは通常、子が完了するまで待機します。&ターミネーターを使用して非同期にすることができます。次のようなもので実際にそれを見てください:

#!/bin/bash

(sleep 2; echo "subsh 1")&
echo "topsh"

$ bash subsh.sh


5
括弧はサブシェルを作成しますが、それはfork + waitです。&フォークだけです。(子プロセスを作成せずにグループ化を行う)の使用中括弧に使用すると、子プロセスで複数のパイプラインを実行したい場合は、それの十分な:{ sleep 2; echo child; } &
ジル「SO-停止されて悪」

6

これを行うためのネイティブbash(または、私の知る限り、他の典型的な* nixシェル)の方法はありません。非同期に何かを行うforkプロセスを生成する方法はたくさんありますが、fork()システムコールの正確なセマンティクスに従うものはないと思います。

典型的なアプローチは、トップレベルのスクリプトに、必要な作業だけを分割するヘルパーを生成させることです。あなたが$0 $@ &何をしたとしても、最初からやり直し、どうにかしてそれを理解する必要があります。

私は実際にそれを行ういくつかの巧妙な方法を考え始めています....

しかし、私の脳があまりにも夢中になる前に、私はかなり良いルールだと思います:シェルで何かを書き込もうとしていて、それが巧妙なトリックでいっぱいになり、あなたがより多くの言語機能を望んでいるなら、切り替える時間です実際のプログラミング言語に


2
あなたの主張はよく理解されていますが、bashの構文は間違いなく困難であり、PerlまたはPythonのより洗練されたデータ構造と機能が欠落していますが、bashはその領域で得られるほどリアルです。これはドメイン固有の言語であり、多くの場合、たとえばPythonよりも優れている(簡潔でシンプルな)と主張します。Pythonを知らずに、たくさんのシステムを管理できますか?はい。あなたはそれをすることができ、bash [プログラミング]のなめを知らないのですか?試したくありません。30年のシェルプログラミングの後、私はそれが現実のものだと言います。そして、はい、私はPythonを話します。しかし、若者を混同しないでください。
マイクS

2
とはいえ、技術的にはこの回答がより好きです。「&」がユーザーの質問に対する答えであると言うと、「ある時点で分岐して同じスクリプトの2つのコピーが実行されている」というのは混乱を招くことです。bashのマニュアルによれば、「&」は「...サブシェルのバックグラウンドで[指定された]コマンドを実行する」という意味です。コマンドを終了する必要があり、フォーク(技術的にはLinuxではclone())が含まれますが、その時点では同じスクリプトの2つのコピーが実行されていません。
マイクS
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.