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