我在 Ubuntu 17.04 上列出了进程,注意到以下进程:
root@user-virtual-machine:~# ps xao pid=,ppid=,pgid=,sid=
1603 1 1601 1601
Run Code Online (Sandbox Code Playgroud)
但是进程 1601 不存在。
root@user-virtual-machine:~# ls /proc/1601
ls: cannot access '/proc/1601': No such file or directory
Run Code Online (Sandbox Code Playgroud)
正如你所看到的 /proc/1603/status 仍然引用 1601。
root@user-virtual-machine:~# cat /proc/1603/status
Name: VGAuthService
Umask: 0000
State: S (sleeping)
Tgid: 1603
Ngid: 0
Pid: 1603
PPid: 1
TracerPid: 0
Uid: 0 0 0 0
Gid: 0 0 0 0
FDSize: 64
Groups:
NStgid: 1603
NSpid: 1603
NSpgid: 1601
NSsid: 1601
Run Code Online (Sandbox Code Playgroud)
重要的是,我在主机上(不在容器内)。
怎么可能?如何为不存在的进程设置 setid/setpgid?
是的,这是一个没有领导者的会话,这对于守护进程来说很常见。
会话主要用于在终端上实现登录会话。
当您从终端启动守护程序时,您希望它与终端断开连接。要使该守护进程的进程不再将终端作为其控制终端,您需要启动一个新会话。因此,通常守护进程会 fork 一个进程(这确保子进程不是进程组领导,并且父进程可以退出),并调用setsid()
该子进程。
该孩子将成为新会话的领导者,因此不是由终端控制的会话。但是,如果该进程在没有传递 O_NOCTTY 标志的情况下打开了另一个终端设备,则会导致该终端成为该会话的控制终端,这不是您想要的守护进程。为了确保它不会发生,最好再次分叉,然后孩子不再是会话领导者,打开终端设备将无害。
父节点没有理由徘徊并退出,因此该会话不再有领导者。
所以守护进程在没有领导者的情况下运行是很常见的。
在这里,在没有领导者的会话中寻找进程,我看到了很多守护进程:
$ ps -je | grep -wf <(comm -23 <(ps -eo sid= | sort -u) <(ps -eo pid= | sort -u) | awk '$1{print $1}')
1722 1714 1714 ? 00:00:01 atopacctd
2540 2178 2178 ? 00:00:00 ddclient - slee
2985 2984 2984 ? 00:00:00 dnsmasq
2987 2984 2984 ? 00:00:00 dnsmasq
8428 8427 8427 ? 00:00:00 gnome-keyring-d
8726 8725 8725 ? 00:01:17 pulseaudio
11456 11455 11455 ? 00:00:00 gnome-keyring-d
11649 11648 11648 ? 00:00:00 pulseaudio
Run Code Online (Sandbox Code Playgroud)