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

在Linux中如何创建自定义的systemd服务的步骤

1.systemd 服务文件的基本结构

systemd 服务文件包含三个重要且必要的配置部分,分别是[Unit]、[Service]和[Install]部分。这类文件以**.service**作为扩展名,并使用井号(#)添加单行注释。

以下是一个systemd服务文件的示例:

[Unit]
Description=Apache web server
After=network.target
Before=nextcloud-web.service[Service]
ExecStart=/usr/local/apache2/bin/httpd -D FOREGROUND -k start
ExecReload=/usr/local/apache2/bin/httpd -k graceful
Type=notify
Restart=always[Install]
WantedBy=default.target
RequiredBy=network.target

下面解释每一部分的含义。


1.1[Unit]部分

Unit部分用于定义服务单元本身的元信息和描述。具体包含:服务描述文本、依赖关系等配置项。

该段主要字段说明:

  • Description:服务的可读性描述文本

  • After:定义服务启动顺序依赖。例如配置Apache服务时,通常需指定其在network.target之后启动(即网络就绪后再启动Web服务)

  • Before:定义当前服务需在指定服务之前启动。例如示例中要求"Nextcloud服务启动前必须确保Apache已运行",这是因为Nextcloud依赖Apache服务。与After类似,可指定target或其他服务


1.2[Service]部分

Service部分定义服务的启动、终止等运行时行为。

该段核心字段说明:

  • ExecStart:服务启动时执行的命令(示例中为启动Apache服务)

  • ExecReload(可选):定义服务重启机制。对于涉及磁盘I/O(特别是数据库类服务),建议配置优雅终止方式

  • Type:定义进程启动类型,可选值包括: simple(默认值)、exec、forking、oneshot、dbus、notify、idle

  • Restart(推荐配置):定义服务异常退出时的重启策略,可选值包括: no(不重启)、on-success、on-failure、on-abnormal、on-watchdog、on-abort、always


1.3[Install]部分

Install部分定义服务安装行为(即通过systemctl enable/disable启用/禁用服务时的配置)。

该段关键字段:

  • WantedBy:指定系统运行级别(runlevels)关联。例如:

    • default.target表示系统初始化完成后(用户登录阶段)

    • 图形界面服务通常关联graphical.target

  • RequiredBy:与WantedBy类似,但建立的是强依赖关系(依赖项不满足时将导致服务启动失败)


2.创建自定义的 systemd 服务

下面我们分别创建两个 systemd 服务,一个需要超级用户权限,另一个以普通用户身份执行。

二者的区别是 root 用户执行的服务与普通用户执行的服务 systemd 服务文件的位置不同

2.1 创建root 用户的 systemd 服务

下面是自己编写的一个名为 sys-update.sh 的脚本,现在希望以 root 用户在系统启动时自动运行。该脚本的绝对路径是 /root/.scripts/sys-update.sh。以下是脚本内容:

#!/usr/bin/env bashif [ ${EUID} -ne 0 ]
thenexit 1 # this is meant to be run as root
fiapt-get update 1>/dev/null 2>>/root/logs/sys-update.log

这个脚本的功能是这样的,首先,它会检查当前用户是否为root用户,如果是 root 用户,就会执行apt-get update命令,该命令输出的所有错误信息将被追加到/root/logs/sys-update.log文件中,而其他输出则会被重定向到/dev/null文件。

1)创建systemd服务文件

接下来我们为这个脚本创建 systemd 服务文件。但在开始之前,需要了解需要超级用户权限的"systemd服务文件"应该放在什么位置。

通常最佳实践是将这些systemd服务文件放置在/etc/systemd/system/目录下。

因此,我将创建一个名为update-on-boot.service的文件,其完整路径为/etc/systemd/system/update-on-boot.service

下同是这个文件的内容:

[Unit]
Description=Keeping my sources fresher than Arch Linux
After=multi-user.target[Service]
ExecStart=/usr/bin/bash /root/.scripts/sys-update.sh
Type=simple[Install]
WantedBy=multi-user.target

这是一个非常简单的 systemd 服务文件。它所做的只是使用 bash 解释器来解释/root/.script/sys-update.sh脚本并执行它。

2)启用服务

首先重新加载systemd守护进程配置,这样使刚才新创建(修改)的systemd配置立即生效:

