Linux系统日志与守护进程开发实战指南
系统日志与守护进程
├── 系统日志syslog
│ ├── 日志路径: /var/log/syslog
│ └── 核心API
│ ├── openlog
│ ├── syslog
│ └── closelog
└── 守护进程daemon└── 创建步骤├── umask(0)├── fork+父进程退出├── setsid├── chdir('/')├── 关闭文件描述符└── 重定向标准IO
一、系统日志(syslog)核心技术
1. 日志系统架构
// 典型日志写入流程
openlog("MyDaemon", LOG_PID|LOG_CONS, LOG_DAEMON);
syslog(LOG_INFO, "Service started: PID=%d", getpid());
closelog();
2. syslog核心API详解
函数 | 参数说明 | 示例用法 |
---|---|---|
openlog() | ident: 程序标识 option: 日志选项 facility: 日志类别 | openlog("httpd", LOG_PID, LOG_DAEMON) |
syslog() | priority: 日志级别 format: 格式化字符串 | syslog(LOG_ERR, "Connection failed: %s", strerror(errno)) |
closelog() | 无参数 | closelog() |
常用选项组合:
// 日志选项
LOG_PID // 包含进程ID
LOG_CONS // 错误时输出到控制台
LOG_NDELAY // 立即打开连接// 日志类别
LOG_DAEMON // 守护进程
LOG_USER // 用户进程(默认)
LOG_LOCAL0 // 自定义类别0// 日志级别(降序)
LOG_EMERG → LOG_ALERT → LOG_CRIT → LOG_ERR
→ LOG_WARNING → LOG_NOTICE → LOG_INFO → LOG_DEBUG
3. 日志配置文件
/etc/rsyslog.conf 关键配置:
# 守护进程日志存储规则
daemon.* /var/log/daemon.log
# 自定义日志存储
local0.* /var/log/myapp.log
# 所有info级别日志
*.info /var/log/messages
日志轮转配置:
# /etc/logrotate.d/mydaemon
/var/log/myapp.log {dailyrotate 30compressmissingoknotifemptysharedscriptspostrotate/usr/bin/systemctl reload rsyslog > /dev/nullendscript
}
二、守护进程开发六步法
1. 标准创建流程
#include <unistd.h>int daemon(int nochdir, int noclose);
手动创建实现:
void create_daemon() {// Step 1: 清除文件掩码umask(0);// Step 2: 首次forkpid_t pid = fork();if (pid > 0) exit(EXIT_SUCCESS); // 父进程退出// Step 3: 创建新会话setsid();// Step 4: 二次fork(可选)pid = fork();if (pid > 0) exit(EXIT_SUCCESS);// Step 5: 切换工作目录chdir("/");// Step 6: 关闭文件描述符for (int fd = sysconf(_SC_OPEN_MAX); fd >= 0; fd--)close(fd);// Step 7: 重定向标准IOopen("/dev/null", O_RDWR); // stdindup(0); // stdoutdup(0); // stderr
}
2. 守护进程特征验证
# 查看进程关系
ps -efj | grep mydaemon# 预期输出特征:
# PID ≠ SID ≠ PGID
# TTY = ? (无控制终端)
# COMMAND = 守护进程名
三、实战:日志守护进程开发
1. 完整代码示例
#include <sys/stat.h>
#include <syslog.h>
#include <fcntl.h>
#include <unistd.h>int main() {// 创建守护进程if(daemon(0, 0) {perror("daemon");return 1;}// 打开日志连接openlog("MyDaemon", LOG_PID|LOG_NDELAY, LOG_DAEMON);// 主循环int counter = 0;while(1) {syslog(LOG_INFO, "Daemon running: %d cycles", ++counter);// 模拟工作sleep(5);// 错误模拟if(counter % 10 == 0) {syslog(LOG_WARNING, "Simulated warning event");}}closelog();return 0;
}
2. 系统服务配置
/etc/systemd/system/mydaemon.service:
[Unit]
Description=Custom Logging Daemon[Service]
ExecStart=/usr/sbin/mydaemon
Restart=always
RestartSec=30
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=mydaemon[Install]
WantedBy=multi-user.target
管理命令:
# 启动服务
sudo systemctl start mydaemon# 查看日志
journalctl -u mydaemon -f# 设置开机启动
sudo systemctl enable mydaemon
四、高级应用场景
1. 自定义日志过滤器
// 设置日志过滤级别
setlogmask(LOG_UPTO(LOG_WARNING));// 此时以下日志将被过滤
syslog(LOG_DEBUG, "Debug message"); // 不会被记录
2. 多守护进程日志分离
// 不同服务使用不同facility
openlog("WebServer", LOG_PID, LOG_LOCAL0);
openlog("DBServer", LOG_PID, LOG_LOCAL1);
配置分离存储:
# /etc/rsyslog.d/10-mydaemons.conf
local0.* /var/log/web.log
local1.* /var/log/db.log
五、调试与问题排查
1. 常见错误处理
错误现象 | 解决方案 |
---|---|
日志写入权限不足 | chown root:adm /var/log/* |
日志文件不滚动 | 检查logrotate配置及权限 |
守护进程启动失败 | 使用strace 跟踪系统调用 |
日志丢失 | 检查rsyslog服务状态 |
2. 实时日志监控
# 跟踪特定设施日志
tail -f /var/log/syslog | grep 'mydaemon'# 使用systemd日志
journalctl -f -t "MyDaemon"# 结构化日志查询
journalctl SYSLOG_IDENTIFIER=mydaemon --since "10min ago"
最佳实践:生产环境中建议采用日志分级策略:
- DEBUG级别:仅开发环境启用
- INFO级别:运行状态记录
- WARNING以上:实时告警通知
完整思维导图:系统日志与守护进程技术全景
扩展阅读:
- Rsyslog高性能日志架构设计
- Systemd Journal深度解析
- 分布式系统中的日志收集方案
整理笔记发送CSDN 博客,并将思维导图加在博客中