systemctl服务文件管理指南

systemctl命令概述

systemctl是 Linux 系统中用于管理系统服务的命令,是systemd初始化系统的一部分。它可以用于启动、停止、重启和重新加载服务,查看服务状态以及设置默认启动级别等等,但是如果要使用systemctl命令管理系统服务,前提是为服务创建一个systemctl服务文件。

使用yum/apt下载的服务,默认会生成一个服务管理文件,但是我们通过二进制编译安装的文件则无法通过systemctl进行服务管理,这时,我们需要手动创建一个服务管理文件用来管理该服务。

Linux系统下的软件安装可以阅读这篇文章:Linux系统中的软件管理

systemctl命令

语法:

systemctl [选项] [命令] [服务名称]

常用命令

  • systemctl --help:查看帮助手册
  • systemctl start <服务名>:启动指定的服务
  • systemctl stop <服务名>:停止指定的服务
  • systemctl restart <服务名>:重启指定的服务
  • systemctl status <服务名>:查看指定服务的状态
  • systemctl enable <服务名>:设置开机自启动指定的服务
  • systemctl disable <服务名>:取消某个服务的开机自启动
  • systemctl reload <服务名>:在不重启服务的情况下,重新加载其配置文件。
  • systemctl mask <服务名>:注销服务,会阻止服务启动,即使使用start命令也无法启动,常用于防止某些服务被意外启动。
  • systemctl unmask <服务名>:取消对服务的注销状态。
  • systemctl list-units:查看当前系统通过systemctl管理的已启动的服务
  • systemctl list-unit -files:查看当前系统通过systemctl管理的所有的服务
  • systemctl list-dependencies <服务名>:查看指定服务依赖哪些其他服务
  • systemctl list-dependencies --reverse <服务名>:向查看哪些服务依赖于指定服务。
  • journalctl -u <服务名>:查看指定服务的日志
  • systemctl daemon-reload:当服务配置文件有变更(新增、修改)时,需要先执行该命令加载服务配置文件

服务文件概述

在 Linux 系统中,systemd 服务文件(.service 文件)是用于定义和管理系统服务的核心配置文件。它们控制服务的启动、停止、依赖关系、运行环境等行为,是 systemd 初始化系统实现服务管理的基础。

服务文件所在路径

  • /etc/systemd/system/:用户自定义配置文件存放的目录,加载时优先加载该目录下的
  • /lib/systemd/system/:软件包安装的默认配置
  • /run/systemd/system/:运行时动态生成的配置

查看yum/apt下载时生成的服务文件

以docker举例

安装docker参考这篇文章:Docker安装

[root@master ~]# cat /etc/systemd/system/docker.service 
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network.target

[Service]
Type=notify
# the default is not to use systemd for cgroups because the delegate issues still
# exists and systemd currently does not support the cgroup feature set required
# for containers run by docker
ExecStart=/usr/bin/dockerd
ExecReload=/bin/kill -s HUP $MAINPID
# Having non-zero Limit*s causes performance problems due to accounting overhead
# in the kernel. We recommend using cgroups to do container-local accounting.
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
# Uncomment TasksMax if your systemd version supports it.
# Only systemd 226 and above support this version.
#TasksMax=infinity
TimeoutStartSec=0
# set delegate yes so that systemd does not reset the cgroups of docker containers
Delegate=yes
# kill only the docker process, not all processes in the cgroup
KillMode=process

[Install]
WantedBy=multi-user.target

通过该文件可以发现服务配置文件主要分为三个部分,分别是[Unit]、[Service]、[Install]
下面我们会详细说一下这三个部分的作用

服务配置文件的结构

服务配置文件主要分为三个部分,分别是[Unit]、[Service]、[Install]

Unit部分

[Unit]:主要用来定义服务的元数据、描述信息和依赖关系。

其常用主要的配置有下面几个:

  • Description:服务的简短描述
  • Documentation:服务文档的 URL 或路径
  • After:指定服务启动的顺序(在哪些服务之后启动)
  • Before:指定服务启动的顺序(在哪些服务之前启动)

示例配置:这是一个尽可能全面的配置

[Unit]
# --- 基础元信息 ---
Description=Advanced Example Service       # 服务描述(必填)
Documentation=man:example(1)               # 文档链接(支持多个,用空格分隔)
Documentation=https://example.com/docs     # 可指定多种类型(man/http/file等)

