'su -c command'生成了多少个子进程(subprocess)

how many child process (subprocess) generated by 'su -c command'

使用Upstart时,控制子进程(child process)非常重要。但是让我感到困惑的是下面的内容,它已经超越了暴发户本身:

场景一:

root@ubuntu-jstorm:~/Desktop# su cr -c 'sleep 20 > /tmp/a.out'

我通过以下方式获得了 3 个进程:cr@ubuntu-jstorm:~$ ps -ef | grep -v grep | grep sleep

root       8026   6544  0 11:11 pts/2    00:00:00 su cr -c sleep 20 > /tmp/a.out
cr         8027   8026  0 11:11 ?        00:00:00 bash -c sleep 20 > /tmp/a.out
cr         8028   8027  0 11:11 ?        00:00:00 sleep 20

场景二:

root@ubuntu-jstorm:~/Desktop# su cr -c 'sleep 20'

我通过以下方式获得了 2 个进程:cr@ubuntu-jstorm:~$ ps -ef | grep -v grep | grep sleep

root       7975   6544  0 10:03 pts/2    00:00:00 su cr -c sleep 20
cr         7976   7975  0 10:03 ?        00:00:00 sleep 20

sleep 20的进程是我比较关心的,尤其是Upstart,Upstart管理的进程应该是这个而不是bash -c sleep 20 > /tmp/a.out是Upstart管理的,而不是sleep 20.

场景一,upstart无法正常工作,原因如上

因此,为什么场景 1 有 3 个进程,这对我来说没有意义。尽管我知道我可以使用命令 'exec' 来修复它,但我只想了解这两个命令提交时发生的过程。

command > file

这不是原子操作,实际上是在2个进程中完成的。

一个是执行命令; 另一个做输出重定向。

以上两个动作不能在一个过程中完成。

我说得对吗?

su -c 启动 shell 并通过其 -c 选项将命令传递给它。 shell 可以产生任意数量的进程(这取决于给定的命令)。

在某些情况下 shell 似乎直接执行命令而不分叉,例如,如果您 运行 su -c '/bin/sleep $$' 那么明显的行为 就好像 :

  1. su 启动一个 shell 进程(例如,/bin/sh
  2. shell 获取自己的进程 ID (PID) 并用它替换 $$
  3. shell exec() /bin/sleep.

你应该在 ps 输出中看到 sleep 的参数在这种情况下等于它的 pid。

如果你 运行 su -c '/bin/sleep $$ >/tmp/sleep' 那么 /bin/sleep 参数不同于它的 PID(它等于祖先的 PID)即:

  1. su 启动一个 shell 进程(例如,/bin/sh
  2. shell 获取自己的进程 ID (PID) 并用它替换 $$
  3. shell双叉exec()/bin/sleep.

双叉表示实际的事件顺序可能不同,例如,su 可以安排分叉或不分叉,而不是 shell(我不知道)。好像是the double fork is there to make sure that the command won't get a controlling terminal.