使用 /bin/bash -c 时 $$ 和 $! 有什么区别

使用 /bin/bash -c 时 $$ 和 $! 有什么区别

我试图理解此评论来自@sysfault:

/bin/sh -c 'echo $$>/tmp/my.pid && exec program args' &

我尝试了以下变化......

内外不同的$$:

/bin/bash -c 'echo $$ && exec sleep 5' ; echo $$
14408
29700

相同的 pid (但在后台):

$ /bin/bash -c 'echo $$ && exec sleep 5' & echo $! 
[1] 8309
8309
$ 8309

[ 1 ]+  Done  /bin/bash -c 'echo $$ && exec sleep 5'

$$ & $! 的不同 pid:

/bin/bash -c 'echo $$ && exec sleep 5 & echo $!'                                 
6504
6503

杀死不起作用:/bin/bash -c 'echo $$ && (sleep 15 ; echo done)'
19063 Killed $ done(杀死后出现 echo)

与访问前台进程的 pid 相同的 pid:

$ /bin/bash -c 'echo > tmp.pid ; sleep 10 ; echo $$ ; echo done ; echo $$;'      
28415 (instantly)
28415 (10 seconds later)
done
28415
$ cat tmp.pid 
28415

使用此命令,我能够在睡眠完成之前在另一个窗口中杀死 pid - 从而防止最后三个回声发生:

$ /bin/bash -c 'echo $$ ; sleep 30 ; echo $$ ; echo done ; echo $$;'               
23236
Killed

上下文:最终我想通过 php exec() 启动 bash 进程,并等待结果后再继续保存 pid,这样我就可以清理,以防手动取消按钮被按下。我要处理 2 个昂贵的过程:一个是 rsync,另一个是 git commit & push。

可靠地获取包含多个命令(使用 ; > | 或 &&)的前台 bash 脚本的 pid 的最佳方法是什么?

答案1

$$当前外壳。在脚本主体中使用 $$ 时bash -c,你将获得生成的 shell

$ echo $$; bash -c 'echo $$'; echo $$
6872
6987
6872

$!最后一个后台进程

$ sleep 5 & echo $!; sleep 5 & echo $!; echo ===; pgrep -l sleep
[1] 7118
7118
[2] 7119
7119
===
7118 sleep
7119 sleep

当您这样做时bash -c 'echo $$' & echo $!,您会得到两次打印相同的 pid,因为对于您当前的 shell,$! 是后台 bash 进程的 pid,而在脚本主体内部,$$ 是同一后台 bash 进程的当前 pid。

当您这样做时/bin/bash -c 'echo $$ && exec sleep 5 & echo $!',您会得到两个不同的 pid:$$ 是 bash 进程的 pid,而 $! 是睡眠进程的 pid。

  • 我觉得这很奇怪,因为你正在使用,exec所以它应该是相同的 PID(睡眠进程取代 bash 进程)
  • 但是你正在使用exec ... &所以 bash 必须首先 fork子壳运行后台任务,然后 exec 替换那个子壳睡眠。

您的实际问题最好由 php 人员来回答,而我不是。您应该向版主举报此问题,并请求将其移至 Stack Overflow,因为那里肯定会有更多 php 人员聚集。

相关内容