欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Linux守护进程详解

程序员文章站 2022-07-14 12:05:14
...

简介

在Linux服务器实际应用中,经常会有需要长时间执行的任务。这类任务若在前台运行,用户无法进行其他操作或者断开与服务器的连接,否则任务将被中止。此时适合使用守护进程。为了使用守护进程,需要了解Linux前台、后台、守护进程的概念与使用,本文将对此进行讲解。

创建守护进程

  • 终端(terminal)是计算机用于文本输入与显示的交互界面。

A text terminal, or often just terminal (sometimes text console) is a serial computer interface for text entry and display.
https://en.wikipedia.org/wiki/Computer_terminal#Text_terminals

  • 前台任务(foreground job)是独占命令行窗口的任务,只有运行完了或者手动中止该任务,才能执行其他命令。
  • 后台任务(background job),与前台任务相对应,在多任务系统中,有一些任务在运行的时候,并不需要与用户交互。它们通常在不打扰用户其它工作的时候默默地执行(此时可以输入其他的命令)。后台任务继承当前session(对话,就是终端窗口)的标准输出(stdout)和标准错误(stderr)。因此,后台任务的所有输出依然会同步地在命令行下显示。不再继承当前session的标准输入(stdin)。你无法向这个任务输入指令了。如果它试图读取标准输入,就会暂停执行(halt)。
  • 守护进程(daemon)是指在UNIX或其他多任务操作系统中在后台执行的电脑程序,并不会接受电脑用户的直接操控。此类程序会被以进程的形式初始化。守护进程程序的名称通常以字母“d”结尾:例如,syslogd就是指管理系统日志的守护进程。用户退出session之后,“后台任务是否会继续执行”是判定这一任务是否为“守护进程”的依据。

可以看出,”后台任务”与”前台任务”的重要区别:是否继承标准输入。所以,执行后台任务的同时,用户还可以输入其他命令。

为了理解守护任务为何在结束session时也不退出,需要先了解Linux下退出session时发生的操作。

Session退出时,linux系统设计如下:

  1. 用户准备退出 session
  2. 系统向该 session 发出SIGHUP信号
  3. session 将SIGHUP信号发给所有子进程
  4. 子进程收到SIGHUP信号后,自动退出

前台任务会随着session的退出而退出是因为它收到了SIGHUP信号
后台任务是否会受到SIGNUP信号,取决于shell的 huponexit 参数。可以通过 $ shopt | grep huponexit 查看该参数的值。大多数Linux系统,这个参数默认关闭(off)。因此,session退出的时候,不会把SIGHUP信号发给”后台任务”,即此时的后台任务是守护进程,但这显然不够安全。并不保险,因为有的系统的huponexit参数可能是打开的(on)状态。

更保险的方法是使用disown命令。它可以将指定任务从”后台任务”列表(jobs命令的返回结果)之中移除。一个”后台任务”只要不在这个列表之中,session 就肯定不会向它发出SIGHUP信号。

$ node server.js &
$ disown

执行上面的命令以后,server.js进程就被移出了”后台任务”列表。你可以执行jobs命令验证,输出结果里面,不会有这个进程。

但是,这样还存在问题。因为”后台任务”的标准 I/O 继承自当前 session,disown命令并没有改变这一点。一旦”后台任务”读写标准 I/O,就会发现它已经不存在了,所以就报错终止执行。 为了解决这个问题,需要对”后台任务”的标准 I/O 进行重定向

$ node server.js > stdout.txt 2> stderr.txt < /dev/null &$ disown

这样基本上就没有问题了。

注:
/dev/null文件的作用
这是一个无底洞,任何东西都可以定向到这里,但是却无法打开。
所以一般很大的stdou和stderr当你不关心的时候可以利用stdout和stderr定向到这里

$ ./command.sh >/dev/null 2>&1

更简便地创建守护进程: nohup 命令

$ nohup node server.js &

nohup命令对server.js进程做了三件事。
阻止SIGHUP信号发到这个进程。
关闭标准输入。该进程不再能够接收任何输入,即使运行在前台。
重定向标准输出和标准错误到文件nohup.out。

也就是说,nohup命令实际上将子进程与它所在的 session 分离了。 注意,nohup命令不会自动把进程变为”后台任务”,所以必须加上&符号

总结

守护进程创建方法:

方法一:

$ node server.js > stdout.txt 2> stderr.txt < /dev/null &
$ disown

方法二:

$ node server.js > stdout.txt 2> stderr.txt < /dev/null 
^z
$ bg
$ disown

方法三:

$ nohup node server.js &

命令总结

fg、bg、jobs、&、nohup、ctrl+z、ctrl+c 命令

一、&
加在一个命令的最后,可以把这个命令放到后台执行,如:

# 每10s在后台执行一次test.sh脚本

$ watch -n 10shtest.sh & 

二、ctrl + z
可以将一个正在前台执行的命令放到后台,并且处于暂停状态。

CTRL+Z 和 CTRL+C的对比

CTRL+Z 和 CTRL+C 都是中断命令,但是他们的作用却不一样.
CTRL+C 是强制中断程序的执行,而 CTRL+Z 的是将任务中断,但是此任务并没有结束,仍然在进程中,只是维持挂起的状态,用户可以使用 fg/bg 操作继续前台或后台的任务。

三、jobs
查看当前有多少在后台运行的进程

jobs -l选项可显示所有任务的PID,jobs的状态可以是running, stopped, Terminated。但是如果任务被终止了(kill),shell 从当前的shell环境已知的列表中删除任务的进程标识。

四、fg
将后台中的命令调至前台继续运行。如果后台中有多个命令,可以用fg %jobnumber(jobnumber是命令编号,不是进程号)将选中的命令调出。

五、bg

将一个在后台暂停的命令,变成在后台继续执行。

如果后台中有多个命令,可以用bg %jobnumber将选中的命令调出。

六、kill

方法1:通过jobs命令查看job号(假设为num),然后执行

$ kill %num

方法2:通过ps命令查看job的进程号(PID,假设为pid),然后执行

$ kill pid

前台进程的终止:Ctrl+c

七、nohup

如果想让程序即使在关闭当前的终端后也始终在后台执行(之前的&做不到),需要使用nohup命令。
nohup命令可以在你退出帐户/关闭终端之后继续运行相应的进程。
关闭终端后,在另一个终端jobs已经无法看到后台跑的程序了,此时利用ps(进程查看命令)查看进程。

ps -aux | grep "test.sh"  #ps选项说明: a:显示所有程序 u:以用户为主的格式来显示 x:显示所有程序,不以终端机来区分

参考资料

http://m.2cto.com/os/201301/185701.html

http://www.cnblogs.com/kaituorensheng/p/3980334.html

http://m.blog.csdn.net/article/details?id=50766752