0

0

Linux如何创建自定义systemd服务

P粉602998670

P粉602998670

发布时间:2025-09-05 13:51:02

|

540人浏览过

|

来源于php中文网

原创

答案是编写.service文件并配置重启策略、日志管理、依赖关系和权限隔离。首先创建包含[Unit]、[Service]、[Install]三部分的service文件,设置Type、ExecStart、User、Restart等关键参数;接着将文件放入/etc/systemd/system/目录,执行daemon-reload加载配置;然后通过enable设置开机自启,start启动服务;最后用status和journalctl排查问题。相比传统脚本,systemd具备并行启动、依赖管理、集中日志、资源控制和自动重启等优势,通过合理配置可确保服务稳定可靠运行。

linux如何创建自定义systemd服务

在Linux系统上创建自定义systemd服务,本质上就是编写一个

.service
单元文件,来告诉systemd如何启动、停止和管理你的应用程序或脚本。这就像是给你的程序一个“身份卡”和一套“行为准则”,让操作系统能以统一且高效的方式来照看它。完成这个文件后,将其放置在systemd能找到的目录中,然后通过几个简单的命令就能让你的服务跑起来,并且在系统启动时自动运行。

解决方案

创建自定义systemd服务通常涉及以下几个核心步骤。我个人觉得,理解每一步背后的逻辑比单纯记住命令更重要,因为这能帮助你在遇到问题时快速定位。

第一步:编写你的服务单元文件

这是最关键的一步。你需要创建一个以

.service
为后缀的文件,比如
my-app.service
。这个文件通常放在
/etc/systemd/system/
目录下。选择这个目录是因为它用于存放系统管理员自定义的单元文件,优先级高于系统默认的单元文件,也方便管理。

一个典型的

.service
文件会包含三个主要部分:
[Unit]
[Service]
[Install]

# /etc/systemd/system/my-app.service

[Unit]
Description=我的自定义应用程序服务
# 这个服务在网络准备好之后才启动,对于需要网络的应用很重要。
# 如果你的应用不需要网络,可以省略或改为其他依赖。
After=network.target

[Service]
# Type=simple 表示ExecStart定义的命令就是主进程。
# 如果你的程序会fork出子进程然后主进程退出,可能需要Type=forking。
Type=simple
# 定义服务启动时执行的命令。这里我假设你有一个Python脚本。
# 最好使用绝对路径,避免环境问题。
ExecStart=/usr/bin/python3 /opt/my-app/app.py
# 定义服务停止时执行的命令,可选。
# 如果不指定,systemd会发送SIGTERM信号。
# ExecStop=/usr/bin/pkill -f "python3 /opt/my-app/app.py"
# 服务的运行用户和组,出于安全考虑,尽量不要用root。
User=myuser
Group=myuser
# 服务的工作目录。
WorkingDirectory=/opt/my-app/
# 当服务异常退出时,systemd会尝试重启它。
# on-failure表示只有在非正常退出(如错误码非0)时才重启。
# always表示无论如何都重启。
Restart=on-failure
# 重启前等待的秒数。
RestartSec=5
# 标准输出和标准错误重定向到journald,方便日志查看。
StandardOutput=journal
StandardError=journal

[Install]
# WantedBy=multi-user.target 表示当系统进入多用户模式(正常运行级别)时,
# 这个服务会被启动。这是最常见的设置,意味着系统启动时自动运行。
WantedBy=multi-user.target

这里我用了一个Python脚本作为例子,但

ExecStart
可以是任何可执行文件或脚本。关键是路径要正确,且脚本有执行权限。

第二步:重新加载systemd配置

在你创建或修改了

.service
文件后,systemd守护进程并不会立即知道这些变化。你需要告诉它去重新扫描配置目录:

sudo systemctl daemon-reload

这步非常重要,否则systemd不会找到你的新服务或应用你的修改。

第三步:启用你的服务

启用服务意味着systemd会在系统启动时自动启动它。

sudo systemctl enable my-app.service

这个命令会在

/etc/systemd/system/multi-user.target.wants/
目录下创建一个指向你服务文件的软链接。

第四步:启动你的服务

现在,你可以手动启动你的服务了:

sudo systemctl start my-app.service

第五步:检查服务状态

随时查看你的服务是否正常运行,以及最近的日志输出:

sudo systemctl status my-app.service

如果一切顺利,你会看到服务处于“active (running)”状态。

如何确保自定义systemd服务稳定可靠地运行?

让一个服务“跑起来”和让它“稳定可靠地跑起来”是两码事。我个人在部署生产环境服务时,会特别关注几个点,它们是确保服务健壮性的基石。

首先是重启策略(Restart Policy)。在

