首页 > 运维 > linux运维 > 正文

Linux怎么创建自定义的systemd服务

P粉602998670
发布: 2025-09-15 16:38:01
原创
187人浏览过
答案:创建自定义systemd服务需编写.service文件并放置于/etc/systemd/system/,通过systemctl管理。具体步骤包括:使用绝对路径在[Service]中定义ExecStart,设置User、WorkingDirectory等参数,选择合适的Type类型(如simple、forking),配置Restart=on-failure实现故障重启;创建后运行sudo systemctl daemon-reload、enable、start启用服务,并用status和journalctl排查启动失败问题,常见原因有路径权限错误、脚本异常、Type类型不匹配等。

linux怎么创建自定义的systemd服务

在Linux中创建自定义的systemd服务,核心在于编写一个

.service
登录后复制
单元文件,它描述了你的程序或脚本如何启动、运行和停止。将这个文件放置到系统指定位置后,你就可以使用
systemctl
登录后复制
命令来管理它,实现开机自启、故障重启等功能。这让你的应用能像系统自带的服务一样,被
systemd
登录后复制
这个强大的初始化系统统一调度和监控。

解决方案

要让你的应用或脚本在Linux上像个“正经”的服务一样运行,被

systemd
登录后复制
管理起来,我们需要做的是定义一个
.service
登录后复制
单元文件。这就像给
systemd
登录后复制
写了一份操作指南,告诉它“我的这个程序叫什么,怎么启动,什么时候算启动成功,出问题了怎么办”。

首先,我们得创建一个

.service
登录后复制
文件。通常,我们会把它放在
/etc/systemd/system/
登录后复制
目录下。例如,如果你想创建一个名为
my_custom_app.service
登录后复制
的服务,那就这样:

sudo vim /etc/systemd/system/my_custom_app.service
登录后复制

文件内容大致会是这样:

[Unit]
Description=我的自定义应用程序服务
After=network.target # 这个服务在网络可用后启动

[Service]
Type=simple # 简单类型,表示ExecStart命令就是主进程,它会一直运行在前景
ExecStart=/usr/local/bin/my_custom_app_script.sh # 你的应用程序或脚本的完整路径
WorkingDirectory=/opt/my_custom_app/ # 设置工作目录,如果你的脚本需要
User=your_username # 指定运行服务的用户,建议不要用root,除非必要
Group=your_group # 指定运行服务的用户组
Restart=on-failure # 当服务失败时(非正常退出),自动重启
RestartSec=5s # 重启前等待5秒

[Install]
WantedBy=multi-user.target # 在多用户模式下启用此服务(即系统启动时)
登录后复制

这里面有几个关键部分:

  • [Unit]
    登录后复制
    : 描述服务的元数据和依赖关系。
    • Description
      登录后复制
      : 服务的简短描述,方便你识别。
    • After=network.target
      登录后复制
      : 这是一个很常见的依赖,意思是你的服务应该在网络服务启动之后再启动。你也可以指定其他服务,比如
      After=mysql.service
      登录后复制
  • [Service]
    登录后复制
    : 定义服务的行为。
    • Type
      登录后复制
      : 这非常重要,它告诉
      systemd
      登录后复制
      你的
      ExecStart
      登录后复制
      命令如何运行。
      simple
      登录后复制
      是最常见的,表示命令就是主进程,在前台运行。如果你的程序会自己fork到后台,你可能需要
      Type=forking
      登录后复制
      。我们稍后会详细聊聊
      Type
      登录后复制
    • ExecStart
      登录后复制
      : 这是启动你的服务所执行的命令或脚本。务必使用绝对路径,因为
      systemd
      登录后复制
      的环境变量可能不像你登录shell时那么丰富。
    • WorkingDirectory
      登录后复制
      : 如果你的脚本或程序需要访问相对路径的文件,设置这个会很有用。
    • User
      登录后复制
      ,
      Group
      登录后复制
      : 出于安全考虑,强烈建议用一个非特权用户来运行服务,而不是
      root
      登录后复制
    • Restart
      登录后复制
      : 定义了服务在何种情况下自动重启。
      on-failure
      登录后复制
      是一个很实用的选项,意味着如果你的程序崩溃了,
      systemd
      登录后复制
      会尝试重新启动它。
    • RestartSec
      登录后复制
      : 配合
      Restart
      登录后复制
      使用,指定重启前的等待时间。
  • [Install]
    登录后复制
    : 定义服务如何被“安装”到系统。
    • WantedBy=multi-user.target
      登录后复制
      : 这表示当系统进入多用户运行级别时(也就是我们日常使用的桌面或服务器模式),你的服务会被拉起来。