sudo systemctl daemon-reload

接着启用我们自定义的 systemd 服务,它的语法如下:

sudo systemctl enable SERVICE-NAME.service

这样,我们就可以这样启动前面定义的systemd服务:

sudo systemctl enable update-on-boot.service

该服务是否启用成功,可以用下面语法进行检查:

sudo systemctl is-enabled SERVICE-NAME.service
$ sudo systemctl is-enabled update-on-boot.service
enabled
2.2创建普通用户的 systemd 服务

前面的例子是服务在系统启动时启动,下面我们创建一个打算在关闭之前运行的脚本。

这个脚本的文件名为big-uptime.sh,它的完整路径是/home/pratham/.scripts/big-uptime.sh,以下是它的内容:

#!/usr/bin/env bashuptime | tee -a /home/pratham/logs/uptime.log

这个脚本的功能是将系统运行时间记录到/home/pratham/logs/uptime.log文件中,相当于一个方便的计时器!

1)创建systemd服务文件

现在我们来为它创建一个systemd服务文件,但在开始之前,需要了解普通用户的systemd服务文件**(unit文件**)应该存放在哪里。普通用户的systemd服务文件应该放在~/.config/systemd/user/目录下。

通常情况下,~/.config/systemd/user/目录并不存在,所以需要先创建这个目录。可以使用以下命令创建:

mkdir -p ~/.config/systemd/user

以下是什么pratham用户的systemd服务文件的内容:

[Unit]
Description=Log uptime in scoreboard
DefaultDependencies=no
Before=shutdown.target[Service]
Type=oneshot
ExecStart=/usr/bin/bash /home/pratham/.scripts/big-uptime.sh
TimeoutStartSec=0[Install]
WantedBy=shutdown.target

这个systemd服务文件与之前的有几个关键区别:

其中最重要的是它的Type被设置为"oneshot"。

Type=oneshot时,systemd会确保在所有服务启动/停止过程中,必须等待当前服务完全初始化或启动完成后才会继续执行其他服务。

现在把这个systemd服务文件保存为~/.config/systemd/user/scoreboard.service

2)启用服务

首先,重新加载systemd

systemctl --user daemon-reload

然后,启用该自定义的systemd 服务:

systemctl --user enable scoreboard.service

同样,最后检查服务的状态:

$ systemctl --user is-enabled scoreboard.service
enabled
http://www.xdnf.cn/news/3883.html

相关文章:

  • 动静态库【Linux操作系统】
  • 股指期货风险管理功能及基差、升水、贴水的影响
  • 牛客月赛115 C题-命运之弹 题解
  • Linux环境下的进程创建、退出和进程等待
  • 谷歌 NotebookLM 支持生成中文播客
  • n8n 条件节点详解:IF 与 Switch 的多分支工作流设计
  • 虚函数VS虚拟继承:C++多重继承二义性破解与性能调优
  • 论快乐的学习和学习的快乐
  • 万字详解ADC药物Payload
  • Debezium 架构详解与实战示例
  • 【操作系统】深入理解内存管理:从虚拟内存到OOM Killer
  • cloudfare+gmail 配置 smtp 邮箱
  • 【CISCO】Se2/0, Se3/0:串行口(Serial) 这里串口的2/0 和 3/0分别都是什么?
  • React hooks详解
  • 快速外网访问,证书自动续约 | 极空间IPv4IPv6 DDNS 配置详解
  • 数据结构与算法:回溯
  • Python:Seaborn 美化图表的技术指南
  • 【五一培训】Day 4
  • 常用命令集合
  • PCB叠层设计方案
  • 探秘DeepSeek模型参数:解锁AI潜能的密码
  • GenCLS++:通过联合优化SFT和RL,提升生成式大模型的分类效果
  • Python之学习笔记(六)
  • Prompt compress 技术探究-LLMLingua
  • SpringAi接入DeepSeek大模型
  • SurfSense开源程序是NotebookLM / Perplexity / Glean的开源替代品,连接到外部来源,如搜索引擎
  • ArrayList的扩容机制(源码解析)
  • 深度学习的简单介绍
  • PISI:眼图1:眼图相关基本概念
  • 使用synchronized关键字同步Java线程