[Service]
部分,
Restart=
指令至关重要。我通常会设置为
on-failure
,这意味着如果我的应用程序因为内部错误(非正常退出码)而崩溃,systemd会自动尝试重启它。配合
RestartSec=5
(重启前等待5秒),可以避免服务在短时间内反复崩溃导致系统资源耗尽,给服务一个“喘息”的机会。对于某些极端情况,比如内存溢出,可能需要更长的
RestartSec
或者更复杂的外部监控。

其次是日志管理。我强烈建议将

StandardOutput
StandardError
都设置为
journal
。这样做的好处是,所有的日志都会被集中到systemd的日志系统
journald
中,你可以用
journalctl -u my-app.service
命令方便地查看、过滤和管理日志,而不是让日志散落在各个文件里。这在故障排查时简直是救命稻草。

再者是资源限制。对于一些资源密集型或可能失控的服务,使用

LimitNOFILE
(限制打开文件句柄数)、
LimitNPROC
(限制进程数)等指令可以有效防止单个服务耗尽系统资源。这就像给你的服务划定了一个“沙盒”,避免它影响到其他关键系统组件。

还有依赖关系

[Unit]
部分的
After=
Requires=
指令定义了服务的启动顺序和依赖。比如,一个数据库应用肯定需要
network.target
和数据库服务(如
postgresql.service
)都启动后才能正常工作。如果依赖没处理好,服务可能在依赖项还没准备好时就启动,然后失败。我通常会先手动测试服务的启动流程,确认所有依赖都已就绪。

最后是权限隔离。在

[Service]
部分指定
User=
Group=
非常重要。永远不要让你的服务以
root
用户运行,除非万不得已。创建一个专门的用户和组来运行服务,并只赋予它必要的权限,这是最基本的安全实践。systemd还提供了
ProtectSystem=full
ProtectHome=true
等更高级的安全选项,可以进一步限制服务对文件系统的访问,进一步增强安全性。

视野自助系统小型企业版2.0 Build 20050310
视野自助系统小型企业版2.0 Build 20050310

自定义设置的程度更高可以满足大部分中小型企业的建站需求,同时修正了上一版中发现的BUG,优化了核心的代码占用的服务器资源更少,执行速度比上一版更快 主要的特色功能如下: 1)特色的菜单设置功能,菜单设置分为顶部菜单和底部菜单,每一项都可以进行更名、选择是否隐 藏,排序等。 2)增加企业基本信息设置功能,输入的企业信息可以在网页底部的醒目位置看到。 3)增加了在线编辑功能,输入产品信息,企业介绍等栏

下载

systemd服务与传统启动脚本相比,有哪些显著优势?

回想我刚接触Linux那会儿,都是用

rc.local
或者在
/etc/init.d/
下写一堆shell脚本来管理服务,那真是段“狂野西部”的岁月。systemd出现后,我个人觉得它带来的变革是巨大的,尤其是以下几个显著优势:

首先,启动速度和并行化。传统的SysV init脚本是串行执行的,一个服务启动完才能轮到下一个。systemd通过其复杂的依赖关系管理,能够识别出哪些服务可以并行启动,从而大大缩短了系统的启动时间。这就像是把单车道变成了多车道高速公路。

其次,强大的依赖管理。在SysV init中,依赖关系通常通过脚本中的注释来暗示,或者需要手动调整启动顺序的数字。systemd则提供了

After=
,
Requires=
,
Wants=
等清晰明了的指令来定义服务间的依赖关系,这让服务的管理和维护变得异常直观和健壮。你不需要再去猜测哪个服务应该先启动,systemd会帮你处理好。

再者,统一的日志管理。前面提到了

journald
。以前,每个服务可能都有自己的日志文件,散落在
/var/log/
的各个角落,查看和分析日志非常不便。systemd将所有服务的日志都集中到
journald
中,通过
journalctl
命令就能进行统一的查询、过滤和分析,大大提高了故障排查的效率。这就像是拥有了一个中央监控室。

还有,资源控制(Cgroups)集成。systemd与Linux内核的Cgroups紧密集成,这意味着你可以非常精细地控制每个服务所能使用的CPU、内存、I/O等资源。这对于防止单个服务耗尽系统资源,或者在多租户环境中进行资源隔离非常有用。这是传统init脚本很难实现的功能。

最后,服务监控与自动重启。systemd能够持续监控服务的状态,并在服务异常退出时根据配置(如

Restart=on-failure
)自动重启服务。这为应用程序提供了一层基础的自我修复能力,减少了人工干预的需要。传统的init脚本需要额外的工具(如
supervisord
)才能实现类似的功能。

这些优势加起来,使得systemd在管理复杂系统服务时,无论是效率、可靠性还是易用性上,都远超传统的init系统。

自定义systemd服务遇到问题时,我应该如何进行故障排查?

哪怕是经验再丰富的开发者,在配置systemd服务时也难免会遇到一些“小插曲”。关键在于,当服务不按预期工作时,你得知道从哪里入手去“审问”它。我个人觉得,故障排查就像是侦探破案,需要一步步抽丝剥茧。

