当我们启动一个前台任务后,命令行窗口退出,应用也就一起退出,无法访问了。怎么才能让它变成系统的守护进程(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

Linux守护进程及Systemd的更多相关文章

  1. [转]❲阮一峰❳Linux 守护进程的启动方法

    ❲阮一峰❳Linux 守护进程的启动方法 "守护进程"(daemon)就是一直在后台运行的进程(daemon). 本文介绍如何将一个 Web 应用,启动为守护进程. 一.问题的由来 ...

  2. linux守护进程、SIGHUP与nohup详解

    前端时间帮忙定位个问题.docker容器故障恢复后,其中的keepalived进程始终无法启动,也看不到Keepalived的日志. strace 查看系统调用之后,发现了原因所在 socket(PF ...

  3. CentOS 7.4 初次手记:第一章 Linux守护进程(daemon)

    第一节 init & sysvinit 6 I sysvinit 运行顺序... 6 II Sysvinit和系统关闭... 7 III Sysvinit 的小结... 7 IV 运行级别.. ...

  4. C#与Linux守护进程

    用C#编写Linux守护进程   如果要在Red Hat Enterprise Linux上将.NET Core进程作为后台进程运行,则可以创建自定义systemd单元.今天我将为.NET Core编 ...

  5. .NET跨平台实践:用C#开发Linux守护进程

    Linux守护进程(Daemon)是Linux的后台服务进程,它脱离了与控制终端的关联,直接由Linux init进程管理其生命周期,即使你关闭了控制台,daemon也能在后台正常工作. 一句话,为L ...

  6. .NET跨平台实践:用C#开发Linux守护进程(转)

    Linux守护进程(Daemon)是Linux的后台服务进程,它脱离了与控制终端的关联,直接由Linux init进程管理其生命周期,即使你关闭了控制台,daemon也能在后台正常工作. 一句话,为L ...

  7. Server Develop (七) Linux 守护进程

    守护进程 守护进程,也就是通常说的Daemon进程,是Linux中的后台服务进程.它是一个生存期较长的进程,通常独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件.守护进程常常在系统引导装 ...

  8. Linux 守护进程和超级守护进程(xinetd)

    一 .Linux守护进程 Linux 服务器在启动时需要启动很多系统服务,它们向本地和网络用户提供了Linux的系统功能接口,直接面向应用程序和用户.提供这些服务的程序是由运行在后台的守护进程来执行的 ...

  9. Linux守护进程详解(init.d和xinetd) [转]

    一 Linux守护进程 Linux 服务器在启动时需要启动很多系统服务,它们向本地和网络用户提供了Linux的系统功能接口,直接面向应用程序和用户.提供这些服务的程序是由运行在后台 的守护进程来执行的 ...

随机推荐

  1. 2020牛客NOIP赛前集训营-普及组(第二场) 题解

    目录 T1 面试 描述 题目描述 输入描述: 输出描述: 题解 代码 T2 纸牌游戏 描述 题目描述 输入描述: 输出描述: 题解 代码 T3 涨薪 描述 题目描述 输入描述: 输出描述: 题解 代码 ...

  2. WebSocket实现前后端通讯

    WebSocket实现前后端通讯 长安如梦里,何日是归期. 简介:我们上线了一个商城项目,移交运营团队使用之后,他们要求商城有新订单来的时候同时加上声音提示,让她们可以及时知道有单来了.我这边想了想, ...

  3. 别错过了,130+个微信小程序源码 “限时分享“

    ​里面有130+款微信小程序源码和效果图,我只放了其中几款小程序的截图,具体请看下方图片 ​ ​ ​ ​ ​ ​ ​ ​ 仿网易云音乐小程序源码 链接:https://pan.baidu.com/s/ ...

  4. (学习心路历程)Vue过渡/动画 VS. 过渡/动画

    [此篇为本人的个人见解和哔哔赖赖,如果有观点不对的地方,还请大家指出来哇!!] 最近实习在做一个项目,里面应用的动画效果还蛮复杂的,因为本身对Vue框架比较熟悉,所以最终选择了Vue框架. 自己之前从 ...

  5. vmware使用U盘安装系统

    创建好系统 创建一个新的硬盘,选择"physicalDrive1" 如果识别不到physicalDrive 1,使用下面的方法. 1.在本机的服务里面启用下面的服务. 2.重启 V ...

  6. XML技术

    XML是一种可扩展标记语言,用来标记数据.定义数据类型,1998年由W3W发布1.0.版本,与HTML语言相比,可以自定义可扩展标签格式,但是语法严格. XML可以用来存储数据,可移植性强,主要充当配 ...

  7. Command 'ifconfig' not found, but can be installed with: sudo apt install net-tools VM Ubuntu 解决方案

    VMware下安装的Ubuntu 一开始由于Firefox连不上网,然后通过看了https://www.bbsmax.com/A/VGzlEGYJbq/这个文章之后,自己也测了一下,确实好用 但是if ...

  8. 添加Lombok插件后调用Setter或Getter方法IDEA编译错误

    虽然添加Lombok插件,但是调用Setter或Getter方法IDEA编译错误,主要原因如下 解决办法:

  9. [004] - JavaSE面试题(四):JavaSE语法(2)

    第一期:Java面试 - 100题,梳理各大网站优秀面试题.大家可以跟着我一起来刷刷Java理论知识 [004] - JavaSE面试题(四):JavaSE语法(2) 第1问:重载(overload) ...

  10. React 组件间通信 总结

    组件间通信 5.1.1. 方式一: 通过props传递 1)         共同的数据放在父组件上, 特有的数据放在自己组件内部(state) 2)         通过props可以传递一般数据和 ...