为何使用&能达到nohup的效果?
nohup
nohup的意思是忽略SIGHUP信号
守护进程
守护进程是一个在后台运行并且不受任何终端控制的进程。Unix操作系统有很多典型的守护进程(其数目根据需要或20—50不等),它们在后台运行,执行不同的管理任务。
用户使守护进程独立于所有终端是因为,在守护进程从一个终端启动的情况下,这同一个终端可能被其他的用户使用。例如,用户从一个终端启动守护进程后退出,然后另外一个人也登录到这个终端。用户不希望后者在使用该终端的过程中,接收到守护进程的任何错误信息。同样,由终端键入的任何信号(例如中断信号)也不应该影响先前在该终端启动的任何守护进程的运行。虽然让服务器后台运行很容易(只要shell命令行以&结尾即可),但用户还应该做些工作,让程序本身能够自动进入后台,且不依赖于任何终端。
守护进程没有控制终端,因此当某些情况发生时,不管是一般的报告性信息,还是需由管理员处理的紧急信息,都需要以某种方式输出。Syslog 函数就是输出这些信息的标准方法,它把信息发送给 syslogd 守护进程。
start=>start: 开始
fork=>operation: fork子进程
exit=>operation: 父进程exit
create=>operation: setsid()创建新会话
chdir=>operation: chdir("/")设置工作目录
umask=>operation: umask(0)重置文件权限掩码
close=>operation: close()关闭文件描述符
e=>end: 结束
start()->fork()->exit()->create()->chdir()->umask()->close()->e
孤儿进程
如果父进程先退出,子进程还没退出那么子进程将被托孤给init进程,这时子进程的父进程(PPID)就是init进程(1).
yiuked@localhost:~$ php test.php &
[2] 6613
yiuked@localhost:~$ ps -ajx
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
0 1 1 1 ? 0 Ss 0 0:00 /init
1 6507 6507 6507 tty2 0 Ss 0 0:00 /init
6507 6508 6508 6507 tty2 0 S 1000 0:00 -bash
6508 6546 6546 6507 tty2 0 S 1000 0:00 /bin/sh ./test.sh
6508 6613 6613 6507 tty2 0 S 1000 0:00 php test.php
6546 6616 6546 6507 tty2 0 S 1000 0:00 sleep 1
6508 6617 6617 6507 tty2 0 R 1000 0:00 ps -ajx
yiuked@localhost:~$ exit
logout
C:\Users\Administrator>wsl
yiuked@localhost:/mnt/c/Users/Administrator$ ps -ajx
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
0 1 1 1 ? 0 Ss 0 0:00 /init
1 6546 6546 6507 ? 0 S 1000 0:00 /bin/sh ./test.sh
1 6613 6613 6507 ? 0 S 1000 0:00 php test.php
1 6662 6662 6662 tty1 0 Ss 0 0:00 /init
6662 6663 6663 6662 tty1 0 S 1000 0:00 -bash
6546 6677 6546 6507 ? 0 S 1000 0:00 sleep 1
6663 6678 6678 6662 tty1 0 R 1000 0:00 ps -ajx
如上,php test.php &
最开始的PPID为6508,在终端退出重新连接后,PPID变为了1,也就是init进程。
如果使用nohup会怎么样?
yiuked@localhost:~$ nohup ./test.sh &
[1] 11979
yiuked@localhost:~$ nohup: ignoring input and appending output to 'nohup.out'
yiuked@localhost:~$
yiuked@localhost:~$ ps -ajx
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
0 1 1 1 ? 0 Ss 0 0:00 /init
1 11945 11945 11945 tty2 0 Ss 0 0:00 /init
11945 11946 11946 11945 tty2 0 S 1000 0:00 -bash
11946 11979 11979 11945 tty2 0 S 1000 0:00 /bin/sh ./test.sh
11979 11987 11979 11945 tty2 0 S 1000 0:00 sleep 1
11946 11988 11988 11945 tty2 0 R 1000 0:00 ps -ajx
yiuked@localhost:~$ exit
logout
C:\Users\Administrator>wsl
yiuked@localhost:/mnt/c/Users/Administrator$ ps -ajx
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
0 1 1 1 ? 0 Ss 0 0:00 /init
1 11979 11979 11945 ? 0 S 1000 0:00 /bin/sh ./test.sh
1 12001 12001 12001 tty1 0 Ss 0 0:00 /init
12001 12002 12002 12001 tty1 0 S 1000 0:00 -bash
11979 12015 11979 11945 ? 0 S 1000 0:00 sleep 1
12002 12016 12016 12001 tty1 0 R 1000 0:00 ps -ajx
使用nohup在终端退出时,依旧会变成孤儿进程,由init接管。
总结
通过&实现守护进程,加nohup与不加的区别在于,加了nohup,进程产生的标准输入与输出不会显示在终端干扰用户。 当终端关闭时,程序都不会退出,而是不init进程接管。
无论是通过&
或者是nohup + &
都只是通过孤儿进程的形式达到守护进程的效果,与httpd,nginx存中的守护进程有本质的区别。
Liunx启动过程
getty 用户登录
参考: 百度百科 https://baike.baidu.com/item/init%E8%BF%9B%E7%A8%8B/3042859?fr=aladdin