サブシェルのpidを取得する方法は?

サブシェルのpidを取得する方法は?

サブシェルのpidを取得する方法は?

たとえば、

$ echo $$
16808

元のシェルが拡張されているため機能しません$$

$ ( echo $$ )
16808

一重引用符が機能しないのはなぜですか?元のシェルから一重引用符を削除した後、サブシェル$$自体は拡張されませんか?

$ ( echo '$$' )
$$

なぜeval動作しないのですか?evalサブシェルによって実行されますか?元のシェルのPIDを提供するのはなぜですか?

$ ( eval echo '$$' )
16808

ありがとうございます。

答え1

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

マニュアルから:

BASHPID

現在のbashプロセスのプロセスIDに展開されます。これは$$、bashを再初期化する必要がないサブシェルと同じ場合とは異なります。

$

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

関連:

答え2

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

答え3

Linuxで新しいプロセスを作成しないクロスシェルソリューション(最小のダッシュ、bash、zsh)は次のとおりです。

read -r this_pid < /proc/self/stat; echo ${this_pid%% *}

少なくともbashとzshでは、読取り区切り文字としてスペースを使用することもできます。

read -d ' ' this_pid < /proc/self/stat ; echo $this_pid

また、見ることができます人5プロセス /proc/[pid]/stat セクション

答え4

元の「なぜ」質問に答えるには、$$サブシェルpidで拡張するか、ゆっくりと評価するのはどうですかeval

引用するPOSIX ドキュメント:

$

呼び出しシェルの10進プロセスIDに展開されます。サブシェル(シェル実行環境を参照)では、「$」は現在のシェルと同じ値に拡張する必要があります。

関連情報