$$が親プロセスと同じIDを返すのはなぜですか?


159

Bashに問題があり、その理由がわかりません。
シェルの下で、次のように入力します。

echo $$    ## print 2433
(echo $$)  ## also print 2433
(./getpid) ## print 2602

「getpid」は、次のように現在のpidを取得するCプログラムです。

   int main() {
    printf("%d", (int)getpid());
    return 0;
   }

私を混乱させるのはそれです:

  1. 「(コマンド)」はサブプロセスだと思います(正しいですか?)
  2. プログラムを使用して括弧内のpidを表示すると、表示されるpidが異なりますか?
  3. 「$$」はマクロのようなものですか?

手伝って頂けますか?


8
getpidサブシェルで実行されていなくても、別のプロセスIDが表示されることに注意してください。
chepner 2014年

1
@Marian echo $$ $BASHPID ; ( echo $$ $BASHPID )は、そのことを示しています。丸括弧はサブシェルを作成します。ステートメントは変数値を変更する可能性があり、親シェルはそれらの変更を認識してはなりません。これはfork()操作として実装されます。
ベン

回答:


222

$$サブシェルで親のプロセスIDを返すように定義されています。「特別なパラメータ」のmanページから:

$シェルのプロセスIDに展開されます。()サブシェルでは、サブシェルではなく、現在のシェルのプロセスIDに展開されます。

ではbash4、あなたはと子プロセスのプロセスIDを取得することができますBASHPID

~ $ echo $$
17601
~ $ ( echo $$; echo $BASHPID )
17601
17634

16
「親」は少し誤解を招く(少なくとも私にとってはそうだった)、実際には「トップレベル」のシェルです。たとえばecho $$; (echo $$; (echo $$))、同じpidを3回エコーします
Martin Bouladour 2017

1
正しい; 私は、値が(から値を継承し、親シェルから継承されていることを言っているはずその親、など)。トップレベルのシェルは、その(非シェル)親プロセスから継承するのではなく、最初に設定します。
chepner 2017

$ Expands to the process ID of the shellそれはそうですか?echo $リテラル$をエコーし​​ます。
Alexander Mills

@AlexanderMillsええ、そうです。$単独ではパラメータ拡張ではありません。manページは、特別なパラメータの名前を参照しています$。それ$だけで拡大するとは主張していません。
chepner

echo $BASHPIDわかりました、正直言って、それが何を意味するのかはわかりませんが、bash 4および5(MacOSではバージョン3.2.57ではありません)で動作します
Alexander Mills

81

次のいずれかを使用できます。

  • $! 最後のバックグラウンドプロセスのPIDです。
  • kill -0 $PID まだ実行中かどうかを確認します。
  • $$ 現在のシェルのPIDです。

2
2番目の弾丸は、kill -0 $!バックグラウンドプロセスについて話しているのではないでしょうか。PIDデフォルトでは何も設定されていません。
Isaac Freeman

26
  1. 括弧はBashのサブシェルを呼び出します。それは単なるサブシェルなので、同じPIDを持つ可能性があります-実装によって異なります。
  2. 呼び出すCプログラムは、独自の一意のPIDを持つ独立したプロセスです。サブシェルにあるかどうかは関係ありません。
  3. $$現在のスクリプトPIDに対するBashのエイリアスです。hereの違い、$$および$BASHPIDその真上$BASH_SUBSHELLに、ネストレベルを含む追加の変数を参照してください。

4

getppid()CプログラムでシェルのPIDを出力するかどうかを試してください。


2

既知のコマンドのPIDを取得する方法を尋ねると、次のようになります。

以下のコマンドを発行した場合#発行されたコマンドは***

dd if = / dev / diskx of = / dev / disky


それからあなたは使うでしょう:

PIDs=$(ps | grep dd | grep if | cut -b 1-5)

ここで何が起こるかは、必要なすべての一意の文字をフィールドにパイプし、そのフィールドは、

$ PIDをエコー


1

これは、正しいpidを取得するための1つの普遍的な方法です

pid=$(cut -d' ' -f4 < /proc/self/stat)

同じ素敵なサブのために働いた

SUB(){
    pid=$(cut -d' ' -f4 < /proc/self/stat)
    echo "$$ != $pid"
}

echo "pid = $$"

(SUB)

チェック出力

pid = 8099
8099 != 8100

いいアイデアですが、シェルが実行したforkのpidを取得して、cutの出力をキャプチャしませんか?2回実行すると、1回はecho $(...)で実行し、もう1回は実行しないと、異なる答えが返されます。
Martin Dorey、
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.