文件创建并保存后,你需要让

systemd
登录后复制
知道这个新文件:

sudo systemctl daemon-reload
登录后复制

接着,启用你的服务,让它在系统启动时自动运行:

sudo systemctl enable my_custom_app.service
登录后复制

然后,你可以手动启动它:

sudo systemctl start my_custom_app.service
登录后复制

最后,检查服务状态,看看它是否正常运行:

sudo systemctl status my_custom_app.service
登录后复制

如果一切顺利,你会看到服务处于

active (running)
登录后复制
状态。如果有什么问题,
status
登录后复制
命令也会显示最近的错误信息,或者你可以用
journalctl -u my_custom_app.service
登录后复制
查看更详细的日志。

这就是创建和管理一个基本

systemd
登录后复制
服务的流程。它提供了一个强大且灵活的方式来自动化你的应用程序。

Linux怎么创建自定义的systemd服务

为什么我的systemd服务启动失败了,该怎么排查?

服务启动失败,这简直是家常便饭。我遇到过太多次了,通常不是

systemd
登录后复制
本身的问题,而是我们配置或者脚本本身的问题。排查起来,其实就是一步步缩小范围,找到真正的“罪魁祸首”。

最常见的几个原因,我总结了一下:

  1. ExecStart
    登录后复制
    命令路径或权限不对
    :这是新手最容易犯的错误。
    systemd
    登录后复制
    在启动服务时,它的
    PATH
    登录后复制
    环境变量通常很精简,不像你平时在终端里那么丰富。所以,你的
    ExecStart=/path/to/your_script.sh
    登录后复制
    里的脚本路径,必须是绝对路径。比如,不能只写
    python app.py
    登录后复制
    ,而要写
    /usr/bin/python /opt/my_app/app.py
    登录后复制
    。另外,脚本文件本身是不是有执行权限?
    chmod +x /path/to/your_script.sh
    登录后复制
    是必须的。
  2. 脚本本身有错误:你的脚本可能语法错误,或者依赖的环境变量、配置文件不存在。
    systemd
    登录后复制
    只是执行它,如果脚本一启动就崩溃,服务自然就失败了。
  3. 用户权限问题:你指定了
    User=your_username
    登录后复制
    ,但这个用户可能没有权限访问脚本需要的文件、目录,或者无法绑定到特定的端口。这时候,服务会因为权限不足而退出。
  4. 工作目录不对:如果你的脚本依赖于当前工作目录下的文件(比如
    ./config.json
    登录后复制
    ),但
    WorkingDirectory
    登录后复制
    没有设置或者设置错误,脚本就找不到这些文件。
  5. 依赖服务未启动:你设置了
    After=network.target
    登录后复制
    或者
    Requires=mysql.service
    登录后复制
    ,但依赖的服务没能正常启动,或者启动时间过长,你的服务可能就会超时失败。
  6. Type
    登录后复制
    类型选择错误
    :如果你的程序是传统的守护进程,会自己fork到后台,但你设置了
    Type=simple
    登录后复制
    systemd
    登录后复制
    会认为主进程退出了,服务就失败了。反之,如果你的程序是前台运行的,却设置了
    Type=forking
    登录后复制
    systemd
    登录后复制
    可能会因为找不到子进程而认为服务失败。

