在第一章中,我们讨论了故障排除最佳实践和所涉及的高级流程。 第一章是关于故障排除的概述,本章开始深入讨论具体问题。
本章将回顾常见的故障诊断命令以及常见的地方,以找到有用的信息。 在本书中,我们将使用 Red Hat Enterprise Linux(也称为 RHEL)的第 7 版。 本章中引用的所有命令都是 RHEL 7 默认安装中包含的命令。
我们将引用默认安装的命令,因为我曾经遇到过这样的情况:我本可以使用一个特定的命令来立即识别问题,但这个命令对我来说不可用。 通过将本章限制为默认命令,您可以确信本章中介绍的故障排除步骤不仅与大多数 RHEL 7 安装相关,而且还与以前的发行版和其他 Linux 发行版相关。
在开始探讨故障诊断命令之前,我首先想了解一些有用的信息。 有用信息是一个有点模糊的术语,几乎每个文件、目录或命令都可以提供有用信息*。 我真正打算涵盖的是那些几乎可以找到任何问题信息的地方。*
*## 日志文件
日志文件通常是开始查找故障排除信息的第一个地方。 每当服务或服务器遇到问题时,检查日志文件的错误通常可以快速回答许多问题。
默认情况下,RHEL 和大多数 Linux 发行版保持他们在/var/log/
的日志文件,这实际上是文件系统层次结构标准的一部分(FHS)【显示】由 Linux 基金会。 然而,尽管/var/log/
可能是缺省位置,但并非所有日志文件都位于中(http://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard)。
虽然/var/log/httpd/
是 Apache 日志的默认位置,但是这个位置可以通过 Apache 的配置文件更改。 当 Apache 安装在标准 RHEL 包之外时,这种情况尤其常见。
像 Apache 一样,大多数服务都允许自定义日志位置。 在/var/log
之外找到专门为日志文件创建的定制目录或文件系统并不罕见。
下表是常见日志文件的简短列表,并描述了可以在其中找到的内容。
请记住,这个列表是特定于 Red Hat Enterprise Linux 7 的,虽然其他 Linux 发行版可能遵循类似的约定,但它们不能保证。
|日志文件
|
描述
|
| --- | --- |
| /var/log/messages
| 默认情况下,该日志文件包含所有优先级为INFO
或更高的 syslog 消息(电子邮件除外)。 |
| /var/log/secure
| 此日志文件包含与身份验证相关的消息项,例如:
- SSH 登录
- 用户创作
- 违反 Sudo 和特权升级
|
| /var/log/cron
| 该日志文件包含了crond
执行的历史,以及cron.daily
、cron.weekly
和其他执行的开始和结束时间。 |
| /var/log/maillog
| 此日志文件是邮件事件的默认日志位置。 如果使用 postfix,这是所有与 postfix 相关的消息的默认位置。 |
| /var/log/httpd/
| 这个日志目录是 Apache 日志的默认位置。 虽然这是默认位置,但它并不是所有 Apache 日志的保证位置。 |
| /var/log/mysql.log
| 这个日志文件是 mysqld 的默认日志文件。 很像httpd
日志,这是默认的,可以很容易地更改。 |
| /var/log/sa/
| 此目录包含默认每 10 分钟运行一次的sa
命令的结果。 我们将在本章后面的章节和本书中更多地使用这些数据。 |
对于许多问题,要检查的第一个日志文件是/var/log/messages
日志。 在 RHEL 系统上,该日志文件接收所有优先级为INFO
或更高的系统日志。 通常,这意味着发送到syslog
的任何重要事件都将在此日志文件中捕获。
以下是可以在/var/log/messages
中找到的一些日志消息的示例:
Dec 24 18:03:51 localhost systemd: Starting Network Manager Script Dispatcher Service...
Dec 24 18:03:51 localhost dbus-daemon: dbus[620]: [system] Successfully activated service 'org.freedesktop.nm_dispatcher'
Dec 24 18:03:51 localhost dbus[620]: [system] Successfully activated service 'org.freedesktop.nm_dispatcher'
Dec 24 18:03:51 localhost systemd: Started Network Manager Script Dispatcher Service.
Dec 24 18:06:06 localhost kernel: e1000: enp0s3 NIC Link is Down
Dec 24 18:06:06 localhost kernel: e1000: enp0s8 NIC Link is Down
Dec 24 18:06:06 localhost NetworkManager[750]: <info> (enp0s3): link disconnected (deferring action for 4 seconds)
Dec 24 18:06:06 localhost NetworkManager[750]: <info> (enp0s8): link disconnected (deferring action for 4 seconds)
Dec 24 18:06:10 localhost NetworkManager[750]: <info> (enp0s3): link disconnected (calling deferred action)
Dec 24 18:06:10 localhost NetworkManager[750]: <info> (enp0s8): link disconnected (calling deferred action)
Dec 24 18:06:12 localhost kernel: e1000: enp0s3 NIC Link is Up 1000 Mbps Full Duplex, Flow Control: RX
Dec 24 18:06:12 localhost kernel: e1000: enp0s8 NIC Link is Up 1000 Mbps Full Duplex, Flow Control: RX
Dec 24 18:06:12 localhost NetworkManager[750]: <info> (enp0s3): link connected
Dec 24 18:06:12 localhost NetworkManager[750]: <info> (enp0s8): link connected
Dec 24 18:06:39 localhost kernel: atkbd serio0: Spurious NAK on isa0060/serio0\. Some program might be trying to access hardware directly.
Dec 24 18:07:10 localhost systemd: Starting Session 53 of user root.
Dec 24 18:07:10 localhost systemd: Started Session 53 of user root.
Dec 24 18:07:10 localhost systemd-logind: New session 53 of user root.
正如我们所看到的,在故障诊断问题时,这个示例中有很多日志消息可能会很有用。
很多时候日志文件不在/var/log/
中,这可能是因为有人将日志位置修改到了默认位置之外的某个位置,也可能仅仅是因为所讨论的服务默认位于另一个位置。
一般来说,有三种方法可以找到不在/var/log/
中的日志文件。
如果您知道某个服务正在使用 syslog 进行日志记录,那么检查其消息要写到哪个日志文件的最佳位置是rsyslog配置文件。 rsyslog 服务有两个位置用于配置。 第一个是/etc/rsyslog.d
目录。
/etc/rsyslog.d
目录是用于自定义 rsyslog 配置的 include 目录。 第二个是/etc/rsyslog.conf
配置文件。 这是 rsyslog 的主要配置文件,包含许多默认的 syslog 配置。
以下是/etc/rsyslog.conf
默认内容的示例:
#### RULES ####
# Log all kernel messages to the console.
# Logging much else clutters up the screen.
#kern.* /dev/console
# Log anything (except mail) of level info or higher.
# Don't log private authentication messages!
*.info;mail.none;authpriv.none;cron.none /var/log/messages
# The authpriv file has restricted access.
authpriv.* /var/log/secure
# Log all the mail messages in one place.
mail.* -/var/log/maillog
# Log cron stuff
cron.* /var/log/cron
通过查看这个文件的内容,可以相当容易地确定哪些日志文件包含所需的信息,如果不是的话,至少可以确定 syslog 管理日志文件的可能位置。
并不是每个应用都使用 syslog; 对于那些不需要的日志文件,找到应用日志文件的最简单方法之一是读取应用的配置文件。
从配置文件中查找日志文件位置的一种快速而有用的方法是使用grep
命令在文件中搜索单词log
:
$ grep log /etc/samba/smb.conf
# files are rotated when they reach the size specified with "max log size".
# log files split per-machine:
log file = /var/log/samba/log.%m
# maximum size of 50KB per log file, then rotate:
max log size = 50
grep
命令是一个非常有用的命令,可用于搜索文件或目录以查找特定的字符串或模式。 这个命令将在本书中以各种方式使用。 在前面的代码片段中可以看到最简单的命令,其中使用grep
命令在/etc/samba/smb.conf
文件中搜索模式“log
”的任何实例。
在查看前面的grep
命令的输出后,我们可以看到配置的 samba 日志位置是/var/log/samba/log.%m
。 需要注意的是,在本例中,在创建文件时,%m
实际上被替换为一个“机器名”。 这实际上是 samba 配置文件中的一个变量。 这些变量对于每个应用都是唯一的,但是这种生成动态配置值的方法是一种常见的实践。
下面是使用grep
命令在 Apache 和 MySQL 配置文件中搜索“log
”的示例:
$ grep log /etc/httpd/conf/httpd.conf
# ErrorLog: The location of the error log file.
# logged here. If you *do* define an error logfile for a <VirtualHost>
# container, that host's errors will be logged there and not here.
ErrorLog "logs/error_log"
$ grep log /etc/my.cnf
# log_bin
log-error=/var/log/mysqld.log
在这两个实例中,此方法都能够识别服务日志文件的配置参数。 通过前面的三个示例,很容易看出通过配置文件进行搜索是多么有效。
find
命令是另一种查找日志文件的有用方法,将在本章后面深入介绍。 find
命令用于在目录结构中搜索指定文件。 查找日志文件的一种快速方法是简单地使用find
命令搜索以“.log
”结尾的任何文件:
# find /opt/appxyz/ -type f -name "*.log"
/opt/appxyz/logs/daily/7-1-15/alert.log
/opt/appxyz/logs/daily/7-2-15/alert.log
/opt/appxyz/logs/daily/7-3-15/alert.log
/opt/appxyz/logs/daily/7-4-15/alert.log
/opt/appxyz/logs/daily/7-5-15/alert.log
前一种方法通常被认为是最后的解决方案,通常在前一种方法不能产生结果时使用。
在执行find
命令时,最佳实践是非常明确地指定要搜索的目录。 当在非常大的目录上执行时,服务器的性能可能会降低。
如前所述,应用或服务的配置文件可以是很好的信息源。 虽然配置文件不会为您提供特定的错误,比如日志文件,但它们可以为您提供关键信息(例如,启用/禁用特性、输出目录和日志文件位置)。
通常,在大多数 Linux 发行版中,系统和服务配置文件位于/etc/
目录中。 然而,这并不意味着每个配置文件都位于/etc/
目录中。 事实上,应用在其home
目录中包含配置目录的情况并不少见。
那么,您如何知道什么时候应该在/etc/
目录中查找配置文件,而不是在应用目录中查找配置文件呢? 一般的经验法则是,如果包是 RHEL 发行版的一部分,那么可以安全地假设配置在/etc/
目录中。 其他内容可能存在/etc/
目录中,也可能不存在。 对于这些情况,你只需要寻找它们。
在大多数情况下,可以使用ls
命令,通过一个简单的目录清单,在/etc/
目录中找到系统配置文件:
$ ls -la /etc/ | grep my
-rw-r--r--. 1 root root 570 Nov 17 2014 my.cnf
drwxr-xr-x. 2 root root 64 Jan 9 2015 my.cnf.d
前面的代码片段使用ls
执行目录列表,并将该输出重定向到grep
,以便在输出中搜索字符串“my
”。 从输出中可以看到,有一个my.cnf
配置文件和一个my.cnf.d
配置目录。 MySQL 进程使用这些进行配置。 我们可以通过假设任何与 MySQL 相关的内容都包含字符串“my
”来找到这些内容。
如果配置文件作为 RPM 包的一部分部署,那么可以使用rpm
命令来标识配置文件。 要做到这一点,只需执行带有–q
(查询)标志的rpm
命令,以及–c
(configfiles)标志,后面加上包的名称:
$ rpm -q -c httpd
/etc/httpd/conf.d/autoindex.conf
/etc/httpd/conf.d/userdir.conf
/etc/httpd/conf.d/welcome.conf
/etc/httpd/conf.modules.d/00-base.conf
/etc/httpd/conf.modules.d/00-dav.conf
/etc/httpd/conf.modules.d/00-lua.conf
/etc/httpd/conf.modules.d/00-mpm.conf
/etc/httpd/conf.modules.d/00-proxy.conf
/etc/httpd/conf.modules.d/00-systemd.conf
/etc/httpd/conf.modules.d/01-cgi.conf
/etc/httpd/conf/httpd.conf
/etc/httpd/conf/magic
/etc/logrotate.d/httpd
/etc/sysconfig/htcacheclean
/etc/sysconfig/httpd
rpm
命令用于管理 RPM 包,在故障排除时是非常有用的命令。 在下一节中,我们将进一步讨论用于故障排除的命令。
与查找日志文件类似,要查找系统上的配置文件,可以使用命令。 在搜索日志文件时,使用find
命令搜索所有以.log
结尾的文件。 在下面的示例中,使用find
命令搜索名称以“http
”开头的所有文件。 这个find
命令应该至少返回一些结果,这些结果将提供与 HTTPD (Apache)服务相关的配置文件:
# find /etc -type f -name "http*"
/etc/httpd/conf/httpd.conf
/etc/sysconfig/httpd
/etc/logrotate.d/httpd
上面的示例搜索/etc
目录; 然而,这也可以用于搜索任何应用主目录中的用户配置文件。 与搜索日志文件类似,使用find
命令搜索配置文件通常被认为是最后的手段,不应该是使用的第一种方法。
一个非常有用的信息源是proc
文件系统。 这是一个由 Linux 内核维护的特殊文件系统。 文件系统可以用来查找关于正在运行的进程的有用信息,以及其他系统信息。 例如,如果我们想要识别一个系统支持的文件系统,我们可以简单地读取/proc/filesystems
文件:
$ cat /proc/filesystems
nodev sysfs
nodev rootfs
nodev bdev
nodev proc
nodev cgroup
nodev cpuset
nodev tmpfs
nodev devtmpfs
nodev debugfs
nodev securityfs
nodev sockfs
nodev pipefs
nodev anon_inodefs
nodev configfs
nodev devpts
nodev ramfs
nodev hugetlbfs
nodev autofs
nodev pstore
nodev mqueue
nodev selinuxfs
xfs
nodev rpc_pipefs
nodev nfsd
这个文件系统非常有用,它包含了大量关于正在运行的系统的信息。 在本书的整个故障排除步骤中将使用proc filesystem
。 在诊断从特定进程到只读文件系统的所有问题时,可以以各种方式使用它。
本节将介绍常用的故障排除命令,这些命令可用于从系统或运行中的服务收集信息。 虽然不可能涵盖所有可能的命令,但所使用的命令确实涵盖了 Linux 系统的基本故障排除步骤。
本书中使用的故障排除步骤主要是基于命令行。 虽然可以从图形化桌面环境中执行其中的许多操作,但更高级的项是特定于命令行的。 因此,本书假设读者至少对 Linux 有一个基本的了解。 更具体地说,本书假设读者已经通过 SSH 登录到服务器,并且熟悉基本命令,如cd
、cp
、mv
、rm
和ls
。
对于那些可能不太熟悉的人,我想快速介绍一些基本的命令行用法,这是本书所需要的知识。
许多读者可能都熟悉下面的命令:
$ ls -la
total 588
drwx------. 5 vagrant vagrant 4096 Jul 4 21:26 .
drwxr-xr-x. 3 root root 20 Jul 22 2014 ..
-rw-rw-r--. 1 vagrant vagrant 153104 Jun 10 17:03 app.c
大多数人应该知道这是ls
命令,它用于执行目录列表。 可能不太熟悉的是该命令的–la
部分具体是什么或做什么。 为了更好地理解这一点,让我们看看 ls 命令本身:
$ ls
app.c application app.py bomber.py index.html lookbusy-1.4 lookbusy-1.4.tar.gz lotsofiles
ls
命令的前一次执行看起来与前一次非常不同。 这是因为后者是ls
的默认输出。 命令的–la
部分通常称为命令标志或选项。 命令标志允许用户在提供特定选项的情况下更改命令的默认行为。
事实上,–la
标志是两个单独的选项,–l
和–a
; 它们甚至可以单独指定:
$ ls -l -a
total 588
drwx------. 5 vagrant vagrant 4096 Jul 4 21:26 .
drwxr-xr-x. 3 root root 20 Jul 22 2014 ..
-rw-rw-r--. 1 vagrant vagrant 153104 Jun 10 17:03 app.c
我们可以从前面的代码片段中看到,ls –la
的输出与ls –l –a
完全相同。 对于常见命令,如ls
命令,标志是否分组或分隔无关紧要,它们将以相同的方式解析。 贯穿本书,例子将显示分组和未分组。 如果出于任何特定原因进行分组或取消分组,它将被调用; 否则,本书中使用的分组或非分组是为了视觉吸引力和记忆。
除了分组和取消分组,本书还将以长格式显示旗帜。 在前面的示例中,我们展示了标志-a
,这被称为短标志。 同样的选项也可以以长格式--all
提供:
$ ls -l --all
total 588
drwx------. 5 vagrant vagrant 4096 Jul 4 21:26 .
drwxr-xr-x. 3 root root 20 Jul 22 2014 ..
-rw-rw-r--. 1 vagrant vagrant 153104 Jun 10 17:03 app.c
–a
和--all
标志本质上是相同的选项; 它可以简单地用短形式和长形式来表示。
一个重要的要记住的是,不是每个简短的标志都有一个长形式,反之亦然。 每个命令都有自己的语法,有些命令只支持短格式,有些命令只支持长格式,但许多命令两者都支持。 在大多数情况下,长标记和短标记都将在命令的手册页中进行记录。
另一个常见的命令行实践是piping
输出,在本书中将多次使用。 具体来说,例子如下:
$ ls -l --all | grep app
-rw-rw-r--. 1 vagrant vagrant 153104 Jun 10 17:03 app.c
-rwxrwxr-x. 1 vagrant vagrant 29390 May 18 00:47 application
-rw-rw-r--. 1 vagrant vagrant 1198 Jun 10 17:03 app.py
在上面的示例中,ls -l --all
命令的输出通过管道传递到grep
命令。 通过在两个命令之间放置|
或管道字符,第一个命令的输出将通过管道传递到第二个命令的输入。 将执行ls
命令之前的示例; 然后,grep
命令将在输出中搜索模式“app
”的任何实例。
在本书中,管道输出到grep
实际上会经常使用,因为这是将输出修剪成可维护尺寸的简单方法。 很多时候,示例还包含多个级别的管道:
$ ls -la | grep app | awk '{print $4,$9}'
vagrant app.c
vagrant application
vagrant app.py
在前面的代码中,ls -la
的输出通过管道传递到grep
的输入; 然而,这一次,grep
的输出也通过管道输送到awk
的输入。
虽然可以通过管道传递许多命令,但并不是每个命令都支持这一点。 通常,从文件或命令行接受用户输入的命令也接受管道输入。 与标志一样,可以使用命令的手册页来标识该命令是否接受管道输入。
在长时间管理相同的服务器时,您开始记住有关这些服务器的关键信息。 比如物理内存的数量、文件系统的大小和布局,以及应该运行哪些进程。 然而,当您不熟悉所讨论的服务器时,收集这类信息总是一个好主意。
本节中的命令可用于收集此类通用信息。
在我的系统管理生涯早期,我有一位导师,他曾经告诉我:当我登录到服务器时,我总是运行 w。 这个简单的技巧实际上在我的职业生涯中一次又一次地非常有用。 w
命令很简单; 执行时,它将输出诸如系统正常运行时间、平均负载和登录用户等信息:
# w
04:07:37 up 14:26, 2 users, load average: 0.00, 0.01, 0.05
USER TTY LOGIN@ IDLE JCPU PCPU WHAT
root tty1 Wed13 11:24m 0.13s 0.13s -bash
root pts/0 20:47 1.00s 0.21s 0.19s -bash
在使用不熟悉的系统时,这些信息非常有用。 即使您熟悉该系统,输出也很有用。 使用这个命令,你可以看到:
-
When this system was last rebooted:
:这些信息非常有用; 无论是 Apache 等服务关闭的警告,还是用户调用,因为他们被锁定在系统之外。 当这些问题是由意外重启引起时,报告的问题通常不包含这些信息。 通过运行
w
命令,很容易看到自上次重新启动以来所经过的时间。 -
The load average of the system:
load average: 0.00, 0.01, 0.05
:平均负载是对系统健康状况的一个非常重要的度量。 总的来说,平均负载是一段时间内处于wait
状态的进程的平均数量。w
输出中的三个数字代表不同的时间。这些数字从左到右排列为 1 分钟、5 分钟和 15 分钟。
-
Who is logged in and what they are running:
USER TTY LOGIN@ IDLE JCPU PCPU WHAT
root tty1 Wed13 11:24m 0.13s 0.13s -bash
w
命令提供的最后一条信息是当前登录的用户以及他们正在执行的命令。
这是实质上与who
命令的相同的输出,其中包括登录的用户、登录的时间、空闲时间以及 shell 正在运行的命令。 最后一项非常重要。
在与大团队合作时,通常会有不止一个人对一个问题或罚单做出回应。 通过在登录后立即运行w
命令,您将看到其他用户正在做什么,从而防止您覆盖其他用户所采取的任何故障排除或纠正步骤。
rpm
命令用于管理Red Hat 包管理器(RPM)。 使用该命令可以安装和删除 RPM 包,也可以搜索已经安装的 RPM 包。
在本章的前面,我们看到了如何使用rpm
命令来查找配置文件。 下面是使用rpm
命令查找关键信息的几种其他方法。
在对服务进行故障排除时,一个关键步骤通常是确定服务的版本及其安装方式。 要列出系统上安装的所有 RPM 包,只需使用-q
(查询)和-a
(全部)执行rpm
命令:
# rpm -q -a
kpatch-0.0-1.el7.noarch
virt-what-1.13-5.el7.x86_64
filesystem-3.2-18.el7.x86_64
gssproxy-0.3.0-9.el7.x86_64
hicolor-icon-theme-0.12-7.el7.noarch
rpm
命令是一个非常多样化的命令,有许多标志。 在前面的示例中,使用了-q
和-a
标志。 -q
标志告诉rpm
命令正在执行的操作是查询; 你可以把它想象成一个“搜索模式”。 -a
或--all
标志告诉rpm
命令列出所有包。
一个有用的特性是在前面的命令中添加--last
标志,因为这会导致rpm
命令按安装时间列出包,最新的在前面。
另一个有用的rpm
函数是显示由特定包部署的所有文件:
# rpm -q --filesbypkg kpatch-0.0-1.el7.noarch
kpatch /usr/bin/kpatch
kpatch /usr/lib/systemd/system/kpatch.service
在前面的示例中,我们再次使用-q
标志和--filesbypkg
标志来指定正在运行一个查询。 --filesbypkg
标志将导致rpm
命令列出指定包部署的所有文件。
在试图确定服务的配置文件位置时,这个示例非常有用。
在第三个示例中,我们将使用的一个非常有用的特性rpm
—verify。 rpm
命令能够验证指定包部署的文件是否已从其原始内容更改。 为此,我们将使用-V
(verify)标志:
# rpm -V httpd
S.5....T. c /etc/httpd/conf/httpd.conf
在前面的示例中,我们简单地运行带有-V
标志和包名的rpm
命令。 -q
标志用于查询,-V
标志用于验证。 使用这个命令,我们可以看到只列出了/etc/httpd/conf/httpd.conf
文件; 这是因为rpm
将只输出已更改的文件。
在该输出的第一列中,我们可以看到哪个验证检查文件失败。 虽然这一列一开始有点神秘,但 rpm 手册页有一个有用的表(如下表所示)解释每个字符的含义:
S
:表示文件大小不同M
:这意味着模式不同(包括权限和文件类型)5
:这意味着摘要(以前的MD5 sum
)不同D
:设备主/副号码不匹配L
:表示readLink(2)
路径不匹配U
:这意味着用户的所有权不同G
:群组所有权不同T
:表示mTime
不同P
:表示caPabilities
不同
使用这个列表,我们可以看到httpd
。 conf's
文件大小、MD5
总和和mtime
(修改时间)不是由httpd.rpm
部署的。 这意味着httpd.conf
文件很可能在安装后被修改了。
虽然乍一看,rpm
命令可能不像故障诊断命令,但前面的示例显示了故障诊断工具的强大程度。 通过这些示例,可以很容易地识别重要的文件,以及这些文件是否已从部署的版本中修改。
在诊断文件系统问题时,df
命令是一个非常有用的命令。 df
命令用于输出挂载文件系统的空间利用率:
# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/rhel-root 6.7G 1.6G 5.2G 24% /
devtmpfs 489M 0 489M 0% /dev
tmpfs 498M 0 498M 0% /dev/shm
tmpfs 498M 13M 485M 3% /run
tmpfs 498M 0 498M 0% /sys/fs/cgroup
/dev/sdb1 212G 58G 144G 29% /repos
/dev/sda1 497M 117M 380M 24% /boot
在上例中,df
命令中包含-h
标志。 此标志使df
命令以“人类可读”的格式打印任何大小的值。 默认情况下,df
将简单地以千字节为单位打印这些值。 从这个示例中,我们可以快速地看到所有挂载文件系统的当前使用情况。 具体地说,如果我们看一下输出,我们可以看到/filesystem
目前使用了 24%:
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/rhel-root 6.7G 1.6G 5.2G 24% /
这是识别文件系统是否已满的一种非常快速和简单的方法。 此外,df
命令在显示挂载哪些文件系统以及它们挂载到何处的详细信息方面也非常有用。 从包含/filesystem
的行中,我们可以看到底层设备是/dev/mapper/rhel-root
。
通过这个命令,我们能够识别两个关键的信息片段。
df
的默认行为是显示已使用的文件系统空间量。 但是,它还可以用于显示每个文件系统可用、使用和空闲的inode的数量。 要输出 inode 利用率,只需在执行df
命令时添加-i
(inode)标志:
# df -i
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/mapper/rhel-root 7032832 44318 6988514 1% /
devtmpfs 125039 347 124692 1% /dev
仍然可以使用–h
标志和df
以人类可读的格式打印输出。 但是,使用–i
标志,将输出缩写为M
,表示数百万,K
表示数千,以此类推。 这种输出很容易与兆字节或千字节混淆,所以通常,在与其他用户/管理员共享输出时,我不使用人类可读的 inode 输出。
当执行free
命令时,将输出关于系统可用内存和正在使用内存的统计信息:
$ free
total used free shared buffers cached
Mem: 1018256 789796 228460 13116 3608 543484
-/+ buffers/cache: 242704 775552
Swap: 839676 4 839672
从前面的示例中,我们可以看到free
命令的输出提供了总可用内存、当前使用的内存数量和空闲内存数量。 free
命令是识别系统中内存当前状态的一种简单而快速的方法。
然而,free
的输出一开始可能有点令人困惑。
与其他操作系统相比,Linux 使用内存的方式有所不同。 在前面的输出中,您将看到它列出了 543,484 KB 作为缓存。 这个内存,虽然在技术上使用,实际上是可用内存的一部分。 系统可以根据需要重新分配缓存的内存。
在输出的第二行可以看到一种快速而简单的方法来查看实际使用或免费的内容。 上面的输出显示系统上有 775,552 KB 的可用内存。
在以前的 RHEL 版本中,free
命令的第二行是确定可用内存数量的最简单方法。 然而,在 RHEL 7 中,对/proc/meminfo
文件进行了一些改进。 其中一个改进是增加了MemAvailable统计数据:
$ grep Available /proc/meminfo
MemAvailable: 641056 kB
/proc/meminfo
文件是位于/proc
文件系统中的许多有用文件之一。 这个文件由内核维护,包含系统当前的内存统计信息。 在诊断内存问题时,这个文件非常有用,因为它包含的信息比free
命令的输出多得多。
ps
命令是用于任何故障排除活动的基本命令。 当执行这个命令时,将输出一个正在运行的进程列表:
# ps
PID TTY TIME CMD
15618 pts/0 00:00:00 ps
17633 pts/0 00:00:00 bash
ps
命令有许多标志和选项,用于显示关于运行进程的不同信息。 下面是一些在故障排除过程中有用的示例ps
命令。
下面的ps
命令使用-e
(所有,所有进程)、-l
(长格式)和-f
(全格式)标志。 这些标志将导致ps
命令不仅打印每个进程,而且还将以一种提供相当多有用信息的格式打印它们:
# ps -elf
F S UID PID PPID C PRI NI ADDR SZ WCHAN STIME TTY TIME CMD
1 S root 2 0 0 80 0 - 0 kthrea Dec24 ? 00:00:00 [kthreadd]
ps -elf
前面的输出,我们可以看到很多有用的信息kthreadd
的过程,等信息父进程 ID(PPID),优先级【显示】的(PRI),【病人】美好价值(【t16.1】倪), 以及正在运行的进程的驻留内存大小(SZ)。****
我发现前面的例子是一个非常通用的ps
命令,可以在大多数情况下使用。
前面的例子可以变得相当大; 这使得识别特定过程变得困难。 本例使用-U
标志指定用户。 这会导致ps
命令打印所有作为指定用户运行的进程; 后缀在以下情况下:
ps -U postfix -l
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
4 S 89 1546 1536 0 80 0 - 23516 ep_pol ? 00:00:00 qmgr
4 S 89 16711 1536 0 80 0 - 23686 ep_pol ? 00:00:00 pickup
值得注意的是,–U
标志还可以与其他标志结合使用,以提供关于正在运行的进程的更多信息。 在前面的示例中,-l
标志再次用于以长格式打印输出。
如果进程 ID 或 PID 已经已知,可以通过使用–p
(进程 ID)标志进一步缩小进程列表:
# ps -p 1236 -l
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
4 S 0 1236 1 0 80 0 - 20739 poll_s ? 00:00:00 sshd
当与–L
(显示带有 LWP 列的线程)或–m
(显示进程后的线程)标志结合使用时,这可能特别有用,这些标志用于打印进程线程。 在对多线程应用进行故障诊断时,-L
和-m
标志可能非常重要。
ps
命令允许用户定制使用-o
(用户定义的格式)标记打印的列:
# ps -U postfix -o pid,user,pcpu,vsz,cmd
PID USER %CPU VSZ CMD
1546 postfix 0.0 94064 qmgr -l -t unix -u
16711 postfix 0.0 94744 pickup -l -t unix -u
–o
选项允许使用大量的自定义列。 在前面的版本中,我选择了与 top 命令中打印的选项类似的选项。
顶部命令是最流行的 Linux 故障诊断命令之一。 它用于显示按 CPU 使用率排序的顶级进程(默认情况下)。 在本章中,我选择省略 top 命令,因为我觉得ps
命令比 top 命令更基本、更灵活。 随着人们对ps
命令更加熟悉,top 命令将更容易学习和理解。
网络是任何系统管理员的基本技能。 如果没有正确配置的网络接口,服务器的作用就很小。 本节中的命令主要用于查询网络配置和当前状态。 学习这些命令是必不可少的,因为它们不仅对故障排除有用,而且对日常设置和配置也有用。
ip
命令用于管理网络设置,例如接口的配置、路由以及基本上与网络相关的任何内容。 虽然这些通常不被认为是故障排除任务,但是ip
命令也可以用来显示系统的网络配置。 如果不能查找路由或设备配置等网络细节,就很难排除网络相关问题。
下面的示例展示了使用ip
命令识别关键网络配置设置的各种方法。
使用ip
命令的的核心之一是查找网络接口并显示其配置。 为此,我们将使用以下命令:
# ip addr show dev enp0s3
2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 08:00:27:6e:35:18 brd ff:ff:ff:ff:ff:ff
inet 10.0.2.15/24 brd 10.0.2.255 scope global dynamic enp0s3
valid_lft 45083sec preferred_lft 45083sec
inet6 fe80::a00:27ff:fe6e:3518/64 scope link
valid_lft forever preferred_lft forever
在前面的ip
命令中,提供的第一个选项addr
(地址)用于定义我们要查找的信息类型。 第二个选项show
告诉ip
显示第一个选项的配置。 第三个选项dev
(设备)后面是有关的网络接口设备; enp0s3
。 如果省略了第三个选项,则ip
命令将显示所有网络设备的地址配置。
对于那些使用过以前的 RHEL 版本的人来说,设备名称enp0s3
可能看起来有点奇怪。 该设备遵循在systemd
中引入的较新的网络设备命名方案。 从 RHEL 7 开始,网络设备将使用如上所述的设备名称,这些名称基于设备驱动程序和 BIOS 详细信息。
要了解更多关于 RHEL 7 的新命名方案,只需参考以下 URL:
ip
命令还可以显示路由配置信息。 此信息对于故障排除服务器之间的连接问题至关重要:
# ip route show
default via 10.0.2.2 dev enp0s3 proto static metric 1024
10.0.2.0/24 dev enp0s3 proto kernel scope link src 10.0.2.15
192.168.56.0/24 dev enp0s8 proto kernel scope link src 192.168.56.101
前面的ip
命令使用route
选项和show
选项显示此服务器上定义的所有路由。 像前面的例子一样,通过添加dev
(device)选项后跟设备名称,可以将输出限制到特定的设备:
# ip route show dev enp0s3
default via 10.0.2.2 proto static metric 1024
10.0.2.0/24 proto kernel scope link src 10.0.2.15
前面的示例显示了查找当前网络配置的方法,下面的这个命令使用-s
(统计信息)标志显示指定设备的网络统计信息:
# ip -s link show dev enp0s3
2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT qlen 1000
link/ether 08:00:27:6e:35:18 brd ff:ff:ff:ff:ff:ff
RX: bytes packets errors dropped overrun mcast
109717927 125911 0 0 0 0
TX: bytes packets errors dropped carrier collsns
3944294 40127 0 0 0 0
在前面的示例中,link
(网络设备)选项用于指定统计信息应该限制在指定设备上。
在排除被丢弃的数据包或确定哪个接口具有更高的网络利用率时,所显示的统计信息非常有用。
netstat
命令是任何系统管理员的工具带中必不可少的工具。 从以下事实可以看出,netstat
命令是普遍可用的,甚至对于传统上不使用命令行进行管理的操作系统也是如此。
netstat
的主要用途之一是打印现有的已建立的网络连接。 这可以通过简单地执行netstat
; 然而,如果使用了-a
(all)标志,输出还将包括监听端口:
# netstat -na
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:44969 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN
tcp 0 0 192.168.56.101:22 192.168.56.1:50122 ESTABLISHED
tcp6 0 0 ::1:25 :::* LISTEN
前面netstat
使用的-a
(all)标志导致打印所有监听端口,而-n
标志用于强制以数字格式输出,例如打印 IP 地址而不是 DNS 主机名。
前面的例子将在第五章、网络故障排除中大量使用,在这里我们将对网络连接进行故障排除。
我见过许多服务正在运行的实例,并且可以通过ps
命令看到; 但是,客户端要连接的端口没有绑定和侦听。 以下netstat
命令在诊断服务的连接性问题时非常有用:
# netstat -nlp --tcp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 1536/master
tcp 0 0 0.0.0.0:44969 0.0.0.0:* LISTEN 1270/rpc.statd
tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN 1215/rpcbind
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1236/sshd
tcp6 0 0 ::1:25 :::* LISTEN 1536/master
tcp6 0 0 :::111 :::* LISTEN 1215/rpcbind
tcp6 0 0 :::22 :::* LISTEN 1236/sshd
tcp6 0 0 :::46072 :::* LISTEN 1270/rpc.statd
前面的命令非常有用,因为它结合了三个有用的选项:
–l
(listening),它告诉netstat
只列出听力插座--tcp
,它告诉netstat
将输出限制为 TCP 连接–p
(program),它告诉netstat
列出在该端口上监听的进程的 PID 和名称
与netstat
一起使用的一个经常被忽略的选项是利用延迟特性。 通过在命令末尾添加一个数字,netstat
将持续运行,并在执行之间休眠指定的秒数。
如果执行以下命令,netstat
命令将每 5 秒打印一次所有正在监听的 TCP 套接字:
# netstat -nlp --tcp 5
在调查网络连接问题时,延迟特性非常有用。 因为它可以很容易地显示应用何时为新连接绑定端口。
虽然我们稍微讨论了一下使用free
和ps
等命令对性能进行故障诊断的,但本节将展示一些非常有用的命令,它们回答了“为什么速度慢?”这个古老的问题。
iotop
命令是 Linux 中相对较新的命令。 在以前的 RHEL 发行版中,默认情况下没有安装它。 iotop
命令提供了一个类似命令的顶级界面,但它并没有显示哪个进程占用了最多的 CPU 时间或内存,而是按照 I/O 利用率排序显示进程:
# iotop
Total DISK READ : 0.00 B/s | Total DISK WRITE : 0.00 B/s
Actual DISK READ: 0.00 B/s | Actual DISK WRITE: 0.00 B/s
TID PRIO USER DISK READ DISK WRITE SWAPIN IO COMMAND
1536 be/4 root 0.00 B/s 0.00 B/s 0.00 % 0.00 % master -w
1 be/4 root 0.00 B/s 0.00 B/s 0.00 % 0.00 % systemd --switched-root --system --deserialize 23
与前面的一些命令不同,iotop
非常专门用于显示使用 I/O 的进程。 然而,有一些非常有用的标志可以改变 iotop 的默认行为。 标志,例如–o
(only),它告诉iotop
只打印使用 I/O 的进程,而不是它的默认行为打印所有进程。 另一组有用的标志是-q
(静音)和–n
(迭代次数)。
与-o
标志一起,这些标志可以用来告诉iotop
只打印使用 I/O 的进程,而不为下一次迭代清除屏幕:
# iotop -o -q -n2
Total DISK READ : 0.00 B/s | Total DISK WRITE : 0.00 B/s
Actual DISK READ: 0.00 B/s | Actual DISK WRITE: 0.00 B/s
TID PRIO USER DISK READ DISK WRITE SWAPIN IO COMMAND
Total DISK READ : 0.00 B/s | Total DISK WRITE : 0.00 B/s
Actual DISK READ: 0.00 B/s | Actual DISK WRITE: 0.00 B/s
22965 be/4 root 0.00 B/s 0.00 B/s 0.00 % 0.03 % [kworker/0:3]
如果我们看一下前面的示例输出,我们可以看到iotop
命令的两次独立迭代。 然而,与前面的示例不同的是,输出是连续的,这样我们就可以看到哪些进程在每次迭代中使用了 I/O。
默认情况下,iotop
迭代之间的延迟为 1 秒; 然而,这可以通过-d
(延迟)标志进行修改。
其中iotop
显示进程正在使用的 I/O,iostat
显示设备正在使用的:
# iostat -t 1 2
Linux 3.10.0-123.el7.x86_64 (localhost.localdomain) 12/25/2014 _x86_64_ (1 CPU)
12/25/2014 03:20:10 PM
avg-cpu: %user %nice %system %iowait %steal %idle
0.11 0.00 0.17 0.01 0.00 99.72
Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn
sda 0.38 2.84 7.02 261526 646339
sdb 0.01 0.06 0.00 5449 12
dm-0 0.33 2.77 7.00 254948 644275
dm-1 0.00 0.01 0.00 936 4
12/25/2014 03:20:11 PM
avg-cpu: %user %nice %system %iowait %steal %idle
0.00 0.00 0.99 0.00 0.00 99.01
Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn
sda 0.00 0.00 0.00 0 0
sdb 0.00 0.00 0.00 0 0
dm-0 0.00 0.00 0.00 0 0
dm-1 0.00 0.00 0.00 0 0
前面的iostat
命令使用-t
(时间戳)标志打印每个报告的时间戳。 这两个数字是间隔和计数值。 在前面的示例中,iostat
以一秒的间隔运行,总共有两个迭代。
iostat
命令对于诊断与 I/O 相关的问题非常有用。 然而,输出结果往往具有误导性。 执行时,第一个报告中提供的值是自上次系统重新启动以来的平均值。 后续报告是上次报告之后的报告。 在本例中,我们执行了两个报告,间隔一秒。 你可以看到第一份报告中的数字比第二份报告中的要高得多。
由于这个原因,许多系统管理员简单地忽略了第一个报告,但他们并不完全理解其中的原因。 因此,不熟悉iostat
的人对第一篇报告中的值做出反应的情况并不少见。
iostat
命令确实有一个标志-y
(省略第一个报告),这实际上会导致iostat
省略第一个报告。 对于那些可能不太熟悉使用iostat
的用户,这是一个很好的标志。
iostat
命令还有一些非常有用的标志,这些标志允许操作其显示数据的方式。 诸如–p
(设备)等标志允许您将统计信息限制到指定的设备,或者–x
(扩展统计信息)将打印扩展统计信息:
# iostat -p sda -tx
Linux 3.10.0-123.el7.x86_64 (localhost.localdomain) 12/25/2014 _x86_64_ (1 CPU)
12/25/2014 03:38:00 PM
avg-cpu: %user %nice %system %iowait %steal %idle
0.11 0.00 0.17 0.01 0.00 99.72
Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
sda 0.01 0.02 0.13 0.25 2.81 6.95 51.70 0.00 7.62 1.57 10.79 0.85 0.03
sda1 0.00 0.00 0.02 0.02 0.05 0.02 3.24 0.00 0.24 0.42 0.06 0.23 0.00
sda2 0.01 0.02 0.11 0.19 2.75 6.93 65.47 0.00 9.34 1.82 13.58 0.82 0.02
上面的示例使用-p
标志指定sda
设备,使用-t
标志打印时间戳,使用-x
标志打印扩展统计信息。 在测量特定设备的 I/O 性能时,这些标志非常有用。
其中iostat
用于磁盘 I/O 性能统计,vmstat
用于内存使用率和性能统计:
# vmstat 1 3
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
2 0 4 225000 3608 544900 0 0 3 7 17 28 0 0 100 0 0
0 0 4 224992 3608 544900 0 0 0 0 19 19 0 0 100 0 0
0 0 4 224992 3608 544900 0 0 0 0 6 9 0 0 100 0 0
vmstat
语法与iostat
非常相似,其中您将报告的间隔和计数作为命令行参数提供。 此外,与iostat
一样,第一个报告实际上是自上次重启以来的平均值,而后续报告是自上次报告以来的平均值。 不幸的是,与iostat
命令不同,vmstat
命令没有包含省略第一个报告的标志。 因此,在大多数情况下,直接忽略第一份报告是恰当的。
虽然vmstat
可能没有包含省略第一个报告的标志,但它确实有一些非常有用的标志; 它们是标志–m
(slab),它导致vmstat
以定义的间隔输出系统的slabinfo
,以及-s
(stats),它打印系统的内存统计信息的扩展报告:
# vmstat -stats
1018256 K total memory
793416 K used memory,
290372 K active memory
360660 K inactive memory
224840 K free memory
3608 K buffer memory
544908 K swap cache
839676 K total swap
4 K used swap
839672 K free swap
10191 non-nice user cpu ticks
67 nice user cpu ticks
11353 system cpu ticks
9389547 idle cpu ticks
556 IO-wait cpu ticks
33 IRQ cpu ticks
4434 softirq cpu ticks
0 stolen cpu ticks
267011 pages paged in
647220 pages paged out
0 pages swapped in
1 pages swapped out
1619609 interrupts
2662083 CPU context switches
1419453695 boot time
59061 forks
前面的代码是使用-s
或--stats
标志的示例。
一个非常有用的实用程序是sar
命令,sar
是与sysstat
包一起提供的实用程序。 sysstat
包包括收集系统指标(如磁盘、CPU、内存和网络利用率)的各种实用程序。 默认情况下,该收集将每 10 分钟运行一次,并作为/ettc/cron.d/sysstat
中的cron
作业执行。
虽然sysstat
收集的数据非常有用,但在高性能环境中,这个包有时会被删除。 因为系统利用率统计信息的收集会增加系统的利用率,从而导致性能下降。 要查看是否安装了sysstat
包,只需使用带有-q
(查询)标志的 rpm 命令:
# rpm -q sysstat
sysstat-10.1.5-4.el7.x86_64
sar
命令允许用户查看sysstat
实用程序收集的信息。 当不带标志执行时,sar
命令将打印当前 CPU 统计信息:
# sar | head -6
Linux 3.10.0-123.el7.x86_64 (localhost.localdomain) 12/25/2014 _x86_64_ (1 CPU)
12:00:01 AM CPU %user %nice %system %iowait %steal %idle
12:10:02 AM all 0.05 0.00 0.20 0.01 0.00 99.74
12:20:01 AM all 0.05 0.00 0.18 0.00 0.00 99.77
12:30:01 AM all 0.06 0.00 0.25 0.00 0.00 99.69
每天午夜,systat
收集器将创建一个新文件来存储收集到的统计信息。 要引用该文件中的统计信息,只需使用-f
(file)标志对指定的文件运行sar
:
# sar -f /var/log/sa/sa13
Linux 3.10.0-123.el7.x86_64 (localhost.localdomain) 12/13/2014 _x86_64_ (1 CPU)
10:24:43 AM LINUX RESTART
10:30:01 AM CPU %user %nice %system %iowait %steal %idle
10:40:01 AM all 2.99 0.00 0.96 0.43 0.00 95.62
10:50:01 AM all 9.70 0.00 2.17 0.00 0.00 88.13
11:00:01 AM all 0.31 0.00 0.30 0.02 0.00 99.37
11:10:01 AM all 1.20 0.00 0.41 0.01 0.00 98.38
11:20:01 AM all 0.01 0.00 0.04 0.01 0.00 99.94
11:30:01 AM all 0.92 0.07 0.42 0.01 0.00 98.59
11:40:01 AM all 0.17 0.00 0.08 0.00 0.00 99.74
11:50:02 AM all 0.01 0.00 0.03 0.00 0.00 99.96
在上述代码中,指定的文件为/var/log/sa/sa13
; 该文件包含本月 13 日的统计信息。
sar
命令有许多有用的标志,太多了,本章无法一一列出。 下面列出了一些非常有用的标志:
-b
:打印与iostat
命令类似的 I/O 统计信息-n ALL
:打印所有网络设备的网络统计信息-R
:打印内存利用率统计信息- :打印所有收集到的数据。 它本质上相当于运行
sar -bBdHqrRSuvwWy -I SUM -I XALL -m ALL -n ALL -u ALL -P ALL
虽然sar
命令显示了许多统计信息,但我们已经介绍了iostat
或vmstat
等命令。 sar
命令的最大好处是能够查看过去的统计数据。 在故障排除短时间内发生的性能问题或已经缓解的性能问题时,此功能至关重要。
在本章中,您了解了日志文件、配置文件和/proc
文件系统是故障排除过程中的关键信息来源。 我们还介绍了许多基本故障诊断命令的基本用法。
在阅读本章时,您可能已经注意到,在日常生活中也有相当多的命令用于非故障排除目的。 如果我们回顾第 1 章、故障排除最佳实践中的故障排除过程,第一步包括信息收集。
虽然这些命令可能无法解释问题本身,但它们可以帮助收集有关问题的信息,从而获得更准确和更快速的解决方案。 熟悉这些基本命令对于成功进行故障排除至关重要。
在接下来的几章中,我们将使用这些基本命令来排除现实场景中的故障。 下一章的重点是解决基于 web 的应用的问题。*