サブシェルのPIDを取得するにはどうすればよいですか?


13

サブシェルのPIDを取得するにはどうすればよいですか?

例えば:

$ echo $$
16808

元のシェルが展開するため、これは機能しません$$

$ ( echo $$ )
16808

単一引用符が機能しないのはなぜですか?元のシェルが単一引用符を削除した後、サブシェル$$自体は展開しませんか?

$ ( echo '$$' )
$$

なぜうまくいかevalないのですか?さevalサブシェルで実行?なぜ元のシェルのPIDが表示されるのですか?

$ ( eval echo '$$' )
16808

ありがとう。


質問は私の意見では本質的に異なるので、再開することをお勧めします(「$$拡張を回避する方法」と「サブシェル内の異なるpid」)。
peterh-モニカを

回答:


12

加えてbash$BASHPID、あなたが移植性、それを行うことができます。

pid=$(exec sh -c 'echo "$PPID"')

例:

(pid=$(exec sh -c 'echo "$PPID"'); echo "$$ $pid")

あなたはそれを関数にすることができます:

# usage getpid [varname]
getpid(){
    pid=$(exec sh -c 'echo "$PPID"')
    test "$1" && eval "$1=\$pid"
}

一部のシェル(例:zshまたはksh93)は、で作成された各サブシェルのサブプロセスを開始しないことに注意してください(...)。その場合、プロセスのPID が呼び出されたので$pid、と同じになる可能性があります。$$getpid


1
いいえ。ただし、サブシェルがサブプロセスで必ず実行されるとは想定しないでくださいksh93。たとえば、の場合はそうではありません。
モスビー

1
これはksh93で正常に動作します-呼び出し元のプロセスのpidを常に返します。これは(...)、のように別のプロセスを生成しない例からのものbashです。
2018年

1
また、一部のシェルは、サブシェルの最後のコマンドに対してa を好きzshまたはyash最適化しfork()ます。スクリプトの最後のコマンドであれば、サブシェルのフォークを最適化してgetpid、の親を報告することもできます$$。あなたは定義することができgetpid:としてgetpid(){ sh -c 'echo "$PPID"'; return; }無効を避けるために問題。
ステファンChazelas

1
@HaroldFischer 1. exec最適化の有無にかかわらずsh -c ...、プロセスは、$(...)コマンド置換が使用されるプロセスの子ではなく孫$PPIDとなり、$(...)サブシェルのpidになります。これが、上記のset -E+ trap ERRbashの例でまさに起こっていることです。
モスビー

1
@HaroldFischer 2. 空の文字列であるtest "$1"かどうかをテストします$1-その関数にvarnamepidを割り当てる引数が指定されているかどうかをテストするための迅速でダーティな方法。関数を使用することは、そもそも最も優れたアイデアではありませんでした。
モスビー

18
$ echo $BASHPID
37152
$ ( echo $BASHPID )
18633

マニュアルから:

BASHPID

現在のbashプロセスのプロセスIDに展開されます。これは、$$bashを再初期化する必要のないサブシェルなど、特定の状況下とは異なります。

$

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

関連:


ありがとう。(1)「再初期化」とはどういう意味ですか?(2)私が試したこれらの方法が機能しない理由も考慮してください。
Tim、

@Tim ここで Gillesが答えていると思います。Bashは単に$$サブシェルで更新しません。
クサラナンダ

bashでは、$$の代わりに常に$ BASHPIDを使用する必要があるということですか?いつ使用しますか?
Tim

@Timサブシェルで、スクリプトまたはサブシェルのプロセスIDを取得するかどうかによって異なります。両方の可能性が提供され、どちらが正しいかはアプリケーションに依存します。これに対する具体的な答えはありません。
クサラナンダ

1
@Timサブシェルの親シェルのPIDは、$BASHPID変数に保存してサブシェルで使用するように手配しない限り、確実に見つけることができません。はありますが$PPID、これはシェルのPIDと同じ意味でシェルの親PIDです$$(サブシェルではリセットされません)。$BASHPPID変数はありません。
クサラナンダ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.