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

在 CentOS 7 中使用 systemd 创建自定义服务

systemd 创建自定义服务

  • 简述创建自定义服务步骤
      • 文件覆盖优先级
  • 创建服务流程
  • 在 /etc/systemd/system/ 目录下创建 .service 文件(需 root 权限):
    • 编写服务配置模板
      • Systemd 服务文件三大区块详解
        • [Unit] 区块 - 服务元数据与依赖
        • [Service] 区块 - 进程运行配置
        • [Install] 区块 - 开机启动配置
      • 完整示例
    • 设置权限和路径
    • 管理服务命令
    • 启动失败排查
    • 注意事项

简述创建自定义服务步骤

  • 创建服务文件:在 /etc/systemd/system/ 目录下创建一个新的服务文件,例如 myapp.service。使用 sudo 权限进行创建。
  • 编辑服务文件:使用文本编辑器(如 vi 或 nano)编写服务单元文件。
  • 重新加载 systemd 配置:每次修改服务文件后,需要运行 sudo systemctl daemon-reload 来重新加载配置。
  • 启用服务:使用 sudo systemctl enable myapp.service 设置开机启动。
  • 启动服务:使用 sudo systemctl start myapp.service 启动服务。
  • 检查服务状态:使用 sudo systemctl status myapp.service 查看服务状态。

文件覆盖优先级

在 CentOS 7 的 systemd 系统中,/usr/lib/systemd/system/ 和 /etc/systemd/system/ 两个目录有明确的区别:

  • systemd 加载配置的顺序(从高到低):