排查步骤,我一般是这么来:

  • 查看服务状态和日志:这是第一步,也是最关键的一步。
    sudo systemctl status my_custom_app.service
    登录后复制

    这个命令会给你一个快速概览,包括服务的状态、最近的错误信息,以及一些日志片段。 如果需要更详细的日志,用

    journalctl
    登录后复制

    sudo journalctl -u my_custom_app.service --since "10 minutes ago" -e
    登录后复制

    -u
    登录后复制
    指定单元,
    --since
    登录后复制
    限制时间范围,
    -e
    登录后复制
    跳到日志末尾。仔细阅读日志,通常错误信息会很明确。

  • 手动运行
    ExecStart
    登录后复制
    命令
    :以服务指定的用户身份,在服务指定的工作目录下,手动执行
    ExecStart
    登录后复制
    中定义的命令。
    # 假设你的服务用户是your_username,工作目录是/opt/my_custom_app/
    sudo -u your_username sh -c "cd /opt/my_custom_app/ && /usr/local/bin/my_custom_app_script.sh"
    登录后复制

    这样可以直接看到脚本的输出和错误信息,模拟

    systemd
    登录后复制
    的执行环境。

  • 检查文件和目录权限:确保脚本文件、日志文件、配置文件以及任何脚本需要访问的目录,都对服务运行的用户有正确的读写权限。
  • 简化脚本:如果脚本很复杂,可以先用一个简单的
    echo "Hello World"
    登录后复制
    脚本替换
    ExecStart
    登录后复制
    ,确保
    systemd
    登录后复制
    能成功启动一个最简单的服务,排除
    systemd
    登录后复制
    配置问题,然后逐步还原你的复杂脚本。
  • 环境变量:如果你的脚本依赖特定的环境变量,可以在
    [Service]
    登录后复制
    部分使用
    Environment=KEY=VALUE
    登录后复制
    EnvironmentFile=/path/to/env_file
    登录后复制
    来设置。

记住,日志是你的好朋友。大部分问题,日志里都会给出线索。

通义万相
通义万相

通义万相,一个不断进化的AI艺术创作大模型

通义万相596
查看详情 通义万相
Linux怎么创建自定义的systemd服务

systemd服务有哪些常见的Type类型,我该如何选择?

Type
登录后复制
指令是
systemd
登录后复制
服务配置中一个相当核心的概念,它告诉
systemd
登录后复制
你的服务主进程是如何启动和退出的。选错了
Type
登录后复制
,服务可能根本就启动不起来,或者
systemd
登录后复制
会误判服务状态。

我们来看看几个最常见的

Type
登录后复制
类型,以及我通常怎么选择:

  1. Type=simple
    登录后复制
    (默认值)

    • 行为
      ExecStart
      登录后复制
      中指定的命令就是主进程。
      systemd
      登录后复制
      认为服务在
      ExecStart
      登录后复制
      命令执行后立即启动成功。如果这个进程退出,
      systemd
      登录后复制
      会认为服务停止。
    • 适用场景:这是最常见、最简单的类型。适用于绝大多数在前台运行的应用程序或脚本,比如一个Web服务器(Nginx、Apache)、一个Python Flask应用、一个Node.js服务等,它们启动后会一直保持运行状态,直到被手动停止或崩溃。
    • 我的选择:如果我不确定,或者我的应用本身就是设计成在前台运行的,我通常会先尝试
      simple
      登录后复制
  2. Type=forking
    登录后复制

    • 行为
      ExecStart
      登录后复制
      中指定的命令会启动一个父进程,然后这个父进程会
      fork
      登录后复制
      出一个或多个子进程,并立即退出。
      systemd
      登录后复制
      会等待父进程退出,并期望子进程继续运行。它会尝试追踪这个子进程作为服务的主进程。为了帮助
      systemd
      登录后复制
      ,你通常需要指定
      PIDFile=/path/to/pidfile.pid
      登录后复制
      ,让
      systemd
      登录后复制
      知道哪个是主进程的PID。
    • 适用场景:适用于那些遵循传统Unix守护进程模式的应用程序。这些程序启动后,会立即将自身“后台化”,父进程退出,子进程继续提供服务。例如,一些老旧的Java应用、某些数据库服务、或者一些用C/C++编写的传统守护进程。
    • 我的选择:如果我的应用程序在启动命令执行后,主进程很快就退出了,但服务还在后台运行,那多半就是
      forking
      登录后复制
      类型。如果应用会生成PID文件,那
      PIDFile
      登录后复制
      指令就变得很重要了。
  3. Type=oneshot
    登录后复制

    • 行为
      ExecStart
      登录后复制
      命令执行并退出后,
      systemd
      登录后复制
      就认为服务已经成功“完成”了。它不会期望有任何进程持续运行。
    • 适用场景:非常适合那些只需要执行一次性任务的脚本或程序。比如,在系统启动时进行一些初始化配置、清理临时文件、数据库迁移、或者执行一个备份脚本。
    • 我的选择:当我需要一个服务在启动后执行某个操作,然后就“功成身退”时,
      oneshot
      登录后复制
      是最佳选择。有时,配合
      RemainAfterExit=yes
      登录后复制
      ,可以表示即使
      ExecStart
      登录后复制
      退出了,服务状态仍然是“active”,这在某些特定场景下很有用,比如一个只启动网络接口的服务。
  4. Type=notify
    登录后复制

    • 行为:类似于
      simple
      登录后复制
      ,但服务启动后,会通过
      sd_notify()
      登录后复制
      函数向
      systemd
      登录后复制
      发送一个“我准备好了”的信号。
      systemd
      登录后复制
      会等待这个信号,才认为服务真正启动成功。
    • 适用场景:适用于那些启动需要一定时间,并且希望
      systemd
      登录后复制
      能精确知道何时服务“就绪”的复杂应用程序。比如,一个Web应用可能需要加载大量数据,或者连接数据库,这些操作完成后才算真正可以对外提供服务。
    • 我的选择:当我的服务启动时间不确定,或者有复杂的初始化逻辑,并且我希望其他依赖它的服务能准确地在我服务真正可用后才启动时,
      notify
      登录后复制
      能提供更健壮的启动流程。这需要应用程序内部集成
      libsystemd
      登录后复制
      库来发送通知。