第一步,也是最直接的一步,就是检查服务状态

sudo systemctl status my-app.service

这个命令会告诉你服务当前是运行中、失败、还是停止。更重要的是,它会显示最近的几行日志,以及服务进程的退出代码。如果状态显示

failed
,那么退出代码(Exit Code)通常能给你提供第一个线索。

第二步,深入查看日志

如果

status
命令提供的日志信息不够,或者你想看更早的日志,
journalctl
就是你的好帮手。

sudo journalctl -u my-app.service

这个命令会显示该服务的所有日志。我通常会加上

-f
(follow)来实时查看日志,或者加上
--since "1 hour ago"
来查看特定时间段的日志。

sudo journalctl -u my-app.service -f # 实时跟踪日志
sudo journalctl -u my-app.service --since "2023-10-27 10:00:00" # 查看特定时间点后的日志

日志往往能揭示服务启动失败的具体原因,比如找不到文件、权限不足、端口被占用、程序内部错误等。

第三步,手动执行

ExecStart
命令

很多时候,服务在systemd下启动失败,但在终端手动执行

ExecStart
定义的命令却能成功。这通常意味着环境问题。我会在服务用户下,切换到
WorkingDirectory
,然后直接运行
ExecStart
中的命令。

sudo su - myuser # 切换到服务运行的用户
cd /opt/my-app/ # 进入工作目录
/usr/bin/python3 /opt/my-app/app.py # 尝试手动运行程序

如果手动运行失败,那么问题出在程序本身或其运行环境。如果手动运行成功,但在systemd下失败,那很可能是systemd服务文件中的配置问题,比如:

  • 权限问题:服务用户对程序文件、日志文件、数据目录是否有读写执行权限?
  • 环境变量:服务是否依赖某些环境变量?systemd默认提供的环境变量很少,你可能需要在服务文件中用
    Environment=
    EnvironmentFile=
    来设置。
  • 工作目录
    WorkingDirectory=
    是否设置正确?程序是否依赖当前工作目录来查找资源?
  • 依赖服务
    After=
    Requires=
    中的依赖服务是否真的已经启动并正常工作?

第四步,检查服务文件语法

虽然不常见,但服务文件本身可能存在语法错误。你可以使用

systemd-analyze verify
命令来检查你的服务文件。

systemd-analyze verify /etc/systemd/system/my-app.service

这个命令会指出服务文件中的任何语法错误或不规范之处。

通过这些步骤,你通常能够定位到问题的根源。记住,耐心和细致是故障排查的关键。

相关专题

更多
python开发工具
python开发工具

php中文网为大家提供各种python开发工具,好的开发工具,可帮助开发者攻克编程学习中的基础障碍,理解每一行源代码在程序执行时在计算机中的过程。php中文网还为大家带来python相关课程以及相关文章等内容,供大家免费下载使用。

774

2023.06.15

python打包成可执行文件
python打包成可执行文件

本专题为大家带来python打包成可执行文件相关的文章,大家可以免费的下载体验。

684

2023.07.20

python能做什么
python能做什么

python能做的有:可用于开发基于控制台的应用程序、多媒体部分开发、用于开发基于Web的应用程序、使用python处理数据、系统编程等等。本专题为大家提供python相关的各种文章、以及下载和课程。

767

2023.07.25

format在python中的用法
format在python中的用法

Python中的format是一种字符串格式化方法,用于将变量或值插入到字符串中的占位符位置。通过format方法,我们可以动态地构建字符串,使其包含不同值。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

719

2023.07.31

python教程
python教程

Python已成为一门网红语言,即使是在非编程开发者当中,也掀起了一股学习的热潮。本专题为大家带来python教程的相关文章,大家可以免费体验学习。

1425

2023.08.03

python环境变量的配置
python环境变量的配置

Python是一种流行的编程语言,被广泛用于软件开发、数据分析和科学计算等领域。在安装Python之后,我们需要配置环境变量,以便在任何位置都能够访问Python的可执行文件。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

570

2023.08.04

python eval
python eval

eval函数是Python中一个非常强大的函数,它可以将字符串作为Python代码进行执行,实现动态编程的效果。然而,由于其潜在的安全风险和性能问题,需要谨慎使用。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

579

2023.08.04

scratch和python区别
scratch和python区别

scratch和python的区别:1、scratch是一种专为初学者设计的图形化编程语言,python是一种文本编程语言;2、scratch使用的是基于积木的编程语法,python采用更加传统的文本编程语法等等。本专题为大家提供scratch和python相关的文章、下载、课程内容,供大家免费下载体验。

751

2023.08.11

c++ 根号
c++ 根号

本专题整合了c++根号相关教程,阅读专题下面的文章了解更多详细内容。

41

2026.01.23

热门下载

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

精品课程

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

共48课时 | 7.7万人学习

Git 教程
Git 教程

共21课时 | 3万人学习

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

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