/etc/systemd/system/service.d/*.conf
/etc/systemd/system/service
/run/systemd/system/service.d/*.conf(临时配置)
/usr/lib/systemd/system/service.d/*.conf
/usr/lib/systemd/system/service
需求操作位置
安装新服务/etc/systemd/system/
修改现有服务参数/etc/systemd/system/service.d/
完全替换服务文件/etc/systemd/system/
查看软件原始配置/usr/lib/systemd/system/
添加开机启动依赖/etc/systemd/system/service.d/

/lib/systemd/system/(实际上是 /usr/lib/systemd/system/ 的符号链接)

特性/usr/lib/systemd/system//etc/systemd/system/
来源软件包安装的原始服务文件管理员自定义的服务文件或覆盖配置
优先级高(覆盖 /lib/ 中的配置)
是否会被覆盖软件升级时可能被覆盖不会被软件升级覆盖
推荐修改方式不应直接修改应在此目录添加自定义配置
目录类型系统默认目录(只读)管理员配置目录(可写)
  • 作用:存放软件包(通过 yum/rpm 安装)提供的原始服务文件
  • 特点:
    • 系统级别的默认配置
    • 软件升级时会覆盖此目录的文件
    • 不要直接修改这里的文件(修改会被覆盖)

创建服务流程

在 /etc/systemd/system/ 目录下创建 .service 文件(需 root 权限):

sudo vi /etc/systemd/system/myapp.service

编写服务配置模板

[Unit]
Description=服务描述
After=network.target    # 依赖关系[Service]
Type=forking     # 服务类型
ExecStart=/path/to/command
User=username           # 运行用户
Restart=on-failure      # 重启策略[Install]
WantedBy=multi-user.target

Systemd 服务文件三大区块详解

[Unit]
• 服务标识 (Description)
• 启动顺序 (After/Before)
• 依赖关系 (Requires/Wants)
[Service][Install]
• 进程控制 (Type/ExecStart)• 开机启动目标 (WantedBy)
• 运行环境 (User/Env)• 别名管理 (Alias)
• 资源限制 (MemoryLimit)
• 安全策略 (PrivateTmp)
[Unit] 区块 - 服务元数据与依赖

定义服务的描述、依赖关系和启动顺序

指令说明示例值
Description必填 服务描述信息(显示在 systemctl status 中)Description=Nginx Web Server
After定义启动顺序依赖(在此服务之后启动)After=network.target
Before定义反向依赖(在此服务之前启动)Before=shutdown.target
Requires强依赖 - 依赖服务失败则本服务失败Requires=mysql.service
Wants弱依赖 - 依赖服务失败不影响本服务Wants=postfix.service
Conflicts冲突服务 - 不能同时运行的服务Conflicts=httpd.service
Documentation服务文档链接Documentation=man:nginx(8)
Condition…启动条件检查(如 ConditionPathExists=/etc/nginx.conf)

[Unit] 区块示例

[Unit]
Description=High Performance Web Server
After=network.target remote-fs.target nss-lookup.target
Wants=postgresql.service
Documentation=https://nginx.org/en/docs/
[Service] 区块 - 进程运行配置

定义服务进程的执行方式和运行时行为

类别指令说明常用值
启动类型Type必填 进程启动类型simple、forking、oneshot、notify
ExecStart必填 启动命令(绝对路径)/usr/sbin/nginx -g “daemon off;”
ExecStartPre主命令前执行的预备命令/bin/mkdir -p /run/nginx
ExecStartPost主命令后执行的后续命令/bin/echo “Service started”
ExecReload重载服务时执行的命令/bin/kill -HUP $MAINPID
运行环境User运行服务的用户nginx、nobody
Group运行服务的用户组www-data
WorkingDirectory工作目录/var/www/html
Environment设置环境变量PORT=8080
EnvironmentFile从文件加载环境变量/etc/sysconfig/nginx
重启策略Restart服务退出时重启策略no、always、onfailure、on-abort
RestartSec重启前等待时间5s、1min
资源限制MemoryLimit内存限制512M
CPUQuotaCPU配额80%
安全控制PrivateTmp使用私有/tmp目录(增强安全)true
ProtectSystem文件系统保护级别full、strict

[Service]示例

[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/bin/rm -f /run/nginx.pid
ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf
ExecReload=/bin/kill -s HUP $MAINPID
User=nginx
Group=nginx
Environment="NGINX_LOGLEVEL=info"
Restart=on-failure
RestartSec=5s
MemoryLimit=500M
PrivateTmp=true

常见 Type 类型:

特性Type=simpleType=forking
工作方式主进程直接在前台运行主进程 fork 子进程后退出
systemd 监控对象ExecStart 启动的进程fork 出来的子进程
适用场景现代应用 (Python/Node.js/Go 等)传统守护进程 (Nginx/MySQL 等)
PID 文件不需要必须 通过 PIDFile= 指定
启动完成判定立即标记为 active需等待主进程退出
日志处理自动捕获 stdout/stderr需程序自行处理日志
启动速度快 (直接启动)稍慢 (需完成 fork 过程)
典型应用Flask, Redis, systemd 自身服务Apache, PostgreSQL, Zabbix Server

在这里插入图片描述

判断应该使用哪种类型:

# 手动测试启动程序
/usr/sbin/nginx -c /etc/nginx/nginx.conf# 观察行为:
# 1. 如果命令立即返回且后台有进程 → forking
# 2. 如果命令阻塞在前台 → simple
[Install] 区块 - 开机启动配置

定义服务安装到哪个运行级别(target)

指令说明示例值
WantedBy必填 指定服务关联的 target(实现开机启动)multi-user.target
RequiredBy指定强依赖本服务的 targetgraphical.target
Alias服务别名Alias=webserver.service
Also安装时同时启用的其他服务Also=nginx-sockets.service

[Install] 示例

[Install]
WantedBy=multi-user.target
Alias=web.service

完整示例

[Unit]
Description=My Custom Application   # 服务描述
After=network.target                # 在网络启动后运行[Service]
Type=simple                         # 服务类型(常用 simple 或 forking)
User=appuser                        # 运行服务的用户
Group=appgroup                      # 运行服务的组
WorkingDirectory=/opt/myapp         # 工作目录
ExecStart=/usr/bin/java -jar /opt/myapp/app.jar  # 启动命令(必须绝对路径)
Restart=on-failure                  # 失败时自动重启  
RestartSec=5s                       # 重启间隔
Environment="PORT=8080"             # 设置环境变量
PrivateTmp=true                     # 启用私有临时目录(安全增强)# 日志配置(可选)
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=myapp[Install]
WantedBy=multi-user.target          # 多用户模式下启用

设置权限和路径

# 确保可执行文件有权限
sudo chmod +x /opt/myapp/start.sh
# 环境变量文件(可选)
sudo vi /etc/sysconfig/myapp  # 定义变量 APP_ENV=production

服务文件中引用:

EnvironmentFile=/etc/sysconfig/myapp
ExecStart=/opt/myapp/start.sh ${APP_ENV}

管理服务命令

# 重载 systemd 配置(修改服务文件后必须执行)
sudo systemctl daemon-reload# 启动/停止服务
sudo systemctl start myapp.service
sudo systemctl stop myapp.service# 设置开机自启
sudo systemctl enable myapp.service# 查看状态和日志
systemctl status myapp         # 服务状态
journalctl -u myapp -f         # 实时日志(-f 跟踪日志)
journalctl -u myapp --since "2020-01-01" --until "1 hour ago"  # 时间筛选

启动失败排查

systemctl status myapp      # 查看错误摘要
journalctl -xe              # 检查详细日志
  • 测试启动命令: 手动执行 ExecStart 中的命令,验证路径和权限。
  • 环境变量问题: 使用 systemctl show myapp 检查最终环境变量

注意事项

  • 路径必须为绝对路径(包括脚本和命令)
  • 修改服务文件后必须执行 daemon-reload
  • 生产环境建议用非 root 用户运行(User=)
http://www.lryc.cn/news/620844.html

相关文章:

  • Java 设计模式-装饰器模式
  • 线程P4 | 线程安全问题及解决方法
  • Linux信号产生
  • Linux下使用Samba 客户端访问 Samba 服务器的配置(Ubuntu Debian)
  • mysql 提示符及快捷执行
  • 从零开始搭建React+TypeScript+webpack开发环境——基于MobX的枚举数据缓存方案设计与实践
  • React 数据持久化:从 “刷新就丢“ 到 “永存不灭“ 的实现方案
  • WEBSTORM前端 —— 第4章:JavaScript —— 第3节:数据类型与类型转换
  • Streamlit实现Qwen对话机器人
  • Pytest自动化测试框架总结
  • 2025年机器视觉与信号处理国际会议(MVSP 2025)
  • springboot博客实战笔记02
  • 游戏行业DevOps实践:维塔士集团基于Atlassian工具与龙智服务构建全球化游戏开发协作平台
  • 阿里云RDS SQL Server实例之间数据库迁移方案
  • flstudio.exe安装教程|FL Studio怎么下载安装?超简单中文指南
  • K8S企业级应用与DaemonSet实战解析
  • 深入解析 HTTP 协议演进:从 1.0 到 3.0
  • 怎么判断晶振的好坏,有什么简单的办法
  • .NET 的 WebApi 项目必要可配置项都有哪些?
  • 【论文阅读-Part1】PIKE-RAG: sPecIalized KnowledgE and Rationale Augmented Generation
  • 机器学习算法篇(八)-------svm支持向量机
  • Android数据缓存目录context.getCacheDir与Environment.getExternalStorageDirectory
  • Linux 文件系统简介
  • 【大模型私有化部署】实战部分:Ollama 部署教程
  • 芯片 讲解| DP7272—24位、192kHz立体声音频编解码器
  • 百川开源大模型Baichuan-M2的医疗能力登顶第一?
  • Mybatis Plus 分页插件报错`GOLDILOCKS`
  • week1-[分支结构]中位数
  • imx6ull-驱动开发篇24——Linux 中断API函数
  • Docker 入门与实战:从环境搭建到项目部署