为什么是 $! 为在后台运行的子 shell 返回错误的进程 ID?

Chr*_*ski 4 shell process subshell

$(sleep 5) &
echo $!
sleep 1
echo "done"
Run Code Online (Sandbox Code Playgroud)

以上输出:

$ ./test.sh
7483
done
Run Code Online (Sandbox Code Playgroud)

但是,如果我在中搜索sleepps aux我会看到:

 ps aux | rg sleep
chris     7484  0.0  0.0 132788  1432 pts/6    S+   12:10   0:00 sleep 1
chris     7485  0.0  0.0 132788  1432 pts/6    S+   12:10   0:00 sleep 5
chris     7519  0.0  0.0  10376  5744 pts/7    S+   12:10   0:00 rg --no-ignore-vcs sleep
Run Code Online (Sandbox Code Playgroud)

sleep 5 进程7485不是7483脚本的输出。这种行为的原因是什么?

Ste*_*itt 8

$(sleep 5)
Run Code Online (Sandbox Code Playgroud)

运行一个运行sleep. 给出的 pid$!是 shell 的。

你不需要在这里替换,

 sleep 5 &
Run Code Online (Sandbox Code Playgroud)

会给你sleep的pid。

我想sleep在你的例子中替换了其他东西,但无论如何,背景替换可能是不必要的。只使用一个子shell,

(sleep 5) &
Run Code Online (Sandbox Code Playgroud)

通常会给你sleep的pid,因为许多shell在子shell中运行最后一个命令时用子命令替换自己,这有效地重用了子shell的pid sleep;但

(sleep 5; sleep 5) &
Run Code Online (Sandbox Code Playgroud)

会给你shell的pid,而不是sleep's。