当前位置: 首页 > news >正文

linux-进程管理-守护进程(Daemon)

守护进程(Daemon)概述

守护进程(Daemon)是Linux操作系统中一种特殊类型的后台进程,它在系统启动时自动启动并一直在后台运行,通常不直接与用户交互。守护进程通常负责执行系统级别的任务,例如日志记录、系统监控、任务调度、网络服务等。由于守护进程在系统引导时启动并一直运行,直到系统关闭,因此它们被称为“守护进程”,意为守护系统的稳定和正常运行。

守护进程的特性

  1. 无控制终端:守护进程通常不依赖于特定的终端设备。它们在启动时会脱离与任何终端的关联,以确保不会因为终端的关闭或用户的退出而受到影响。
  2. 长时间运行:守护进程的生命周期通常与系统的运行时间一致,它们在系统启动时启动,并持续运行直到系统关闭或守护进程被手动停止。
  3. 自主性和自我恢复:守护进程通常设计为具有较强的自主性,即使在出现错误时,它们也会尝试自我恢复。许多守护进程会定期检查自身的状态,并在必要时重启。
  4. 低权限运行:为了安全起见,许多守护进程在运行时会以低权限的用户身份运行,以减少对系统的潜在威胁。例如,Apache HTTP服务器可以在启动时以root权限运行,但随后会切换到一个非特权用户(如www-data)。

守护进程的工作原理

守护进程通常通过以下步骤来实现:

  1. 创建子进程:守护进程通常通过创建一个子进程(fork)来启动。父进程退出,而子进程成为一个新的进程。
  2. 脱离控制终端:子进程调用setsid()系统调用,创建一个新的会话并成为会话的领导者。此步骤使进程脱离任何控制终端,并成为一个新的进程组的组长。
  3. 改变工作目录:为了防止进程在一个可能被卸载的文件系统上,守护进程通常会将其工作目录更改为根目录/
  4. 重设文件权限掩码:守护进程会将文件权限掩码(umask)设置为0,以确保进程创建的新文件拥有所需的权限。
  5. 关闭文件描述符:守护进程通常会关闭所有继承自父进程的文件描述符,特别是标准输入、输出和错误(即stdinstdoutstderr)。这可以防止守护进程与任何终端的交互,并确保没有意外的数据泄露。

如何创建一个守护进程

要在Linux中创建一个守护进程,可以按照以下步骤进行:

  1. Fork一个子进程:创建一个新的子进程,父进程退出,确保新的子进程不是一个进程组的领导者。
  2. 调用setsid():在子进程中调用setsid(),使其成为新的会话领导者,这将脱离其控制终端。
  3. 捕获或忽略信号:处理信号以确保守护进程可以正确地终止或重新加载配置。
  4. 关闭不必要的文件描述符:关闭不再需要的文件描述符,特别是标准输入、输出和错误。
  5. 重定向标准文件描述符:将标准输入、输出和错误重定向到/dev/null,避免任何输出。

以下是一个简单的C语言守护进程示例:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <syslog.h>int main() {pid_t pid, sid;// Fork the parent processpid = fork();if (pid < 0) {exit(EXIT_FAILURE);}// If we got a good PID, then we can exit the parent processif (pid > 0) {exit(EXIT_SUCCESS);}// Change the file mode maskumask(0);// Open logs for writingopenlog("mydaemon", LOG_NOWAIT | LOG_PID, LOG_USER);syslog(LOG_NOTICE, "Daemon started");// Create a new SID for the child processsid = setsid();if (sid < 0) {syslog(LOG_ERR, "Failed to create a new SID");exit(EXIT_FAILURE);}// Change the current working directoryif ((chdir("/")) < 0) {syslog(LOG_ERR, "Failed to change directory to /");exit(EXIT_FAILURE);}// Close standard file descriptorsclose(STDIN_FILENO);close(STDOUT_FILENO);close(STDERR_FILENO);// Daemon-specific initialization goes here// The daemon main loopwhile (1) {// Perform daemon-specific taskssyslog(LOG_INFO, "Daemon is running...");sleep(30); // Sleep for 30 seconds}closelog();return EXIT_SUCCESS;
}

常见的守护进程示例

  1. 系统守护进程:包括systemdinitupstart等,它们负责系统的启动、管理和停止各种服务。
  2. 网络守护进程:如sshd(OpenSSH守护进程),用于提供安全的远程登录和文件传输服务。
  3. 日志守护进程:如rsyslogd,用于收集和存储系统和应用程序的日志信息。
  4. 定时任务守护进程:如cron,用于定期执行计划任务。
  5. 文件和目录监控守护进程:如inotifywatchdog,用于监视文件系统的变化并执行相应的操作。

守护进程的管理和控制

1. 使用systemd管理守护进程

在现代Linux发行版中,systemd是默认的服务管理器,它提供了一种简单的方式来管理守护进程。可以通过创建一个service文件来定义一个守护进程的配置。

[Unit]
Description=My Daemon[Service]
ExecStart=/usr/local/bin/mydaemon
Restart=always[Install]
WantedBy=multi-user.target

保存上述内容为/etc/systemd/system/mydaemon.service,然后使用以下命令启用和启动守护进程:

sudo systemctl enable mydaemon.service
sudo systemctl start mydaemon.service
2. 使用supervisordsystemd组合

