个人主页:Lei宝啊
愿所有美好如期而遇
我们在写完一个服务之后,想要让他一直跑,即使我们关闭了会话,因为我们不可能让我们自己的电脑一直开着机,博主这里使用的云服务器,即使在云服务器上,启动了服务,当关闭了终端后,这个服务也就关闭了,我们想要让他一直跑,那么就需要将他守护进程化。
守护进程
守护进程(Daemon)是一种在后台运行的进程,通常与终端会话无关。
我们可以在命令行启动一个服务并将他变成守护进程:nohup 服务 &
当你看到 nohup: ignoring input and appending output to 'nohup.out'
这条消息时,意味着你已经成功使用了 nohup
命令来运行一个命令,并且该命令现在将在后台运行,即使你关闭了终端或SSH会话。
当然,这种方式只是权宜之计,我们不推荐这样做,因为SSH会话在因为网络问题或者其他原因意外中断时,我们通过命令行的方式启动的守护进程可能会在会话关闭时也一同关闭。(后面我们会说一种更好的方式)
会话
Linux服务器中,当用户登录时,会给我们打开一个终端文件,并创建bash子进程,将他们关联起来,这就是一个会话,在一个会话中新启动的任务,一定是默认属于改会话的。
什么是终端文件?
/dev/pts下的文件就是终端文件,我们输入输出都是从这个终端文件中来的,同时,我们也可以看到,我们下一条命令中,有一个pts/0,也就是说,他们的输入输出就是在这个终端下的。
PPID是父进程PID,PGID是进程组ID,SID就是会话ID,我们可以发现,我们执行的指令也好,新启动的任务也好,SID在同一会话下,都是一样的。
我们新建一个会话,通常会话id就是会话中的第一个进程的id,这个进程也叫做话首id,我们可以查看一下:
-bash组id,sid,pid都是一样的。
daemon
下面我们介绍一种更好的方式:使用代码将服务变成守护进程。
通常我们会使用setsid创建守护进程:
他用来创建一个会话并且设置进程组id,但是他是有要求的:
setsid() creates a new session if the calling process is not a process group leader.
也就是说,他需要调用这个函数的进程不能是进程组的组长,也就是进程组的第一个进程,我们可以肯定的是,子进程一定不是进程组的组长。
所以,我们通常需要fork一个子进程,然后使父进程退出,子进程去调用setsid。
之后,这个调用setsid的进程将会成为进程组的组长,并且PID,PGID,SID被设置为相同的。
这种方式有些繁琐,我们不需要自己去做,有这样一个函数daemon:
他会帮我们将上述工作全部做完。
参数:
- daemon(0,0),意为改变进程的工作目录到根目录下,进程的输入输出要进行重定向,重定向到/dev/null中。
- daemon(1,1),和上面相反,什么都不改变。
/dev/null,也就是说,进程从这个文件中进行读取,直接就读到文件末尾,也就是什么都读不到,向这个文件中写入的内容会被直接丢弃。
如何进行重定向呢?首先/dev/null是个文件,open后得到文件描述符,将0,1,2文件描述符通过dup2全部重定向到他中。
这样,我们就可以将服务守护进程化,守护进程是去关联终端文件的,去关联后,TTY就是?。