# --- 依赖关系控制 ---
# 强依赖:依赖服务失败则本服务不启动
Requires=postgresql.service redis.service
# 弱依赖:依赖服务失败不影响本服务启动
Wants=nginx.service
# 绑定依赖:依赖服务停止时,本服务也停止
BindsTo=essential-dependency.service
# 服务组:当本服务停止时,关联服务也会停止
PartOf=service-group.target

# --- 启动顺序 ---
# 确保在 network.target 和 postgresql.service 之后启动
After=network.target postgresql.service
# 确保在 graphical.target 之前启动
Before=graphical.target

# --- 冲突管理 ---
# 禁止与旧版本服务同时运行
Conflicts=legacy-service.service

# --- 失败联动 ---
# 若本服务失败,触发另一个服务启动
OnFailure=fallback-service.service

# --- 条件检查 ---
# 仅当文件存在时才启动
ConditionPathExists=/etc/example/config.conf
# 检查目录是否为空(若目录不存在,条件失败)
ConditionDirectoryNotEmpty=/var/lib/example/data
# 检查系统是否满足最低要求(如内核版本)
ConditionKernelVersion>=4.15

# --- 高级依赖 ---
# 共享命名空间(常用于容器间通信)
JoinsNamespaceOf=container-service.service
# 重载信号传递
PropagatesReloadTo=reload-dependent.service
ReloadPropagatedFrom=parent-service.service

# --- 资源关联 ---
# 限制仅在特定 CPU 上运行(需 systemd 247+)
AllowedCPUs=0,2
# 限制内存节点(NUMA 架构)
AllowedMemoryNodes=0-1

# --- 其他 ---
# 允许的服务退出状态码(默认0为成功)
SuccessExitStatus=0 255
# 启动超时(默认无限制)
StartLimitIntervalSec=30s
StartLimitBurst=5

Service部分

[Service]:主要用来定义服务的具体行为,如启动方式、启动命令、重启策略、运行环境等。

其常用的主要配置有以下几个

  • Type:服务类型,常见值有:
    • simple(默认):ExecStart 直接启动主进程
    • forking:后台守护进程(如 Apache),需通过 PIDFile 指定 PID 文件
    • oneshot:一次性任务(如系统初始化脚本)
    • notify:通过 sd_notify() 通知 systemd 启动完成
    • dbus:通过 D-Bus 接口启动完成通知
  • ExecStart:启动服务的命令
  • ExecStop:停止服务的命令
  • ExecReload:重载配置的命令
  • Restart:重启策略,如 always、on-failure、on-abort 等
  • RestartSec:重启前的等待时间(秒)
  • TimeoutStartSec:启动超时时间
  • Environment:设置环境变量,如 Environment="FOO=bar"
  • WorkingDirectory:设置工作目录
  • User/Group:指定服务运行的用户和组
  • LimitNOFILE/LimitNPROC:设置文件描述符和进程数限制

Service示例配置:这是一个尽可能全面的配置

[Service]
# ==== 基础运行配置 ====
Type=forking                     # 服务类型: forking/simple/oneshot/notify...
ExecStart=/usr/local/bin/myapp start  # 启动命令(必须用绝对路径)
ExecStop=/usr/local/bin/myapp stop    # 停止命令(可选)
ExecReload=/usr/local/bin/myapp reload # 重载命令(支持自定义信号)
Restart=on-failure              # 重启策略: no/always/on-success/on-abort...
RestartSec=5s                   # 重启前等待时间(默认100ms)
TimeoutStartSec=30s             # 启动超时时间(默认无限制)
TimeoutStopSec=15s              # 停止超时时间
RemainAfterExit=yes             # 进程退出后仍标记为 active(适用于 oneshot)

# ==== 权限控制 ====
User=appuser                    # 运行用户(必须存在)
Group=appgroup                  # 运行组
UMask=0027                      # 文件权限掩码
CapabilityBoundingSet=CAP_NET_BIND_SERVICE # 允许的 Linux 能力
NoNewPrivileges=yes             # 禁止进程提升权限

# ==== 环境配置 ====
Environment="NODE_ENV=production"   # 直接设置环境变量
EnvironmentFile=/etc/myapp/env.conf # 从文件加载环境变量
WorkingDirectory=/var/lib/myapp     # 工作目录(必须存在)
StandardOutput=syslog            # 标准输出目标: syslog/journal/file...
StandardError=inherit            # 错误输出继承自标准输出
SyslogIdentifier=myapp           # 自定义 syslog 标识符

# ==== 资源限制 ====
LimitCPU=10min                   # CPU 时间限制(格式: 秒/min/hour)
LimitNOFILE=65536                # 最大文件描述符数
LimitMEMLOCK=64M                 # 最大锁定内存
MemoryMax=2G                     # 最大内存用量(OOM 触发限制)
CPUQuota=150%                    # CPU 配额(CGroup 控制)

