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使用](https://www.cnblogs.com/huangSir-devops/p/18808870#_label1 "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.