Linux守护进程及Systemd

Linux守护进程及Systemd,第1张

Linux守护进程及Systemd

当我们启动一个前台任务后,命令行窗口退出,应用也就一起退出,无法访问了。


怎么才能让它变成系统的守护进程(daemon),成为一种服务(service),一直在那里运行呢?

守护进程 前台任务和后台任务

只要在命令的尾部加上符号&,启动的进程就会成为"后台任务"。


如果要让正在运行的"前台任务"变为"后台任务",可以先按ctrl + z,然后执行bg命令(让最近一个暂停的"后台任务"继续执行)。


后台任务有两个特点:

  • 继续当前session对话的标准输出(stdout)和标准错误(stderr)。


    因此,后台任务的所有输出仍然会同步地在命令行下显示。


  • 不再集成当前session的标准输入(stdin)。


    你无法像这个任务输入指令了。


    如果它试图读取标准输入,就会暂停执行(halt)。


可以看到,"后台任务"与"前台任务"的本质区别只有一个:是否继承标准输入。


所以,执行后台任务的同时,用户还可以输入其他命令。


SIGHUP信号

变为"后台任务"后,一个进程是否就成为了守护进程呢?或者说,用户退出 session 以后,"后台任务"是否还会继续执行?Linux系统是这样设计的。


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

后台任务是否会收到SIGHUP信号由Shell的huponexit参数决定

shopt | grep huponexit

大多数Linux系统这个参数是默认关闭的,但也有打开的,意味着后台任务会收到SIGHUP信号从而随着session的关闭而退出。


disown、nohup、screen命令
  • disown命令可以将指定任务从后台任务列表(jobs命令返回结果)之中移除,这样就不会收到SIGHUP信号了。


    #移出最近一个正在执行的后台任务
    $ disown #移出所有正在执行的后台任务
    $ disown -r #移出所有后台任务
    $ disown -a #不移出后台任务,但让他们不会收到SIGHUP信号
    $ disown -h #根据jobid,移出指定的后台任务
    $ disown %2

    使用disown命令之后,还有一个问题。


    那就是,退出 session 以后,如果后台进程与标准I/O有交互,它还是会挂掉。


    这是因为"后台任务"的标准 I/O 继承自当前 session,disown命令并没有改变这一点。


    一旦"后台任务"读写标准 I/O,就会发现它已经不存在了,所以就报错终止执行。


    为了解决这个问题,需要对"后台任务"的标准 I/O 进行重定向。


    $ node server.js > stdout.txt 2> stderr.txt < /dev/null &
    $ disown
  • 比disown更方便的命令是nohup,它阻止SIGHUP信号、关闭标准输入、重定向标准输出和标准错误到文件nohup.out。


    也就是说,nohup命令实际上将子进程与它所在的 session 分离了。


  • 另一种思路是使用 terminal multiplexer (终端复用器:在同一个终端里面,管理多个session),典型的就是 Screen 命令和 Tmux 命令。


    它们可以在当前 session 里面,新建另一个 session。


    这样的话,当前 session 一旦结束,不影响其他 session。


    而且,以后重新登录,还可以再连上早先新建的 session。


Systemd

除了专用工具以外,Linux系统有自己的守护进程管理工具 Systemd 。


它是 *** 作系统的一部分,直接与内核交互,性能出色,功能极其强大。


我们完全可以将程序交给 Systemd ,让系统统一管理,成为真正意义上的系统服务。


历史上,Linux的启动一直采用init 进程。


*** 作系统接管硬件后,首先读入/boot目录下的内核文件到内存里,然后启动init进程(pid 1)初始化系统环境。


早期linux守护进程是通过init进程运行的,通过确定运行级别(每个级别对一个一个目录/etc/runN.d 存放开机启动的程序)来启动不同的守护进程,运行级别里面的程序都是链接文件,指向另一个目录/etc/init.d,真正启动脚本都统一放在这个目录中。


(init.d表示是一个目录,用于区分/etc/init程序)。


开机启动程序加载完毕后,就让用户登录了。


由于init进程启动时间长(串行执行),启动脚本复杂,systemd诞生了。


systemd不是一个命令,而是一组命令,有systemctlhostnamectl等。


Systemd可以管理所有系统资源呢,不通资源统称为Unit。


每个unit都有一个配置文件,告诉systemd怎么启动这个unit。


Systemd 默认从目录/etc/systemd/system/读取配置文件。


但是,里面存放的大部分文件都是符号链接,指向目录/usr/lib/systemd/system/,真正的配置文件存放在那个目录。


systemctl enable命令用于在上面两个目录之间,建立符号链接关系,相当于激活开机启动。


一旦修改unit配置文件,就要执行systemctl daemon-reload重新加载配置文件。


systemctl cat docker.service可以查看配置文件内容,配置文件有以下几部分组成:

  • [Unit]:定义Unit元数据以及与其他Unit的关系

  • [Service]:service的配置,只有service类型才有这个区块

  • [Install]:通常是最后一个区块,定义如何启动以及是否开机启动。


启动计算机的时候,需要启动大量的 Unit。


如果每一次启动,都要一一写明本次启动需要哪些 Unit,显然非常不方便。


Systemd 的解决方案就是 Target。


启动某个 Target 的时候,Systemd 就会启动里面所有的 Unit。


Systemd 统一管理所有 Unit 的启动日志。


带来的好处就是,可以只用journalctl一个命令,查看所有日志(内核日志和应用日志)。


日志的配置文件是/etc/systemd/journald.conf


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/587843.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-12
下一篇 2022-04-12

发表评论

登录后才能评论

评论列表(0条)

保存