如何选择?

我的经验是:

  • 大多数现代应用(Web服务、API)
    Type=simple
    登录后复制
    。它们通常设计成在前台运行。
  • 传统守护进程,或者自行后台化的程序
    Type=forking
    登录后复制
    ,并尽量提供
    PIDFile
    登录后复制
  • 一次性任务或初始化脚本
    Type=oneshot
    登录后复制
  • 需要精确启动就绪状态的复杂应用
    Type=notify
    登录后复制

如果不确定,先从

simple
登录后复制
开始尝试。如果服务启动后立即退出,但你期望它继续运行,那可能就是
forking
登录后复制
或你的脚本本身有问题。如果服务启动后一直卡住,或者依赖它的服务启动失败,可能需要考虑
notify
登录后复制
来更明确地通知
systemd
登录后复制
就绪状态。

Linux怎么创建自定义的systemd服务

如何让我的systemd服务在特定条件下自动重启或停止?

systemd
登录后复制
服务具备“自我修复”能力,或者在特定情况下优雅地停止,是构建健壮系统的重要一环。
systemd
登录后复制
在这方面提供了非常强大的控制能力。

自动重启策略 (

Restart=
登录后复制
指令)

这是让服务在出现问题时自动恢复的关键。我通常会根据服务的性质来选择合适的重启策略。

  • Restart=no
    登录后复制
    (默认值)
    :服务停止后,无论是正常退出还是崩溃,都不会自动重启。这适用于那些一次性任务(比如
    Type=oneshot
    登录后复制
    的服务),或者你希望手动介入处理的服务。
  • Restart=on-success
    登录后复制
    : 仅当服务进程以退出码0(表示成功)退出时,才自动重启。这听起来有点反直觉,但有时用于一些特殊场景,比如一个周期性运行但每次成功后都需要重新启动的服务。
  • Restart=on-failure
    登录后复制
    : 这是我最常用的一个选项。当服务进程以非0退出码退出、被信号终止(如
    SIGSEGV
    登录后复制
    崩溃)、或者达到看门狗超时时,
    systemd
    登录后复制
    会尝试重启它。这意味着如果你的应用崩溃了,
    systemd
    登录后复制
    会尝试让它活过来。
  • Restart=on-abnormal
    登录后复制
    : 仅当服务进程被信号终止(如崩溃)或达到看门狗超时时重启。它不包括非0退出码的情况。
  • Restart=on-watchdog
    登录后复制
    : 仅当看门狗超时时重启。这需要服务本身支持
    systemd
    登录后复制
    的看门狗机制。
  • Restart=always
    登录后复制
    : 无论服务如何停止(正常退出、崩溃、被手动停止),
    systemd
    登录后复制
    都会尝试重启它。这个选项要慎用,如果服务一直崩溃,它会导致系统不断尝试重启,形成“重启风暴”,反而消耗系统资源。

通常,我会在

[Service]
登录后复制
部分这样配置:

Restart=on-failure
RestartSec=5s # 重启前等待5秒,避免服务在极短时间内反复崩溃又重启
登录后复制

RestartSec
登录后复制
非常重要,它提供了一个缓冲时间,防止服务在快速失败循环中耗尽系统资源。

为了防止无限重启导致的问题,

systemd
登录后复制
还提供了重启频率限制

  • StartLimitIntervalSec=60s
    登录后复制
    :

以上就是Linux怎么创建自定义的systemd服务的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

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