在一些复杂的场景中,可以结合使用supervisordsystemd来监控和管理守护进程,提供更多的灵活性和控制。supervisord是一种进程管理器,可以监控和自动重启被管理的子进程。

守护进程的调试和日志记录

调试守护进程是一个具有挑战性的任务,因为守护进程没有与终端直接交互。调试守护进程的方法包括:

  1. 使用syslog记录日志:守护进程可以将重要的信息记录到syslog系统日志中,以便管理员分析和调试。使用openlog()syslog()函数来记录日志信息。
  2. 使用信号(signals)进行调试:可以使用信号(如SIGUSR1SIGUSR2)来控制守护进程的行为,或者触发守护进程的状态转储。
  3. 使用调试工具gdb等调试工具可以附加到正在运行的守护进程,以调试它们的行为。
  4. 开发环境调试:在开发环境中以非守护进程的方式运行代码,以便更容易地进行调试和测试。

守护进程的安全性

  1. 权限控制:尽量以最低权限用户运行守护进程,以减少潜在的安全风险。
  2. 避免使用动态代码执行:守护进程应避免运行来自外部来源的代码或指令,除非经过充分的验证和安全检查。
  3. 监控和日志记录:确保守护进程的活动被充分监控和记录,以便检测和响应潜在的安全事件。
  4. 隔离和沙箱:使用Linux容器(如Docker)或沙箱技术来隔离守护进程的运行环境,以减少潜在的安全威胁面。

结论

守护进程在Linux系统的稳定性和安全性方面起着至关重要的作用。通过遵循最佳实践来编写和管理守护进程,确保它们安全可靠地执行系统任务,是每一个系统管理员

和开发者需要掌握的技能。理解和管理守护进程的工作原理,不仅有助于提高系统的整体性能,还能有效应对系统运行中的各类挑战。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 讯飞语音转文字怎么样?试试这4款工具吧!
  • 动态规划解决LCS问题
  • ElasticSearch底层原理解析
  • ESXI8.0 vsphere vcenter 多网卡多网段配置
  • OpenHarmony开发实战:动画样式(JS),2024年最新自学HarmonyOS鸿蒙
  • 三菱伺服电机抱闸(刹车)的用法
  • 研1日记9
  • 开源FormCreate低代码表单组件的配置项和事件的详解
  • 【二】TDEngine快速入门
  • 深入理解FastAPI的response_model:自动化数据验证与文档生成
  • linux学习之线程2:线程控制与使用
  • 一例pyinstaller打包的cs马鉴赏
  • SprinBoot+Vue校园车辆管理系统的设计与实现
  • (Java企业 / 公司项目)点赞业务系统设计-批量查询点赞状态(二)
  • 【区块链 + 人才服务】Blockchain Workshop- 区块链编程实践平台 | FISCO BCOS应用案例
  • [译] 理解数组在 PHP 内部的实现(给PHP开发者的PHP源码-第四部分)
  • “寒冬”下的金三银四跳槽季来了,帮你客观分析一下局面
  • 「前端」从UglifyJSPlugin强制开启css压缩探究webpack插件运行机制
  • 【comparator, comparable】小总结
  • HTTP传输编码增加了传输量,只为解决这一个问题 | 实用 HTTP
  • JavaScript HTML DOM
  • JAVA并发编程--1.基础概念
  • JS函数式编程 数组部分风格 ES6版
  • js继承的实现方法
  • Linux学习笔记6-使用fdisk进行磁盘管理
  • Logstash 参考指南(目录)
  • mac修复ab及siege安装
  • vagrant 添加本地 box 安装 laravel homestead
  • 从零到一:用Phaser.js写意地开发小游戏(Chapter 3 - 加载游戏资源)
  • 检测对象或数组
  • 我看到的前端
  • HanLP分词命名实体提取详解
  • Mac 上flink的安装与启动
  • ​【已解决】npm install​卡主不动的情况
  • ​14:00面试,14:06就出来了,问的问题有点变态。。。
  • ## 1.3.Git命令
  • (Arcgis)Python编程批量将HDF5文件转换为TIFF格式并应用地理转换和投影信息
  • (二)WCF的Binding模型
  • (附源码)计算机毕业设计SSM基于java的云顶博客系统
  • (南京观海微电子)——I3C协议介绍
  • (入门自用)--C++--抽象类--多态原理--虚表--1020
  • (四) 虚拟摄像头vivi体验
  • (原创)Stanford Machine Learning (by Andrew NG) --- (week 9) Anomaly DetectionRecommender Systems...
  • (转)Sql Server 保留几位小数的两种做法
  • ***监测系统的构建(chkrootkit )
  • .net core docker部署教程和细节问题
  • .NET Core SkiaSharp 替代 System.Drawing.Common 的一些用法
  • .NET 事件模型教程(二)
  • .NET 指南:抽象化实现的基类
  • .netcore 如何获取系统中所有session_ASP.NET Core如何解决分布式Session一致性问题
  • /bin/bash^M: bad interpreter: No such file or directory
  • ??如何把JavaScript脚本中的参数传到java代码段中
  • @param注解什么意思_9000字,通俗易懂的讲解下Java注解
  • @reference注解_Dubbo配置参考手册之dubbo:reference
  • [ 2222 ]http://e.eqxiu.com/s/wJMf15Ku