# ==== 进程特性 ====
Nice=-10                         # 进程优先级(-20 最高,19 最低)
IOSchedulingClass=realtime       # I/O 调度类(realtime/best-effort/idle)
CPUSchedulingPolicy=rr           # CPU 调度策略(rr/fifo/batch)
CPUSchedulingPriority=90         # 调度优先级(1-99,仅实时策略)

# ==== 安全沙箱 ====
ProtectSystem=full               # 禁止写入系统目录
ProtectHome=tmpfs                # 隔离 /home /root /run/user
PrivateTmp=yes                   # 使用私有 /tmp 和 /var/tmp
PrivateDevices=yes               # 无法访问物理设备(如 /dev/sda)
ProtectKernelTunables=yes        # 禁止修改内核参数
ProtectControlGroups=yes         # 禁止修改 CGroup 配置
RestrictAddressFamilies=AF_INET AF_UNIX # 允许的 socket 协议簇
RestrictNamespaces=yes           # 禁止创建新命名空间
LockPersonality=yes              # 禁止切换进程 personality

# ==== 信号处理 ====
KillMode=mixed                   # 停止模式: process/control-group/mixed...
KillSignal=SIGTERM               # 首选终止信号
SendSIGHUP=yes                   # 是否发送 SIGHUP 到进程组
FinalKillSignal=SIGKILL          # 最终强制终止信号
WatchdogSec=30s                  # 看门狗检测间隔(需服务定期 ping)

# ==== 高级特性 ====
NotifyAccess=all                 # 支持 sd_notify 状态通知(配合 Type=notify)
ExecStartPre=/path/to/pre-script # 启动前脚本
ExecStartPost=/path/to/post-script # 启动后脚本
Slice=myapp.slice                # 关联自定义 CGroup slice
Delegate=yes                     # 允许服务管理子 CGroup
OOMPolicy=kill                   # OOM 处理策略(continue/stop/kill)

Install部分

[Install]:主要是用来定义服务的安装信息,如何在系统启动时启用

其常用的配置主要有以下几个:

  • WantedBy:指定服务在哪些目标(Target)下启用,常见值为 multi-user.target(多用户模式)
  • RequiredBy:强依赖关系,类似 Requires 的反向设置
  • Alias:服务的别名,可通过别名启动服务

示例配置:尽可能全面的配置

[Install]
# ===== 基础安装配置 =====
WantedBy=multi-user.target          # 关联到标准多用户目标(开机自启)
RequiredBy=critical-services.target # 强依赖目标(必须随该目标启动)
Also=myapp-socket.service           # 关联的其他单元(同时启停)
Alias=legacy-app.service            # 服务别名(兼容旧名称)

# ===== 多实例服务 =====
DefaultInstance=http               # 默认实例名称(用于模板单元)
WantedBy=app-instances.target       # 多实例关联目标

# ===== 反向依赖控制 =====
WantedBy=postgresql.service         # 反向声明:当 postgresql 启用时自动启用本服务
RequiredBy=nginx.service            # 反向强依赖(不推荐,易导致循环)

# ===== 高级生命周期 =====
StopWhenUnneeded=yes                # 当无其他依赖时自动停止(需配合 RefuseManualStart)
RefuseManualStart=no                # 是否允许手动启动(默认 no)
RefuseManualStop=no                 # 是否允许手动停止(默认 no)

# ===== 触发式安装 =====
Upholds=myapp-monitor.timer         # 当 timer 激活时自动维护本服务状态

编写第一个systemd文件

安装tomcat

tomcat安装参考这篇文章:tomcat使用

编写systemd文件

[root@master ~]# cat /etc/systemd/system/tomcat.service 
[Unit]
Description=Tomcat Service
Documentation=https://www.cnblogs.com/huangSir-devops/p/18808870
After=syslog.target network.target

[Service]
Type=forking
# jdk安装的位置
Environment=JAVA_HOME=/root/jdk
Environment=CATALINA_PID=/opt/tomcat/temp/tomcat.pid
# tomcat安装的位置
Environment=CATALINA_HOME=/root/tomcat
Environment=CATALINA_BASE=/root/tomcat
Environment='CATALINA_OPTS=-Xms512M -Xmx1024M -server -XX:+UseParallelGC'

# 启动命令
ExecStart=/root/tomcat/bin/startup.sh
# 停止命令
ExecStop=/root/tomcat/bin/shutdown.sh -wait 30

