0

0

c++ systemd服务编写 c++如何编写一个linux后台守护进程

星降

星降

发布时间:2026-03-17 20:22:00

|

263人浏览过

|

来源于php中文网

原创

C++程序在systemd中启动后立即退出,是因为未正确配置Type=及进程生命周期管理;应设Type=simple并确保main中阻塞等待信号,同时配置User=、WorkingDirectory=、Environment=等关键项。

c++ systemd服务编写 c++如何编写一个linux后台守护进程

systemd 服务文件里为什么 ExecStart 启动 C++ 程序后立刻退出?

因为没告诉 systemd 这是个长期运行的守护进程,它默认把进程当一次性命令执行完就认为服务“成功启动”了。结果进程一结束,systemd 就标记为 inactive (dead),甚至反复重启(如果配了 Restart=always)。

根本原因不是 C++ 写得不对,而是 systemd 的服务类型(Type=)没匹配上程序行为:

  • Type=simple(默认):要求 ExecStart 启动的进程就是主服务进程,且必须持续运行;C++ 程序如果没做任何后台化处理(比如 fork + exit 父进程),它跑完 main 就退出,systemd 立刻认为服务崩了
  • Type=forking:适用于传统 daemon,程序自己 fork 出子进程后父进程退出——但现代 C++ 程序极少手动 fork,容易出错且不必要
  • Type=exec:和 simple 类似,但更严格要求进程不能 fork,适合 exec 后直接替换自身的情况

✅ 推荐做法:C++ 程序保持前台运行(不 fork、不 setsid、不重定向 stdio),在 systemd 服务文件中显式设 Type=simple,并确保 main 函数里有阻塞逻辑(如事件循环、std::this_thread::sleep_for 或信号等待)。

C++ 程序如何避免被 systemd 当成“瞬间崩溃”?

核心是让主线程活下来,同时不卡死、不占用无谓 CPU。别用 while(true) sleep(1) 这种轮询,既浪费资源又难响应信号。

立即学习C++免费学习笔记(深入)”;

实操建议:

  • sigwaitsignalfd(Linux 特有)等待 SIGTERM,这是 systemd 停止服务时发的标准信号
  • 如果用了网络库(如 libuv、Boost.Asio、或自建 epoll 循环),确保事件循环本身能响应中断,不要屏蔽 SIGTERM
  • 避免在全局构造函数或 main 开头做耗时初始化(如连数据库失败就直接 return),否则 systemd 会因超时(TimeoutStartSec=)判定启动失败
  • 日志输出走 stdout/stderr,systemd 会自动捕获并存入 journal;别写死到 /var/log/xxx.log,除非你手动配置 StandardOutput=journal+console 并确保目录可写

示例片段(简化版信号等待):

小绿鲸英文文献阅读器
小绿鲸英文文献阅读器

英文文献阅读器,专注提高SCI阅读效率

下载
#include <csignal>
#include <thread>
#include <chrono>

volatile sig_atomic_t running = 1;
void signal_handler(int) { running = 0; }

int main() {
    std::signal(SIGTERM, signal_handler);
    std::signal(SIGINT, signal_handler);

    while (running) {
        // 做实际工作,或短暂休眠
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }
    return 0;
}

服务文件里哪些 systemd 配置项最容易漏?

光写对 Type= 不够,几个关键项漏掉会导致权限错误、路径找不到、或无法自动拉起。

必须检查:

  • User=Group=:不设的话默认以 root 运行;若程序不需要特权,明确指定非 root 用户(如 User=myapp),避免安全风险
  • WorkingDirectory=:C++ 程序里用相对路径读配置或写临时文件时,这个值决定起点;不设则默认是 /,大概率导致 open 失败
  • Environment=EnvironmentFile=:C++ 代码依赖环境变量(如 CONFIG_PATH)时,必须在这里声明,别指望 shell profile 生效
  • Restart=on-failureRestart=always:仅当程序确实支持热重启时才开;否则先关掉,避免崩溃后无限拉起掩盖问题
  • LimitNOFILE=65536:如果程序要处理大量连接,不调高会卡在 EMFILE

典型服务单元片段:

[Service]
Type=simple
User=myapp
Group=myapp
WorkingDirectory=/opt/myapp
Environment=CONFIG_PATH=/etc/myapp/config.yaml
ExecStart=/opt/myapp/myapp-daemon
Restart=on-failure
RestartSec=5
LimitNOFILE=65536

调试时 journalctl 看不到输出?

不是程序没打日志,是 systemd 捕获了但没显示全,或者日志级别被过滤了。

排查步骤:

  • 确认程序真的往 stdoutstderr 输出了(别只打 printf 却忘了 fflush(stdout);C++ 用 std::cout << "msg" << std::endl;std::endl 自带 flush)
  • 查 journal:用 journalctl -u myapp.service -n 100 -f 实时跟踪,加 -o short-precise 看毫秒级时间戳
  • 如果只有启动日志、没后续输出,大概率是程序启动后立刻崩溃退出了——用 journalctl -u myapp.service --since "1 minute ago" 查完整生命周期
  • 检查 SELinux 状态:sestatus,如果是 enforcing 模式,可能阻止程序访问文件或端口,临时设为 permissive 测试(sudo setenforce 0

最常被忽略的一点:systemd 默认限制单次日志行长度为 48KB,超长日志会被截断。如果 C++ 日志是大 JSON 或堆栈,得在服务文件里加 SystemMaxLineLength=1M(需 systemd v240+)。

相关文章

c++速学教程(入门到精通)
c++速学教程(入门到精通)

c++怎么学习?c++怎么入门?c++在哪学?c++怎么学才快?不用担心,这里为大家提供了c++速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
json数据格式
json数据格式

JSON是一种轻量级的数据交换格式。本专题为大家带来json数据格式相关文章,帮助大家解决问题。

458

2023.08.07

json是什么
json是什么

JSON是一种轻量级的数据交换格式,具有简洁、易读、跨平台和语言的特点,JSON数据是通过键值对的方式进行组织,其中键是字符串,值可以是字符串、数值、布尔值、数组、对象或者null,在Web开发、数据交换和配置文件等方面得到广泛应用。本专题为大家提供json相关的文章、下载、课程内容,供大家免费下载体验。

549

2023.08.23

jquery怎么操作json
jquery怎么操作json

操作的方法有:1、“$.parseJSON(jsonString)”2、“$.getJSON(url, data, success)”;3、“$.each(obj, callback)”;4、“$.ajax()”。更多jquery怎么操作json的详细内容,可以访问本专题下面的文章。

337

2023.10.13

go语言处理json数据方法
go语言处理json数据方法

本专题整合了go语言中处理json数据方法,阅读专题下面的文章了解更多详细内容。

84

2025.09.10

while的用法
while的用法

while的用法是“while 条件: 代码块”,条件是一个表达式,当条件为真时,执行代码块,然后再次判断条件是否为真,如果为真则继续执行代码块,直到条件为假为止。本专题为大家提供while相关的文章、下载、课程内容,供大家免费下载体验。

108

2023.09.25

printf用法大全
printf用法大全

php中文网为大家提供printf用法大全,以及其他printf函数的相关文章、相关下载资源以及各种相关课程,供大家免费下载体验。

76

2023.06.20

fprintf和printf的区别
fprintf和printf的区别

fprintf和printf的区别在于输出的目标不同,printf输出到标准输出流,而fprintf输出到指定的文件流。根据需要选择合适的函数来进行输出操作。更多关于fprintf和printf的相关文章详情请看本专题下面的文章。php中文网欢迎大家前来学习。

309

2023.11.28

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

448

2023.07.18

Python WebSocket实时通信与异步服务开发实践
Python WebSocket实时通信与异步服务开发实践

本专题聚焦 Python 在实时通信场景中的开发实践,系统讲解 WebSocket 协议原理、长连接管理、消息推送机制以及异步服务架构设计。内容包括客户端与服务端通信实现、连接稳定性优化、消息队列集成及高并发处理策略。通过完整案例,帮助开发者构建高效稳定的实时通信系统,适用于聊天应用、实时数据推送等场景。

7

2026.03.18

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C# 教程
C# 教程

共94课时 | 11.6万人学习

C 教程
C 教程

共75课时 | 5.6万人学习

C++教程
C++教程

共115课时 | 22.5万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号