对于Linux用户而言,systemctl
想必并不陌生。在管理服务时,它堪称首选命令,启动、停止服务或是查看服务状态,都不在话下。然而,实话实说,倘若仅使用这些基础功能,那不过是触及了systemctl
的冰山一角。不妨将systemctl
比作一部智能手机,你若仅用它来打电话,便会错过其蕴藏的诸多强大功能。
在本文中,我们将深入探索,解锁高级技术与工具,大幅提升你的服务管理技能,这些技术远超基础操作范畴。准备好开启升级之旅了吗?让我们即刻出发!
一、systemd概述
Systemd是Linux系统中最新一代的初始化系统(init)。其核心设计目标在于克服sysvinit与生俱来的缺陷,显著提升系统启动速度,为系统启动与管理构建一套完备的解决方案。依照Linux的惯例,字母d是守护进程(daemon)的缩写。Systemd这一命名,寓意着它将守护整个系统。
采用Systemd后,便无需再使用init。Systemd取代了initd,成为系统的首个进程(进程ID为1),其他进程皆为其子进程。我们可通过以下命令查看Systemd的版本:
# systemctl --version
systemd 219
+PAM +AUDIT +SELINUX +IMA -APPARMOR +SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ -LZ4 -SECCOMP +BLKID +ELFUTILS +KMOD +IDN
Systemd的优势在于功能极为强大,使用便捷;缺点则是体系庞大复杂。实际上,至今仍有不少人反对使用systemd,原因就在于其过度复杂,与操作系统的其他部分紧密耦合,背离了“保持简单,保持愚蠢”的http://www.ruanyifeng.com/blog/2009/06/unix_philosophy.html。
二、systemctl命令简介
systemctl
作为Systemd的核心命令,肩负着管理系统的重任。从功能层面来看,systemctl
整合了service
与chkconfig
这两个命令的功能:
任务 | 旧指令 | 新指令 |
---|---|---|
使某任务自动启动 | chkconfig--level 3 httpd on |
systemctl enable httpd.service |
使某服务不自动启动 | chkconfig--level 3 httpd off |
systemctl disable httpd.service |
检查服务状态 | service httpd status | systemctl status httpd.service(服务详细信息) systemctl is - active httpd.service(仅显示是否Active) |
显示所有已启动服务 | chkconfig--list |
systemctl list - units--type=service |
启动某服务 | service httpd start | systemctl start httpd.service |
停止某服务 | service httpd stop | systemctl stop httpd.service |
重启某服务 | service httpd restart | systemctl restart httpd.service |
三、systemctl 常用命令
查看服务状态:
systemctl status <service>
:显示指定服务的运行状态、日志信息和依赖关系。systemctl is-active <service>
:检查指定服务是否处于激活状态(运行中)。systemctl is-enabled <service>
:检查指定服务是否已启用(将在系统引导时自动启动)。systemctl is-failed <service>
:检查指定服务是否处于失败状态。
管理服务:
systemctl start <service>
:启动指定服务。systemctl stop <service>
:停止指定服务。systemctl restart <service>
:重新启动指定服务。systemctl reload <service>
:重新加载指定服务的配置文件。systemctl enable <service>
:启用指定服务,使其在系统引导时自动启动。systemctl disable <service>
:禁用指定服务,使其不会在系统引导时启动。
管理服务单元:
systemctl list-units
:列出所有已知的服务单元并显示其当前状态。systemctl list-unit-files
:列出所有已安装的服务单元文件。systemctl show <unit>
:显示指定服务单元的详细信息。
系统操作:
systemctl poweroff
:关闭系统。systemctl reboot
:重启系统。systemctl suspend
:将系统置于挂起状态(睡眠模式)。systemctl hibernate
:将系统置于休眠状态(保存当前状态到磁盘)。
日志查询:
systemctl status <service/unit>.service
:显示服务或单元的当前状态和日志。journalctl -u <service/unit>.service
:查看指定服务或单元的日志。
四、为何仅依赖systemctl
远远不够
首先需要明确,systemctl
无疑是一款极为强大的工具。对于简单任务而言,它表现得游刃有余。然而,倘若你仅仅利用它来启动和停止服务,那么你将错失systemd潜藏的全部巨大潜能。下面为你揭示那些被忽略的关键方面:
- 可见性受限:
systemctl status
能够提供某个瞬间的状态快照,但当你需要实时更新信息或者查阅历史日志时,它便显得力不从心了。 - 日志功能基础:虽然
journalctl
能够提供帮助,但其操作较为复杂。例如,如何依据时间、服务类别或者错误类型对日志进行精准过滤呢? - 手动操作负担重:怎样实现任务自动化,或者在无需人工干预的情况下妥善处理服务故障呢?
接下来,让我们借助高级技术,将你的服务管理水平提升到全新高度,使你宛如一位Linux高手。
1. 借助journalctl
精通日志管理
若你仅仅依靠systemctl status <service>
来排查问题,那么你便遗漏了一个极为强大的工具——journalctl
。该命令能够为你呈现来自systemd
日志的详尽记录,其中存储着所有系统和服务的日志信息。journalctl
堪称systemctl
的最佳搭档,它为你打开了系统日志的大门,然而大多数人并未充分挖掘其价值。
- 它允许你按照服务、时间或者日志严重程度对日志进行筛选,从而让你在故障排查过程中拥有更强的掌控力。
- 它有助于你探寻服务失败的根本原因,不仅能够展示服务自身的输出,还能呈现依赖项或者相关服务的日志。
按服务过滤日志
倘若你期望查看特定服务的日志,可使用以下命令:
sudo journalctl -u <service - name>
实时日志跟踪
通过添加-f
标志,你能够实时跟踪日志:
sudo journalctl -u <service - name> -f
按时间范围过滤
想要查看过去一小时的日志、特定日期范围内的日志,亦或是仅查看最近的日志?方法如下:
sudo journalctl --since "1 hour ago"
sudo journalctl --since "2023 - 10 - 01" --until "2023 - 10 - 02"
导出日志用于分析
你还可以将日志导出至文件,以便进行离线分析:
sudo journalctl -u <service - name> > service - logs.txt
2. 深度挖掘systemctl
的潜能
在深入探讨其他工具之前,我们先来确保你充分发挥systemctl
的作用。这里有一些你可能尚未知晓的隐藏功能:
列出所有服务
你能够列出系统中的所有服务,包括已禁用或静态的服务,命令如下:
systemctl list-units --type=service --all
检查服务依赖项
若想了解哪些其他服务依赖于特定服务,可尝试此命令:
systemctl list-dependencies <service-name>
屏蔽服务
要阻止服务启动,无论是手动启动还是自动启动,使用以下命令:
sudo systemctl mask <service-name>
模拟服务重启
若想了解重启服务时的情况,却又不想实际执行,可使用该命令:
sudo systemctl restart --dry-run <service-name>
journalctl功能强大,用法非常多:
# 查看所有日志(默认情况下,只保存本次启动的日志)
sudo journalctl
# 查看内核日志(不显示应用日志)
sudo journalctl -k
# 查看系统本次启动日志
sudo journalctl -b
sudo journalctl -b -0
# 查看上一次启动的日志(需要更改设置)
sudo journalctl -b -1
# 查看指定时间的日志
sudo journalctl --since="2012-10-30 18:17:16"
sudo journalctl --since "20 min ago"
sudo journalctl --since yesterday
sudo journalctl --since "2015-01-01" --until "2015-01-11 03:00"
sudo journalctl --since 09:00 --until "1 hour ago"
# 显示尾部的最新10行日志
sudo journalctl -n
# 显示尾部指定行数的日志
sudo journalctl -n 20
# 实时滚动显示最新日志
sudo journalctl -f
# 查看指定服务的日志
sudo journalctl /usr/lib/systemd/systemd
# 查看指定进程的日志
sudo journalctl _PID=1
# 查看某个路径的脚本的日志
sudo journalctl /usr/bin/bash
# 查看指定用户的日志
sudo journalctl _UID=33 --since today
# 查看某个Unit的日志
sudo journalctl -u nginx.service
sudo journalctl -u nginx.service --since today
# 实时滚动显示某个Unit的最新日志信息
sudo journalctl -u nginx.service -f
# 合并显示多个unit的日志
sudo journalctl -u nginx.service -u php-fpm.service --since today
# 查看指定优先级(及其以上级别)的日志,共有8级
# 0: emerg
# 1: alert
# 2: crit
# 3: err
# 4: warning
# 5: notice
# 6: info
# 7: debug
sudo journalctl -p err -b
# 日志默认分页输出, --no-pager 改为正常标准输出
sudo journalctl --no-pager
# 以Json格式(当行)输出
sudo journalctl -b -u nginx.service -o json
# 以Json格式(多行)输出,可读性更好
sudo journalctl -b -u nginx.service -o json-pretty
# 显示日志占据的硬盘空间
sudo journalctl --disk-usage
#指定日志文件占据的最大空间
sudo journalctl --vacuum-size=1G
# 指定日志文件保存多久
sudo journalctl --vacuum-time=1years
注: 默认情况下,Systemd将日志保存在
/run/log/journal
中,系统重启就会清除。通过新建/var/log/journal
目录,日志会自动记录到这个目录中,并永久存储。
五、处理Unit配置文件
每个服务都有对应的Unit文件,它定义了服务的运行方式。这些文件存储位置因来源不同而异:系统提供的单元文件存于/lib/systemd/system/
,用户提供的则存于/etc/systemd/system/
。
若要列出所有已安装的Unit文件,可使用:
systemctl list-unit-files --type=service
这会显示每个Unit的状态,如启用、禁用、静态等。
查看Unit文件详细信息
若想查看Unit文件的详细内容,运行:
systemctl cat <service-name>
要检查服务的依赖项,使用:
systemctl list-dependencies <service-name>
若想编辑Unit文件,可运行以下命令:
sudo systemctl edit <service-name>
这会创建一个覆盖文件,你可在其中调整单个设置,而无需修改原始单元文件。
创建自己的Unit文件
每一个Unit都有一个配置文件,告诉Systemd怎么启动这个Unit。Systemd
默认从 /etc/systemd/system/
目录读取配置文件。但是,里面存放的大部分文件都是符号链接,指向目录 /usr/lib/systemd/system/
目录下的文件,因此真正的文件存放在那个目录下。
systemctl enable
命令用于在上面两个目录之间建立符号链接关系:
# sudo systemctl enable [email protected]
//等价于
# sudo ln -s /usr/lib/systemd/system/[email protected] /etc/systemd/system/[email protected]
如果配置文件里面设置了开机启动,systemctl enable
就相当于激活开机启动。与之对应的,systemctl disable
命令用于在两个目录之间撤销符号链接关系,相当于撤销开机启动:
# sudo systemctl disable [email protected]
配置文件名称的后缀,就是该 Unit
的种类,比如 sshd.socket
。如果省略,Systemd默认后缀名为 .service
。所以 sshd
会被理解成 sshd.service
。
配置文件的状态
systemctl list-unit-files
命令用于列出所有配置文件:
//列出所有配置文件
# systemctl list-unit-files
UNIT FILE STATE
proc-sys-fs-binfmt_misc.automount static
dev-hugepages.mount static
dev-mqueue.mount static
proc-fs-nfsd.mount static
proc-sys-fs-binfmt_misc.mount static
sys-fs-fuse-connections.mount static
sys-kernel-config.mount static
sys-kernel-debug.mount static
tmp.mount disabled
var-lib-nfs-rpc_pipefs.mount static
brandbot.path disabled
cups.path enabled
//列出指定类型的配置文件
# systemctl list-unit-files --type=service
配置文件的状态有4种:
enabled: 已建立启动链接
disabled: 没建立启动链接
static: 该配置文件没有[Install]部分(无法执行),只能作为其他配置文件的依赖
masked: 该配置文件被禁止建立启动链接
注意,从配置文件的状态无法看出,该Unit是否正在运行。这必须执行前面提到的 systemctl status
命令。
# systemctl status bluetooth.service
一旦修改配置文件,就要让 Systemd
重新加载配置文件,然后重新启动,否则修改不会生效。
# sudo systemctl daemon reload
# sudo systemctl restart httpd.service
配置文件的格式
配置文件就是普通的文本文件,可以用文本编辑器打开。systemctl cat
命令可以查看配置文件的内容:
[root@bogon ~]# systemctl cat mysqld
# /usr/lib/systemd/system/mysqld.service
# Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# systemd service file for MySQL forking server
#
[Unit]
Description=MySQL Server
Documentation=man:mysqld(8)
Documentation=http://dev.mysql.com/doc/refman/en/using-systemd.html
After=network.target
After=syslog.target
[Install]
WantedBy=multi-user.target
[Service]
User=mysql
Group=mysql
Type=forking
PIDFile=/var/run/mysqld/mysqld.pid
# Disable service start and stop timeout logic of systemd for mysqld service.
TimeoutSec=0
# Execute pre and post scripts as root
PermissionsStartOnly=true
# Needed to create system tables
ExecStartPre=/usr/bin/mysqld_pre_systemd
# Start main service
ExecStart=/usr/sbin/mysqld --daemonize --pid-file=/var/run/mysqld/mysqld.pid $MYSQLD_OPTS
# Use this to switch malloc implementation
EnvironmentFile=-/etc/sysconfig/mysql
# Sets open_files_limit
LimitNOFILE = 5000
Restart=on-failure
RestartPreventExitStatus=1
PrivateTmp=false
从上面的输出可以看到,配置文件分成几个区块。每个区块的第一行,使用方括号表示的区的名称,比如 [Unit]
。注意,配置文件的区块名和字段名都是 大小写敏感
的。
每个区块内部是一些符号连接的键值对:
[Section]
Directive1=value
Directive2=value
...
注意: 键值对的等号两侧不能有空格。
配置文件的区块
1) Unit区块
[Unit]
区块通常是配置文件的第一个区块,用来定义Unit的元数据,以及配置与 其他Unit
的关系。它的主要字段如下:
Description: 简短描述
Documentation: 文档地址
Requires: 当前Unit依赖的其他Unit,如果它们没有运行,当前Unit会启动失败
Wants: 与当前Unit配合的其他Unit,如果它们没有运行, 当前Unit不会启动失败
BindsTo: 与Requires类似,它指定的Unit如果退出,会导致当前Unit停止运行
Before: 如果该字段指定的Unit也要启动,那么必须在当前Unit之后启动
After: 如果该字段指定的Unit也要启动,那么必须在当前Unit之前启动
Conflicts: 这里指定的Unit不能与当前Unit同时运行
Condition...: 当前Unit运行必须满足的条件,否则不会运行
Assert...: 当前Unit运行必须满足的条件,否则会报启动失败
2) Install区块
[Install]
区块用来定义如何启动,以及是否开机启动。它的主要字段如下:
WantedBy: 它的值是一个或多个Target,当前Unit激活时(enable)符号链接会放入/etc/systemd/system目录下面以
Target名 + .wants后缀构成的子目录中
RequiredBy: 它的值是一个或多个Target,当前Unit激活时(enable)符号链接会放入/etc/systemd/system目录下面以
Target名 + .required后缀构成的子目录中
Alias: 当前Unit可用于启动的别名
Also: 当前Unit激活时(enable),会被同时激活的其他Unit
3) Service区块
[Service]
区块用来Service的配置,只有service类型的unit才有本区块。它的主要字段如下:
Type: 定义启动时的进程行为。它有以下几种值:
1) Type=simple 默认值,执行ExecStart指定的命令,启动主进程
2) Type=forking 以fork方式从父进程创建子进程,创建后父进程会立即退出
3) Type=oneshot 一次性进程,Systemd会等待当前服务退出,再继续往下执行
4) Type=dbus 当前服务通过DBus启动
5) Type=notify 当前服务启动完毕,会通知Systemd,再继续往下执行
6) Type=idle 若有其他任务执行完毕,当前服务才会运行
ExecStart: 启动当前服务的命令
ExecStartPre: 启动当前服务之前执行的命令
ExecStartPost: 启动当前服务之后执行的命令
ExecReload: 重启当前服务执行时的命令
ExecStop: 停止当前服务时执行的命令
ExecStopPost: 停止当前服务之后执行的命令
RestartSec: 自动重启当前服务间隔的秒数
Restart: 定义何种情况下会自动重启当前服务,可能的值包括always(总是重启)、on-success、on-failure、on-abnormal、on-abort、on-watchdog
TimeoutSec: 定义Systemd停止当前服务之前等待的秒数
Environment: 指定环境变量
Unit配置文件的完整清单,请参看官方文档
六、Target 用法
计算机启动时,需要启动大量的Unit。倘若每次启动都要逐个写明本次启动所需的Unit,显然极为不便。Systemd给出的解决方案是Target。简单来讲,Target就是一个Unit组,囊括了众多相关Unit。当启动某个Target时,Systemd便会启动其中的所有Unit。从这个层面而言,Target的概念类似于“状态点”,启动某个Target就如同启动到某种特定状态。
在传统的init
启动模式中,存在RunLevel
的概念,其作用与Target颇为相似。不同之处在于,RunLevel具有互斥性,多个RunLevel不可能同时启动,而多个Target却能够同时启动。
//查看当前系统的所有Target
# systemctl list-unit-files --type=target
//查看一个target所包含的所有Unit
# systemctl list-dependencies multi-user.target
//查看启动时的默认target
# systemctl get-default
//设置启动时的默认target
# systemctl set-default multi-user.target
//切换target时,默认不关闭前一个Target启动的进程。systemctl isolate命令改变这种行为,
//关闭前一个Target里面所有不属于后一个Target的进程
# sudo systemctl isolate multi-user.target
Target与传统RunLevel存在如下对应关系:
Traditional runlevel New target name Symbolically linked to...
Runlevel 0 | runlevel0.target -> poweroff.target
Runlevel 1 | runlevel1.target -> rescue.target
Runlevel 2 | runlevel2.target -> multi-user.target
Runlevel 3 | runlevel3.target -> multi-user.target
Runlevel 4 | runlevel4.target -> multi-user.target
Runlevel 5 | runlevel5.target -> graphical.target
Runlevel 6 | runlevel6.target -> reboot.target
它与init
进程主要存在以下差别:
- 默认的RunLevel(在/etc/inittab文件中设置)如今已被默认的Target所取代,其位置为/etc/systemd/system/default.target,通常符号链接到
graphical.target
(图形界面)或者multi-user.target(多用户命令行)。 - 启动脚本的位置:以往是/etc/init.d目录,符号链接到不同的RunLevel目录(例如/etc/rc3.d、/etc/rc5.d等),现在则存放在/lib/systemd/system和/etc/systemd/system目录。
- 配置文件的位置:以前init进程的配置文件是/etc/inittab,各类服务的配置文件存放在/etc/sysconfig目录。如今的配置文件主要存放在/lib/systemd目录,在/etc/systemd目录中的修改能够覆盖原始设置。
七、使用 systemd-analyze 加速启动时间
若系统启动缓慢,systemd-analyze
是识别瓶颈、加快启动速度的绝佳工具。该命令能让你了解启动时间、服务启动性能以及可能拖慢系统的关键路径。
主要功能:
systemd-analyze blame
:显示每个服务在启动期间花费的时间。这对于识别可能延迟系统启动的慢速服务非常有用。systemd-analyze blame
systemd-analyze critical-chain
:提供启动过程中涉及的服务的可视化分解及其依赖关系,帮助你查看是什么拖慢了系统。systemd-analyze critical-chain
想要启动过程的可视化表示?使用:
systemd-analyze plot > boot-graph.svg
八、排查常见服务问题
有时,事情会出错,服务无法启动。
以下是排查方法:
服务无法重新加载
修改单元文件后, 始终重新加载 systemd 配置,然后再重启服务:
sudo systemctl daemon-reload
sudo systemctl restart <service-name>
未能重新加载 systemd 管理器可能导致更改未应用。
要 列出并检查失败的单元,请使用:
systemctl --failed
该命令帮助你快速识别失败的服务。然后你可以使用 journalctl -u <service-name>
检查它们的日志。
权限问题
以非 root 权限运行的服务可能无法访问某些资源。
始终确保你的服务文件和脚本具有正确的权限。
例如,如果你的服务需要访问 /var/log/myapp
,请确保服务用户对该目录具有读/写权限:
sudo chown myuser:mygroup /var/log/myapp
环境变量
某些服务依赖于可能未正确设置的 环境变量。
始终检查你运行的服务的文档,并确保所有必要的环境变量都在单元文件的 [Service]
部分中定义:
[Service]
Environment="MY_VAR=value"
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件举报,一经查实,本站将立刻删除。
文章由技术书栈整理,本文链接:https://study.disign.me/article/202511/11.linux-commands-systemctl.md
发布时间: 2025-03-12