User=root
Group=root
UMask=0007
RestartSec=10
Restart=always

[Install]
WantedBy=multi-user.target

验证启动Tomcat

创建pid文件目录

[root@master ~]# mkdir -p /opt/tomcat/temp/

重新加载systemd文件

[root@master ~]# systemctl daemon-reload

启动Tomcat

[root@master ~]# systemctl start tomcat

检查启动状态,发现处于running状态

[root@master ~]# systemctl status tomcat.service 
● tomcat.service - Tomcat Service
     Loaded: loaded (/etc/systemd/system/tomcat.service; disabled; preset: enabled)
     Active: active (running) since Wed 2025-05-28 14:53:51 CST; 3min 18s ago
       Docs: https://www.cnblogs.com/huangSir-devops/p/18808870
    Process: 3561014 ExecStart=/root/tomcat/bin/startup.sh (code=exited, status=0/SUCCESS)
   Main PID: 3561021 (java)
      Tasks: 63 (limit: 76938)
     Memory: 150.3M
     CGroup: /system.slice/tomcat.service
             └─3561021 /root/jdk/bin/java -Djava.util.logging.config.file=/root/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManage>

May 28 14:53:51 master systemd[1]: Starting tomcat.service - Tomcat Service...

检查端口是否启动成功

# 检查端口
[root@master ~]# ss -lntup | grep 8080
tcp   LISTEN 0      100                                 *:8080             *:*    users:(("java",pid=3561021,fd=55))

# 检查进程
[root@master ~]# ps -ef | grep java
root     3561021       1  1 14:53 ?        00:00:03 /root/jdk/bin/java -Djava.util.logging.config.file=/root/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dorg.apache.catalina.security.SecurityListener.UMASK=0027 -Xms512M -Xmx1024M -server -XX:+UseParallelGC -Dignore.endorsed.dirs= -classpath /root/tomcat/bin/bootstrap.jar:/root/tomcat/bin/tomcat-juli.jar -Dcatalina.base=/root/tomcat -Dcatalina.home=/root/tomcat -Djava.io.tmpdir=/root/tomcat/temp org.apache.catalina.startup.Bootstrap start
root     3565153 2589339  0 14:58 pts/0    00:00:00 grep java

验证停止和重启

验证重启

[root@master ~]# systemctl restart tomcat
[root@master ~]# systemctl status tomcat
● tomcat.service - Tomcat Service
     Loaded: loaded (/etc/systemd/system/tomcat.service; disabled; preset: enabled)
     Active: active (running) since Wed 2025-05-28 15:04:06 CST; 3s ago
       Docs: https://www.cnblogs.com/huangSir-devops/p/18808870
    Process: 3570268 ExecStart=/root/tomcat/bin/startup.sh (code=exited, status=0/SUCCESS)
   Main PID: 3570275 (java)
      Tasks: 63 (limit: 76938)
     Memory: 157.0M
     CGroup: /system.slice/tomcat.service
             └─3570275 /root/jdk/bin/java -Djava.util.logging.config.file=/root/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManage>

验证停止

[root@master ~]# systemctl stop tomcat
[root@master ~]# systemctl status tomcat
○ tomcat.service - Tomcat Service
     Loaded: loaded (/etc/systemd/system/tomcat.service; disabled; preset: enabled)
     Active: inactive (dead)
       Docs: https://www.cnblogs.com/huangSir-devops/p/18808870

May 28 15:04:06 master systemd[1]: tomcat.service: Deactivated successfully.
May 28 15:04:06 master systemd[1]: Stopped tomcat.service - Tomcat Service.
May 28 15:04:06 master systemd[1]: Starting tomcat.service - Tomcat Service...
May 28 15:04:06 master startup.sh[3570268]: Tomcat started.
May 28 15:04:06 master systemd[1]: Started tomcat.service - Tomcat Service.
May 28 15:04:40 master systemd[1]: Stopping tomcat.service - Tomcat Service...
May 28 15:04:40 master shutdown.sh[3570785]: usage: java org.apache.catalina.startup.Catalina [ -config {pathname} ] [ -nonaming ] [ -generateCode [ {pathname} ] ] [ -useGener>
May 28 15:04:41 master shutdown.sh[3570776]: Tomcat stopped.
May 28 15:04:41 master systemd[1]: tomcat.service: Deactivated successfully.
May 28 15:04:41 master systemd[1]: Stopped tomcat.service - Tomcat Service.
原创作者: huangSir-devops 转载于: https://www.cnblogs.com/huangSir-devops/p/18899281
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值