第二十一章:系统性能和监控

即使“它很慢!”不是系统管理员能听到的最可怕的短语,它也在列表中遥遥领先。用户不知道为什么系统运行缓慢,甚至可能无法进一步量化或限定问题。只是感觉很慢。通常没有测试用例,没有一组可重复的步骤,也没有什么特别错误。一个缓慢的投诉可能会导致你花费数小时在系统中挖掘,试图找到可能存在或甚至不存在的问题。

有一句话更可怕,尤其是在你投入了这些时间的工作之后:“它仍然很慢。”

缺乏经验的系统管理员通过购买更快的硬件来加速缓慢的系统。这就将“速度问题”换成了昂贵的零件,甚至更昂贵的时间。升级只是让你在不实际使用你已经拥有的硬件的情况下隐藏问题,有时甚至根本无法解决问题。

您可以通过调整导致问题的软件来经常解决性能问题。你的WordPress网站很慢吗?调查在memcached或其他PHP加速器下运行PHP的情况。FreeBSD只是应用程序堆栈的一层,所以一定要对其他层给予适当的关注。

FreeBSD包含许多工具,旨在帮助您检查系统性能,并提供必要的信息,以了解实际减慢速度的原因。其中一些,如 dtrace(1) ,非常复杂,需要对系统、软件和自己的书有广泛的了解。一旦你了解了问题所在,确定问题的解决方案就会变得简单得多。实际上,您可能需要更快的硬件,但有时转移系统负载或重新配置软件可能会以更低的成本解决问题。无论哪种情况,第一步都是理解问题。

计算机资源

性能问题通常是由于运行的任务比计算机可以处理的任务多造成的。这似乎很明显,但想想看。这到底意味着什么?

计算机有四种基本资源:输入/输出、网络带宽、内存和CPU。如果其中任何一个被填满,其他人就无法发挥最大作用。例如,您的CPU很可能正在等待磁盘传递数据或等待网络数据包到达。如果你升级CPU以使系统更快,你会失望的。购买一台全新的服务器可能会解决这个问题,但只能通过扩大现有的瓶颈来解决。新系统可能比旧系统有更多的内存、更快的磁盘、更好的网卡和更快的处理器。您已将问题推迟到性能达到某个新的极限。然而,通过识别您的系统不足之处并满足特定需求,您可以进一步扩展现有的硬件。毕竟,当几GB相对便宜的内存可以解决问题时,为什么还要购买一个全新的系统呢?(当然,如果你的目标是淘汰这个“缓慢”的系统,使其成为你的新桌面,那就另当别论了。)

输入/输出是一个常见的瓶颈。系统总线具有最大吞吐量,虽然您可能没有将磁盘或网络推到极限,但您可能会通过不断轰炸来使总线饱和。

系统速度减慢的一个常见原因是同时运行多个大型程序。不仅磁盘I/O会饱和,而且处理器可能会花费大部分时间等待在CPU缓存和内存之间交换数据。例如,我曾经轻率地安排了一次大规模的数据库日志轮换,在每天的 periodic(8) 运行的同时移动和压缩了数GB的数据。由于该作业需要关闭主数据库并导致应用程序停机,因此速度至关重要。数据库作业和 periodic(8) 运行都慢得令人难以忍受。重新安排其中一项工作使这两项工作都进行得更快。

FreeBSD有一些提高性能的特性。进行大量的加密操作?使用 aesni(4) 内核模块。数据库是磁盘绑定的吗?考虑文件系统块大小。ZFS池速度慢?也许你需要一个附加缓存。然而,确定你应该改变什么需要仔细审视这个系统。

我们将研究几个用于检查系统性能的FreeBSD工具。有了这些信息,我们将考虑如何解决性能问题。每个潜在的瓶颈都可以用适当的工具进行评估。FreeBSD不断变化,因此以后的系统可能会有新的调优选项和性能特性。阅读系统上的 tuning(7) 以获取当前的性能提示。

什么是正常的? 在本章中,有一个词你会一直被绊倒,那就是“不正常”(abnormal)。作为系统管理员,您应该知道系统的正常情况。这有点像艺术;你可能无法定义正常(normal),但当你看到异常(abnormal )时,你需要识别出来。当系统正常运行时,定期使用这些工具,这样你就可以很好地了解系统减速期间哪些结果不正常。注意你的硬件!

检查网络

如果您担心网络性能,请进行测量。查阅 netstat -mnetstat -s ,查找错误或内存或缓冲区不足的地方。这些是即时快照,但对于网络来说,你真的需要评估几分钟、几小时甚至几天的拥塞和延迟。网络团队可能有一个像Cacti、Zabbix或Graphite这样的工具来观察长期性能。向他们询问信息。将这些工具提供的功能与您的即时快照相结合。如果您的10千兆以太网每分钟的平均吞吐量仅为每秒5千兆比特,但您的瞬时测量显示频繁的峰值高达10千兆比特,那么您可能真的有突发连接。

一些网卡在轮询模式(polling mode)下可以更好地处理整个网络。轮询告诉网卡在帧到达时停止向操作系统发送帧,而是让操作系统每隔一段时间访问一次以收集帧。检查网卡的手册页,看看它是否支持轮询。使用 ifconfig(8) 启用和禁用轮询。

重负载网络可能受益于不同的拥塞控制算法。FreeBSD提供了多种TCP拥塞控制算法。在 /boot/kernel 中查找以 cc_ 开头的文件;这些是拥塞控制模块。每个都有一个手册页。

使用sysctl net.inet.tcp.cc 查看当前加载的拥塞控制算法。

New Reno算法是传统的拥塞控制算法。该系统上的拥塞控制核心模块包括CDG、CHD、CUBIC、DCTCP、HD、H-TCP和Vegas。H-TCP算法是专门为长距离、高带宽应用而设计的。让我们启用它。

我们现在在内核中提供了H-TCP。使用net.inet.tcp.cc.算法sysctl启用它。

最终,你无法在5磅的电路中容纳10磅的带宽。如果饱和的以太网使您的应用程序瘫痪,请关闭不必要的网络服务或增加更多带宽。

其他系统条件要复杂得多。首先检查 vmstat(8) 的问题所在。

使用 vmstat(8) 进行一般瓶颈分析

FreeBSD包括几个用于检查系统性能的程序。其中包括 vmstat(8)iostat(8)systat(1) 。我们将讨论 vmstat(8) ,因为我发现它非常有用;iostat(8) 类似于vmstat(8)systat(1) 以ASCII图形格式提供相同的信息。

使用 vmstat(8) 查看系统当前的虚拟内存统计信息。虽然输出需要习惯,但 vmstat(8) 非常擅长在小空间中显示大量数据。在命令提示符下键入 vmstat ,然后按照以下步骤操作。

vmstat将其显示分为六个部分:进程(procs)、memory、分页(page)、disksfaultscpu。我们将快速查看所有这些,然后详细讨论对调查性能问题最重要的部分。这条线表示系统运行整个时间的平均值。我们将在下一节中获得更多实时数据。

进程

vmstat(8)procs 标题下有三列。从技术上讲,vmstat计算线程而不是进程。无线程应用程序每个进程有一个线程,但您的多线程应用程序可以有更多的线程。

自启动以来,此主机平均有8个可运行线程,但没有等待I/O或内存的线程。如果您收到关于此主机速度慢的投诉,首先要检查的是处理器利用率。有人,比如说,从源代码构建FreeBSD只是为了为一本书的性能章节生成有趣的输出,而真实的人正试图在同一个系统上完成他们的工作吗?

内存

FreeBSD将内存分解为统一大小的块,称为页面(pages) 。当程序请求内存时,它会被分配一定数量的页面。页面的大小取决于硬件和操作系统,但会出现在 hw.pagesize sysctl中。在FreeBSD的i386和amd64平台上,一个页面是4KB。系统将每个页面视为一个整体——例如,如果FreeBSD必须将内存转换为交换,它会逐页进行。管理内存的内核线程称为pagedaemonmemory 部分有两列。

我们的示例输出使用1.3GB的RAM,有26GB的空闲空间。记忆不是问题。

Paging

page 部分显示了虚拟内存系统的工作强度。虚拟内存系统的内部运作是一门神秘的科学,我在这里不会详细描述。

将内存移入交换区并不是坏事,但持续恢复分页出的内存表明内存不足。具有较高的 frflt 值可能表示许多短寿命的进程,例如,启动许多其他进程的脚本或计划过于频繁的cron作业。或者也许有人一直在运行 make -j16 buildworld 。高 sr 可能意味着你没有足够的内存,因为页面守护进程一直在试图释放内存。分页守护进程通常每分钟运行一次左右,但较高的 sr 计数意味着您可能要做的工作比RAM所能容纳的更多。

磁盘

disks 部分按设备名称显示每个磁盘。显示的数字是每秒的磁盘操作数,这是确定磁盘处理负载能力的重要线索。您应该尽可能在不同的磁盘之间划分磁盘操作,并尽可能将它们安排在不同的总线上。如果一个磁盘明显比其他磁盘繁忙,并且系统有等待磁盘访问的操作,请考虑将一些频繁访问的文件从一个磁盘移动到另一个磁盘。高磁盘负载的一个常见原因是内核转储程序可以自行重启。例如,一个有缺陷的CGI脚本,每次有人点击链接时都会转储核心,这将大大增加您的磁盘负载。

如果您有很多磁盘,您可能会注意到它们并没有全部显示在vmstat显示器上。vmstat(8) 专为80列显示而设计,无法列出大型系统上的每个磁盘。但是,如果您有更宽的显示器并且不介意超过80列的限制,请使用 -n 标志设置要显示的驱动器数量。

Faults

故障本身并不坏;它们只是接收到系统陷阱和中断。当然,异常多的故障是不好的,但在解决这个问题之前,您需要知道系统的正常情况。

vmstat输出的第一行显示了自系统启动以来每秒的平均故障数。

自启动以来,此主机平均每秒有12次系统调用和212次上下文切换。这与系统正常工作时的情况相比如何?

CPU

最后,cpu部分显示了系统在执行用户任务(us)、系统任务(sy)和空闲时间(id)上花费了多少时间。top(1) 以更友好的格式显示相同的信息,但仅限于当前时间,而vmstat允许您查看随时间变化的系统利用率。

使用 vmstat

那么,你如何使用这些信息呢?首先检查前三列,看看系统在等待什么。如果你正在等待CPU访问(r 列),那么你的CPU性能不足。如果您正在等待磁盘访问(b 列),那么您的磁盘就是瓶颈。如果你正在交换(w 列),你的内存不足。使用其他列更详细地探讨这三种类型的短缺。

连续 vmstat

您可能更感兴趣的是随着时间的推移会发生什么,而不是系统性能的简短快照。使用 -w 标志和一个数字将其作为每隔几秒更新一次的持续显示运行。FreeBSD显示自上次更新以来的平均值,并不断更新计数器:

第一行仍然显示了自启动以来的平均值。然而,每五秒钟,末尾就会出现一条更新的行。您可以坐在那里,观察当计划作业开始或启动特定程序时,系统的性能会如何变化。完成后按CTRL-C。在这个例子中,进程总是在等待CPU时间(如 r 列中的8 秒堆栈所示),我们经常有一些东西在等待磁盘访问。

偶尔等待系统资源并不意味着您必须升级硬件;如果性能可以接受,不要担心。否则,你必须进一步考虑。最常见的罪魁祸首是存储系统。

磁盘 I/O

磁盘速度是一个常见的性能瓶颈,尤其是在旋转磁盘的情况下,但即使是基于闪存的存储也会变慢。必须反复等待磁盘活动完成的程序运行速度较慢。这通常被称为磁盘阻塞(blocking on disk),意味着磁盘正在阻止程序活动。唯一真正的解决方案是使用更快的磁盘、安装更多磁盘或重新安排加载。

虽然FreeBSD提供了多种工具来检查磁盘活动,但我最喜欢的是 gstat(8) ,所以我们将使用它。您可以在没有参数的情况下运行gstat,以显示所有每秒更新一次的磁盘和分区。但是,如果您有很多磁盘,这可能会生成一大堆零。我总是使用 -a 标志,这样 gstat(8) 就只显示有活动的磁盘。-p 标志对于查看整个磁盘也很有用,但我更喜欢按分区查看:

我们得到每个磁盘设备、切片和分区的行,以及每个磁盘设备的各种信息。gstat(8) 显示了各种各样的好东西,比如每秒读取次数(r/s)、每秒写入次数(w/s)、读取和写入的千字节数,以及一个看起来友好的 %busy 列。

忽略其中的大部分。其中一些,如繁忙百分比列,使用了草率的测量方法。FreeBSD开发人员选择磁盘性能而不是统计测量的准确性。然而,重要的是ms/r(每次读取的毫秒数)➊和ms/w(每次写入的毫秒数)➋。测量并监控它们。如果一个磁盘的活动非常高,但另一个磁盘处于空闲状态,可以考虑将该磁盘上的内容划分为多个磁盘或使用条带存储。或者,如果是你的笔记本电脑,考虑接受这是你的存储系统最快的速度。

一旦你确定了稀缺的系统资源,你就需要弄清楚是什么程序在消耗这些资源。我们需要其他工具。

使用 top(1) 查看CPU, Memory, 和 I/O

top(1) 工具提供了系统状态的良好概述,显示了有关CPU、内存和磁盘使用情况的信息。只需键入 top 即可获得系统性能数据的全屏显示。显示器每两秒钟更新一次,因此您可以获得接近实时的系统视图。即使将更新间隔更新为1秒,您仍然可能错过短暂的、消耗资源的进程。

top(1) 的输出被分成两半。上半部分给出基本的系统信息,而下半部分给出每个过程的数据。

包装得很紧,不是吗?top(1) 工具将尽可能多的数据塞进标准的80×25终端窗口或X终端。让我们把它拆开,学习如何阅读。我们将从上半部分开始,根据您使用的是UFS还是ZFS,上半部分看起来可能会有所不同。

UFS 和 top(1)

top(1) 上半部分的每台主机信息在ZFS和UFS主机之间略有不同,但我们将从UFS开始,然后解释差异。

PID 值

Unix机器上的每个进程都有一个唯一的进程ID(PID)。每当一个新进程启动时,内核都会为其分配一个比前一个进程大的PID。最后一个PID值是系统分配的最后一个进程ID。在前面的例子中,我们的最后一个PID是84111➊。创建的下一个进程将是84112,然后是84113,以此类推。观察这个数字,看看系统变化的速度有多快。如果系统运行PID的速度比平时快,则可能表明进程分叉失控或崩溃并重新启动。

【但是对于sysctl kern.randompid=1的设置,pid值应该不是按顺序增长的】

平均负载

load average ➋是一个有点模糊的数字,它提供了系统CPU负载量的粗略印象。负载平均值是等待CPU时间的线程的平均数量。(其他操作系统有不同的负载平均计算方法。)可接受的负载平均值取决于您的系统。如果数字异常高,你需要调查。一些主机的平均负载为3,而一些现代系统仍然很快,平均负载高得离谱。再说一次,对于这个主机来说,什么是正常的?

您将看到三个负载平均值。第一个(此处为0.09)是最后一分钟的负载平均值,第二个(0.21)是最后五分钟的负载,最后一个(0.20)是最后15分钟的负载。如果你的15分钟平均负荷很高,但1分钟平均负荷较低,那么你的主要活动高峰已经消退。另一方面,如果15分钟的值较低,但1分钟的平均值较高,则过去60秒内发生了一些事情,现在可能仍在继续。如果所有负载平均值都很高,则该情况已持续至少15分钟。

运行时长

第一行的最后一个条目是正常运行时间(uptime )➌,或者系统已经运行了多长时间。该系统已运行7天7小时58分钟,当前时间为14:41:09。我会让你来计算我启动这个系统的时间。

进程数

在第二行,您将找到有关系统上当前运行的进程的信息➍。运行的进程实际上正在工作——它们正在回答用户请求、处理邮件,或者做系统所做的任何事情。休眠过程正在等待来自一个或另一个源的输入;他们很好。你应该期待在任何时候都有相当多的睡眠过程。其他状态的进程通常在等待资源可用或以某种方式挂起。大量不休眠、不运行的进程暗示着问题。ps(1) 命令可以显示所有进程的状态。

进程类型

CPU states 行➎表示系统处理不同类型进程的可用CPU时间百分比。它显示了五种不同的进程类型:usernicesysteminterrupt(中断) 和 idle(空闲)。

user 进程是普通的日常程序,可能是由root运行的守护进程,也可能是由普通用户运行的命令,等等。如果它出现在 ps-ax 中,则它是一个用户进程。

nice 进程是用户进程,其优先级被故意操纵。我们将在第543页的“用美好重新排序”中详细介绍这一点。

system 值给出了FreeBSD运行内核进程和内核中用户区进程所花费的CPU时间的总百分比。这些包括虚拟内存处理、网络、写入磁盘、使用INVARIANTS和WITNESS进行调试等。

interrupt 值显示系统处理中断请求(IRQ)所花费的时间。

最后,idle 条目显示了系统什么都不做的时间。如果您的CPU经常有很低的空闲时间,您可能需要考虑重新安排作业或获得更快的处理器。

topSMP 在SMP系统中,top(1) 显示所有处理器的平均使用情况。您可能有一个处理器完全忙于编译某些内容,但如果另一个处理器处于空闲状态,top(1) 显示CPU使用率仅为50%。使用 -p 标志查看每个CPU(per-CPU)的统计数据。

内存

mem 行➏表示物理RAM的使用情况。FreeBSD将内存使用分为几个不同的类别。

活动内存(Active memory)是用户进程使用的内存总量。当程序结束时,它使用的内存会被放入非活动内存(inactive memory)中。如果系统再次运行此程序,它可以从内存而不是磁盘中检索软件。

可用内存(Free memory)完全未使用。它可能是从未被访问过的内存,也可能是进程释放的内存。这个系统有17MB的可用RAM。如果你的服务器已经运行了几个月,但仍然有可用内存,你可以考虑将一些RAM放在内存不足的机器上。

Laundry 的内存排队等待与其他存储(如磁盘)同步。

FreeBSD 11根据需要在非活动(inactive)、laundry和free类别之间洗牌(shuffles)内存,以维护可用内存池。非活动内存最容易转移到空闲池。当缓存内存不足,FreeBSD需要更多可用内存时,它会从非活动池中选取页面,验证是否可以将其用作可用内存,并将其移动到可用池中。FreeBSD试图将空闲页面的总数保持在sysctl vm.v_free_target 之上。

FreeBSD 12没有缓存,处理内存不足的情况略有不同。当可用内存不足时,页面守护进程(pagedaemon)会从非活动池中选取页面。如果该非活动页面需要同步到磁盘,它会被放置在 laundry 队列中,页面守护进程会尝试另一个非活动页面。测试主机是否需要更多RAM的一种方法是,页面守护进程是否从所有这些测试中积累了CPU时间。

在任一FreeBSD版本上,有空闲内存并不意味着你的系统有足够的内存。如果 vmstat(8) 显示您正在进行交换,那么您使用的物理内存比您拥有的要多。您可能有一个定期释放内存的程序。此外,FreeBSD会将一些页面从非活动状态转移到空闲状态,以保持一定程度的空闲内存。

FreeBSD将 wired 内存用于内核内数据结构,以及必须立即使用特定内存的系统调用。wired 内存从不交换或分页。ZFS使用的所有内存都是 wired

Swap

Swap 行➐给出了系统上可用的总交换量以及正在使用的交换量。交换是将磁盘驱动器用作额外内存。我们将在本章稍后更详细地介绍swap。

ZFS 和 top(1)

ZFS系统上 top(1) 的输出表面上看起来不同,但每个主机对内存的处理有重要差异。

Mem部分➊列出了UFS输出中熟悉的活动(Active)、非活动(Inactive)、LaundryWired 和空闲(Free)内存。

ARC行➋代表ZFS的高级替换缓存(Advanced Replacement Cache)。Total 字段显示整个ARC使用的内存量。在缓存使用的2312MB中,458MB位于最常用(Most Frequently Used —— MFU)缓存中,而1626MB位于最近使用(Most Recently Used —— MRU)缓存。您还将看到ZFS内部数据结构的较小条目,如匿名缓冲区(anonymous buffers —— Anon)、ZFS标头(Header)和非常有用的Other

ZFS压缩ARC➌,用充足的CPU时间换取稀缺的内存。您可以看到压缩和未压缩缓存数据使用的空间量。

ZFS对内存贪婪,只要其他人不需要它。ZFS积极缓存从磁盘读取和写入磁盘的数据。该主机有4096MB的RAM,ZFS声称有2312MB。您将看到此主机只有137MB的可用空间。如果程序请求内存,而系统没有可用内存,ZFS会将其部分缓存释放回系统。如果你看到有线内存级别很高,提醒自己ZFS占用的所有内存都会进入“wired”存储桶。

这是一种冗长的说法,“不要让明显的高ZFS内存使用率让你担心。”只有在主机开始分页和交换时才担心。

更有趣的是使用该内存的进程列表。

进程列表

最后,top(1) 列出了系统上的流程及其基本特征。表格格式旨在以尽可能小的空间呈现尽可能多的信息。每个过程都有自己的路线。

查看 top(1) 的输出,您可以了解系统在哪里花费时间。

并非主机上的每个进程都在积极工作。您可能有数十或数百个守护进程处于空闲状态。在运行 top(1) 显示器上输入 i 以切换显示空闲进程,或使用 -i 命令行标志。要显示单个线程,请切换 H 或添加 -H 标志。

默认情况下,top按加权CPU使用率对其输出进行排序。您还可以按优先级、大小和驻留内存对输出进行排序。在运行顶部显示中输入 o 。输入要排序的列的名称。这将有助于识别自我重要的程序或使用太多内存的程序。

top(1) 和 I/O

除了标准的CPU显示外,top(1) 还有一个I/O模式,显示哪些进程最活跃地使用磁盘。当 top(1) 运行时,按 m 进入I/O模式。显示器的上部仍然显示内存、交换和CPU状态,但下部变化很大。

当然,PID 是进程ID,USERNAME 列显示谁在运行进程。

VCSW代表自愿上下文切换;这是该进程将系统交给其他进程的次数。IVCSW 意味着非自愿的上下文切换(involuntary context switches),显示了内核告诉进程 “你现在完成了。是时候让其他人运行一段时间了。”的频率。

同样,READWRITE 显示系统从磁盘读取和写入磁盘的次数。FAULT 列显示了此进程从磁盘中提取内存页的频率,这导致了另一种磁盘读取。最后三列汇总在 TOTAL 列中。

PERCENT 列显示此进程正在使用的磁盘活动百分比。与 gstat(8) 不同,top(1) 将每个进程的利用率显示为实际磁盘活动的百分比,而不是可能的磁盘活动。如果只有一个进程访问磁盘,则 top(1) 显示该进程使用了100%的磁盘活动,即使它只发送了少量数据。gstat(8) 告诉您磁盘有多忙,top(1) 则告诉您是什么导致了磁盘活动以及将责任归咎于何处。在这里,我们看到进程ID 3064正在生成我们所有的磁盘活动。这是一个 tcsh(1) 进程,也被称为“某个用户的shell”。让我们追踪一下罪魁祸首。

更多top功能 top(1) 工具可以通过多种方式更改其显示。您可以查看特定用户的进程,包括或排除内核线程,排除空闲进程等。有关详细信息,请阅读手册页。

跟踪进程

在任何类Unix系统中,每个用户区进程都与其他进程有父子关系。当FreeBSD启动时,它通过启动 init(8) 并为其分配PID 1 来创建一个进程。此进程启动其他进程,例如 /etc/rc 启动脚本和处理登录请求的 getty(8) 程序。这些进程是进程ID 1的子进程。当您登录时,getty(8) 会启动 login(8) ,它会为您启动一个新的shell,使您的shell成为 login(8) 进程的子进程。您运行的命令要么是shell进程的子进程,要么是shell的一部分。您可以使用 -ajx 标志(以及其他标志)通过 ps(1) 查看这些父子关系。

在最左侧,我们有进程所有者的用户名,然后是进程的 PID 和父PID(PPID)。这是我们在这里看到的最有用的东西,但我们将简要介绍其他领域。

PGID 是进程组ID号,通常从其父进程继承。程序可以启动一个新的进程组,该新进程组的PGID将等于进程ID。进程组用于信号处理和作业控制。会话ID或 SID 是一组PGID,通常由单个用户或守护进程启动。进程不能从一个 SID 迁移到另一个SID。JOBC 给出作业控制计数,指示进程是否在作业控制下运行(即在后台)。

STAT 显示进程状态——确切地说,在运行 ps(1) 时进程正在做什么。进程状态非常有用,因为它“告诉”您进程是否空闲,它在等待什么等等。我强烈建议阅读ps(1)中关于进程状态的部分。

TT 列出了进程的控制终端。此列仅显示终端名称的末尾,例如 ttyv0v0ttyp0p0 。没有控制终端的进程用 ?? 表示。

TIME 列显示进程在用户区和内核中使用了多少处理器时间。

最后,我们看到父进程调用的 COMMAND 名称。方括号中的进程实际上是内核线程,而不是真正的进程。FreeBSD运行一大堆内核线程。

那么,这如何帮助我们追踪一个有问题的过程呢?在我们的 top(1) I/O示例中,我们看到进程3064几乎生成了我们所有的磁盘活动。运行 ps -ajx 查找此进程:

我们的兴趣流程归root所有,是 tcsh(1) 实例➍,正如top的I/O模式所说。但是,该命令正在 su(1) 下运行。使用PPID列检查此进程的父进程ID,您将看到进程3064是进程2990的子进程➌, 其是过程2989➋的子过程,两者均归root所有。进程2989是2981➊的子进程,然而,这是一个由真实用户运行的shell。您可能还会注意到,这些进程都是会话2981的一部分,这表明它们可能都在同一个登录会话中运行。TT 列显示 p1 ,这意味着用户已登录到 /dev/ttyp1 ,这是此计算机上的第二个虚拟终端。调查SID将阐明伯特认为他在做什么。

既然您已经了解了父子操作流程的工作原理,就可以作弊了。添加 -d 标志,如 ps -ajxd ,以显示与父进程一起排列在树中的进程。你会想要一个宽的终端。

系统经历短暂的总利用率是正常的。如果没有其他人使用该系统,也没有人抱怨性能,为什么不让这个用户运行他的工作呢?然而,如果这个过程给其他用户带来了问题,我们可以降低它的优先级,使用我们的root权限终止作业,或者拿着棒球棍出现在用户的隔间里。

分页和交换

使用交换空间本身并不坏。交换空间比芯片内存慢得多,但它确实有效,许多程序不需要将所有内容都放在RAM中才能运行。老的经验法则说,一个典型的程序花费80%的时间运行20%的代码。它的其余大部分代码涵盖了启动和关闭、错误处理等。您可以安全地将这些位从RAM中释放出来,同时对性能的影响最小。

交换已处理的缓存数据。一旦进程使用了交换,该交换就会一直使用,直到进程退出或从交换中调用内存。

交换使用是通过分页(paging)和交换(swapping)来实现的。分页是可以的;交换不是很好,但总比崩溃好。

分页

当FreeBSD将正在运行的程序的一部分移动到交换空间时,就会发生分页(paging )。分页实际上可以提高高负载系统的性能,因为未使用的位可以存储在磁盘上,直到需要为止——如果有的话。FreeBSD可以将实际内存用于实际运行的代码。一旦数据库启动并运行,您的系统是否会将数据库启动代码进行交换真的很重要吗?

交换

如果计算机没有足够的物理内存来存储在特定微秒内没有运行的进程,系统可以移动整个进程进行交换。当调度程序再次启动该进程时,FreeBSD会从swap中获取整个进程并运行它,可能会委托其他进程进行swap。

交换的问题是磁盘I/O活动会急剧增加,性能会急剧下降。由于处理请求需要更长的时间,因此系统上随时都有更多的请求。登录以检查问题只会使情况变得更糟,因为您的登录只是另一个过程。一些系统可以处理一定数量的交换,而在另一些系统上,情况很快就会恶化成死亡螺旋。

当你的CPU过载时,系统会变慢。当您的磁盘成为瓶颈时,系统会变慢。内存不足实际上会使您的计算机崩溃。如果你要换,你必须买更多的内存,否则就只能接受糟糕的表现。如果你被困在这个硬件中,无法购买更多内存,你可能会得到一个非常快的SSD,并将其用于交换。

vmstat(8) 的输出显示了任何时候交换的进程数。

性能调整

FreeBSD将最近访问的数据缓存在内存中,因为一次又一次地从磁盘读取惊人数量的信息。可以非常快速地访问物理内存中缓存的信息。如果系统需要更多内存,它会转储最旧的缓存块,以支持新数据。UFS和ZFS使用不同的方法来决定缓存什么,但该原则通常适用。

今天早上启动桌面时,我启动了Firefox,这样我就可以检查我的RSS提要了。磁盘工作了一两分钟才读入程序。然后我关闭了浏览器,这样我就可以专注于我的工作,但FreeBSD把Firefox留在了缓存中。如果我重新启动Firefox,FreeBSD将从内存中提取它,而不是打扰磁盘,这大大缩短了它的启动时间。不过,如果我启动了一个需要大量内存的进程,FreeBSD会从缓存中转储web浏览器来支持新程序。

如果你的系统运行良好,你至少有几兆字节的可用内存。sysctls vm.v_free_targethw.pagesize 告诉你FreeBSD认为你的系统需要多少可用内存。如果你一直有比这两个系统多的可用内存,那么你的系统并没有得到充分的利用。例如,在我的邮件服务器上,我有:

我的系统希望至少有5350×4096=21913600字节(约22MB)的可用内存。如果不是因为内存不足给我带来了根深蒂固的情感创伤,我可能会毫不犹豫地从台式机上损失1GB的内存。

内存使用

如果主机的缓存或缓冲区中有很多内存,或者ARC已经吃掉了所有的RAM,那么它就不会出现内存短缺。你可能会充分利用更多的内存,但这并不是绝对必要的。如果您的可用内存较低,但有大量活动和非ZFS wired 内存,则您的系统正在吞噬RAM。添加内存可以让您利用缓冲区缓存。

如果pagedaemon继续运行,增加vmstat输出中的 sr 字段,则内核正在努力提供内存。主机很可能内存不足。然而,一旦主机开始使用交换,这种内存短缺就不再是假设。这可能不坏,但这不是理论上的。

交换空间使用

交换空间有助于暂时弥补RAM短缺。例如,如果你正在取消对一个巨大文件的标记,你可能会很容易地消耗掉所有的物理内存,并开始使用虚拟内存。当交换足够时,不值得为这种偶尔的任务购买更多的RAM。如果内存不足的服务器运行一个从未被调用的守护进程,那么该守护进程最终将大部分或完全被替换为正在执行工作的进程。

当系统不断地将数据移入和移出交换区时,只需要担心交换空间的使用。

简而言之,交换空间就像葡萄酒。偶尔喝一两杯不会伤害你,甚至可能是个不错的选择。不停地敲打瓶子是个问题。如果你必须不断使用swap,可以考虑一个非常快速但耐用的SSD。

CPU使用

一个处理器一秒钟只能做这么多事情。如果你运行的任务超过了CPU的处理能力,请求将开始备份,你将开发一个处理器积压(backlog),系统将变慢。简而言之,这就是CPU的使用情况。如果性能不可接受,并且 top(1) 显示您的CPU一直徘徊在100%左右,那么CPU利用率可能是您的问题。虽然新硬件当然是一种选择,但你确实有其他选择。例如,调查系统上运行的进程,看看它们是否都是必要的。是否有初级系统管理员安装了SETI@Home客户端用你的空闲CPU周期寻找外星人?比特币矿工怎么样?有什么东西曾经很重要,但现在不再重要了吗?找到并关闭那些不必要的进程,并确保它们在下次系统启动时不会启动。

如果您有非常具体的需求,例如将某些处理器专用于特定任务,请考虑 cpuset(1) 。对于大多数用户来说,这太过分了,但高性能应用程序可能会充分利用专用处理器。

完成后,再次评估您的系统性能。如果你仍然有问题,试着重新安排或重新确定优先级。

重新安排

重新安排(rescheduling)比重新确定优先级(reprioritizing)更容易;这是一种相对简单的平衡系统进程的方法,这样它们就不会垄断系统资源。如第20章所述,您和您的用户可以使用 cron(8) 安排程序在特定时间运行。如果你有用户在特定时间运行大量作业,你可以考虑使用 cron(1) 在非工作时间运行它们。通常,诸如每月账单数据库搜索之类的工作可以在下午6点到早上6点之间运行,没有人会关心——财务部门只希望在每月第一天早上8点获得数据,这样他们就可以完成上个月的会计工作。同样,您可以将 make buildworld && make buildkernel 安排在凌晨1点。

以 Niceness 重新排序

如果重新安排不起作用,你只能重新安排优先级(reprioritizing),这可能会有点棘手。在重新确定优先级时,您可以告诉FreeBSD更改给定流程的重要性。例如,您可以在繁忙时间运行一个程序,但只有在没有其他东西想要运行的时候。你刚刚告诉那个节目要好,让位给其他程序。

进程越好,它所需的CPU时间就越少。默认的niceness为 0 ,但niceness从 20 (非常好)到 -20 (根本不好)。这似乎有些倒退;你可以说,更高的数字意味着更高的优先级。然而,这将导致语言问题;将这个因素称为“自私(selfishness)”或“偏执(crankiness)”而不是“善良(niceness)”在当时似乎不是一个好主意。

top(1) 工具显示了进程优先级的PRI列。FreeBSD根据各种因素计算进程的优先级,包括友好性,并尽可能先运行高优先级进程。正确性会影响优先级,但您不能直接编辑优先级。

如果你知道你的系统正在满负荷或接近满负荷运行,你可以选择运行一个带有 nice(1) 的命令来为进程分配niceness。使用 nice -n 和命令前面的nice值指定nicess。例如,要在nice 15开始一个非常自私的 make buildworld ,你可以运行:

只有root可以为程序分配负nicess,如 nice -n -5 。例如,如果你想滥用你的超级用户权限尽快完成编译,请使用负nicness:

NICE VS.TCSH tcsh(1) shell内置了一个nice命令。内置的nice使用 renice(8) 语法,这与 nice(1) 不同。我确信除了烦人的tcsh用户之外,还有其他原因,但目前我无法理解这个道理。要使用nice(1) ,请使用完整路径 /usr/bin/nice

通常,当你启动一个命令时,你没有奢侈地告诉它要友好,但当你知道它正在吸收你所有的系统容量时,你必须改变它的友好性。您可以使用 renice(8) 按进程ID或所有者重新确定正在运行的进程的优先级。要更改进程的nicness,请使用新nicness和PID作为参数运行renice

在我的职业生涯中,我经营过几家日志主机。除了一般的syslog服务外,它们通常还运行几个流捕获、Nagios和其他关键网络感知系统的实例。我经常使用web界面来实现这一切,并允许其他人访问我的日志。如果我发现web服务器上的间歇性负载干扰了我的网络监控或 syslogd(8) 服务器,我必须采取行动。重新设置web服务器会使客户端运行得更慢,但这比减慢监控速度要好。使用 pgrep(1) 查找web服务器的PID

Boom!FreeBSD现在在其他进程之后处理web请求。这让该服务的用户非常恼火,但由于这是我的服务器,我已经很恼火了,没关系。

要还原用户拥有的每个进程,请使用 -u 标志。例如,为了使我的流程比其他人的流程更重要,我可以这样做:

1001 是我在这个系统上的用户ID。同样,我这样做可能有一个很好的理由,除了我对个人权力的需要。同样,如果那个吞噬了我所有处理器时间的用户坚持要表现得很难,我可以让他的流程变得非常非常好,这可能会解决其他用户的抱怨。如果你有一个大型的后台数据库作业,让用户运行该作业可以让前台工作正常进行。

Niceness 只影响CPU使用率。它对磁盘或网络活动没有影响。

瓶颈洗牌 每个系统都有瓶颈。如果你消除了一个瓶颈,性能就会提高,直到遇到另一个瓶颈。系统的性能受到计算机中最慢组件的限制。例如,web服务器经常是网络绑定的,因为系统中最慢的部分是互联网连接。如果您将千兆上行链路升级到2.4Gb/s OC-48,系统将以其他组件允许的最快速度分发其站点。管理层经常要求的假设性“消除瓶颈”实际上是“消除干扰您正常工作负载的瓶颈”

现在您可以查看系统问题了,让我们学习如何听到系统试图告诉您的内容。

状态邮件

FreeBSD通过 periodic(8) 每天、每周和每月运行维护作业。这些作业执行基本的系统检查,并将更改、需要注意的项目和潜在的安全问题通知管理员。每个计划作业的输出每天都会邮寄到本地系统上的根帐户。了解系统正在做什么的最简单方法是阅读这封邮件;许多像您一样非常忙碌的系统管理员共同协作,使这些消息变得有用。虽然你可能会收到很多这样的消息,但只要有一点经验,你就会学会如何浏览报告,只寻找关键或不寻常的变化。

日报、周报和月报的配置在 periodic.conf 中控制,如第20章所述。

您可能不想每天以root身份登录所有服务器只是为了阅读电子邮件,因此将root的邮件从每台服务器转发到一个集中邮箱。如第20章所述,在 /etc/mail/aliases 中进行此更改。

我建议禁用这些作业的唯一地方是在嵌入式系统上,应该通过其他方式对其进行管理和监控,例如您的网络监控系统。在这样的系统中,禁用 /etc/crontab 中的 periodic(8) 检查。

虽然这些每日报告很有用,但它们并不能说明全部情况。日志提供了更完整的图片。

使用syslogd进行日志记录

FreeBSD日志系统非常有用。任何类Unix操作系统都允许您记录几乎任何级别的细节。虽然您可以找到最常见系统资源的默认系统日志挂钩,但您可以选择满足您需求的日志配置。几乎所有程序都与日志守护进程 syslogd(8) 集成。

syslog协议通过消息工作。程序发送单个消息,syslog守护进程syslogd(8)捕获并处理这些消息。syslogd(8) 根据其设施和优先级处理每条消息,这两个级别都是客户端程序分配给消息的。您必须了解管理系统日志的设施和级别。

设施

设施(facility)是指示日志条目的来源的标签。这是一个任意的标签,只是一个用于将一个程序与另一个程序排序的文本字符串。在大多数情况下,每个需要唯一日志的程序都使用唯一的工具。许多程序或协议都有专用于它们的设施——例如,FTP是一种非常常见的协议,syslogd(8) 有一个专门的设施。syslogd还支持各种通用设施,您可以将其分配给任何程序。

以下是标准设施及其使用的信息类型。

虽然大多数程序都有合理的默认值,但作为系统管理员,你的工作是管理哪些程序登录到哪个设施。

级别

日志消息的级别(level)表示其相对重要性。虽然程序将所有日志数据发送到syslogd,但大多数系统只记录syslogd接收到的重要内容,并丢弃其余内容。当然,一个人的琐事是另一个人的重要数据,这就是级别发挥作用的地方。

syslog协议提供八个级别。使用这些级别告诉syslogd要记录什么和丢弃什么。这些级别从最重要到最不重要依次为:

通过将级别与优先级相结合,您可以对消息进行非常狭义的分类,并根据您的需求对每条消息进行处理。

使用 syslogd(8) 处理消息

syslogd(8) 守护进程从网络捕获消息,并将其与 /etc/syslog.conf 中的条目或 /etc/syslog.d/ 中的文件进行比较。/etc/syslog.d/ 中的文件用于您自己的条目和附加程序,而 /etc/syslog.conf 用于集成系统程序。Syslogd只读取以 .conf 结尾的 /etc/syslog.d/ 文件。这两个文件的格式相同,但为了清楚起见,我将参考 /etc/syslog.conf 。该文件有两列;第一个描述了日志消息,可以按设施和级别,也可以按程序名称。第二个命令告诉 syslogd(8) 当日志消息与描述匹配时要做什么。例如,查看默认 syslog.conf 中的此条目:

这个消息告诉 syslogd(8) ,当它从邮件设施接收到信息级别或更高级别的消息时,应该将该消息附加到 /var/log/maillog

记录器不会记录到不存在的文件。在重新启动 syslogd(8) 之前,使用 touch(1) 创建日志文件。

通配符

您还可以使用通配符作为信息源。例如,此行记录来自 mail 设施的每条消息:

要记录来自任何地方的所有内容,请取消注释 all.log 条目并创建 /var/log/all.log 文件:

这很有效,但我觉得它信息量太大,没有任何实际用途。您会发现自己使用复杂的 grep(1) 语句菊花链连接在一起,以查找最简单的信息。此外,这将包括各种私人数据。

排除信息

使用none级别从日志中排除信息。例如,在这里,我们从全包日志中排除 authpriv 信息。分号允许您在一行中组合条目:

比较

您还可以在 syslog.conf 规则中使用比较运算符<(小于)、=(等于)和>(大于)。虽然syslogd默认记录指定级别或更高级别的所有消息,但您可能只希望包含一系列级别。例如,您可以将信息级别及以上的所有内容记录到主日志文件中,同时将其余内容记录到调试文件中:

mail.info 条目与发送到信息级别及以上邮件设施的所有日志消息相匹配。第二行仅匹配具有精确 debug 级别的消息。您不能使用简单的 mail.debu ,因为调试日志将复制上一个日志的内容。这样,您就不必对基本邮件日志的调试信息进行排序,也不必对邮件传输信息进行排序以获得调试输出。

当地设施

许多程序都提供通过syslog进行日志记录。其中大部分可以设置为您选择的设施。各种当地设施都是为这些项目预留的。例如,默认情况下,dhcpd(8) (见第20章)会记录到设施 local7 。在这里,我们捕获这些消息并将其发送到自己的文件中:

如果您用完了 local 设施,您可以使用系统未使用的其他设施。例如,我曾经在没有 uucp 服务的网络上的繁忙日志服务器上使用过 uucp 设施。

按程序名称记录

如果你没有设施,你可以使用该程序的名称作为匹配词。名称条目需要两行:第一行包含带有前导感叹号的程序名称,第二行设置日志记录。例如,FreeBSD使用它来记录 ppp(8) 信息:

第一行指定程序名,第二行使用通配符告诉 syslogd(8) 将所有内容绝对附加到文件中。

这个 !programname 语法会影响其后的所有行,因此您必须将其放在 syslogd.conf 中的最后一行。您可以在 /etc/syslog.d 文件中安全地使用它,而不必担心影响其他条目。

记录到用户会话

当您登录到用户时,到达的任何消息都会显示在该用户的屏幕上。要登录到用户会话,请列出以逗号分隔的用户名作为目标。要向所有用户的终端写入消息,请使用星号(*)。例如,默认的 syslog.conf 包含以下行:

这表示任何紧急级别的消息都将出现在所有用户的终端上。由于这些信息通常以某种方式说“再见”,这是恰当的。

向程序发送日志消息

要将日志消息定向到程序,请使用管道符号(|):

记录到日志主机

我的网络习惯性地有一个日志主机,它不仅处理FreeBSD盒子,还处理思科路由器和交换机、其他Unix盒子以及任何讲syslog的设备。这大大减少了系统维护并节省了磁盘空间。每条日志消息都包含主机名,因此您以后可以轻松地对其进行排序。

使用 at 符号(@)向另一台主机发送消息。例如,以下行将本地syslog接收到的所有内容转储到我网络上的日志主机:

目标主机上的 syslog.conf 决定了这些消息的最终目标。

在日志主机上,您可以按日志消息来源的主机分隔日志。使用加号(+)和主机名表示以下规则适用于此主机:

将通用规则放在 syslog.conf 的顶部。每个主机的规则应该放在底部附近或单独的 syslog.d 文件中。

日志记录重叠

日志守护进程不会以第一次匹配或最后一次匹配为基础进行日志记录;相反,它根据每个匹配规则进行日志记录。这意味着您可以轻松地在多个不同的日志中创建一条日志消息。考虑以下日志配置片段。

几乎所有级别通知或更多级别的消息都记录在 /var/log/messages 中。不过,任何具有 authpriv功能的内容都会被故意排除在此日志之外。我们让DHCP服务器记录到 /var/log/dhcp 。这意味着任何通知级别或更高级别的DHCP消息都将记录到 /var/log/messages/var/log/dhcpd 中。我不喜欢这样;我只希望我的DHCP消息在 /var/log/dhcpd 中。我可以按照 authpriv 的例子,使用 none 工具故意从 /var/log/messages 中排除DHCP消息:

我的 /var/log/messages syslog配置经常增长很长时间,因为我逐步从中排除了每个本地设施,但没关系。

空格和制表符 传统的类Unix操作系统要求 syslog.conf 中的列之间有制表符,但FreeBSD允许您使用空格。如果在不同操作系统之间共享相同的 syslog.conf ,请确保仅使用制表符。

syslogd 自定义

FreeBSD默认运行syslogd,它可以直接用作日志主机。您可以通过使用命令行标志自定义其工作方式。您可以在命令行或 rc.conf 中将标志指定为 syslogd_flags

允许的日志发送者

您可以精确指定 syslogd(8) 从哪些主机接受日志消息。这可能很有用,这样你就不会最终接受互联网上随机人的日志。虽然向您发送大量日志可用于填充硬盘以备攻击,但这更有可能是配置错误的结果。无论如何,您的日志服务器都应该受到防火墙的保护。使用-a标志指定可以向您发送日志消息的IP地址或主机网络,如这两个(互斥)示例所示:

虽然 syslogd(8) 也接受DNS主机名和域名作为此限制,但DNS是一种完全不合适的访问控制机制。

您可以通过指定 -s 标志(FreeBSD的默认值)完全禁用接受来自远程主机的消息。如果改用 -sssyslogd(8) 还将禁用向远程主机发送日志消息。使用 -sssyslogd(8)sockstat(1)netstat(1) 中显示的网络感知进程列表中删除。虽然这个半开放的UDP套接字是无害的,但如果 syslogd(8) 根本不连接到网络,有些人会感觉更好。

附加到单个地址

syslogd(8) 默认连接到系统具有的每个IP地址上的UDP端口514。您的jail服务器需要syslogd,但jail机器只能运行绑定到单个地址的守护进程。使用 -b 标志强制 syslogd(8) 连接到单个IP:

其他日志套接字

syslogd(8) 可以通过Unix域套接字以及网络接受日志消息。它的标准位置是 /var/run/log 。但是,系统上的chrooted进程无法访问此位置。如果你想让这些chrooted进程运行,你必须配置它们通过网络登录,或者为它们提供一个额外的日志套接字。为此使用 -l 标志,并指定附加日志套接字的完整路径:

named(8)ntpd(8) 程序随FreeBSD一起提供,通常是chrooted的。如果您通过 rc.conf chroot这些程序,/etc/rc.d/syslogd 足够智能,可以添加适当的syslogd套接字。

详细日志记录

使用详细模式(-v)进行日志记录会打印本地日志中写入的每条消息的数字功能和级别。使用双重详细日志记录会打印设施和级别的名称,而不是数字:

这些是我最常考虑的旗帜。阅读 syslogd(8) 以获取完整的选项列表。

日志文件管理

日志文件会增长,在修剪它们之前,您必须决定它们可以增长多大。标准的方法是通过原木轮换。当日志轮换时,最旧的日志将被删除,当前日志文件将被关闭并赋予新名称,并为新数据创建一个新的日志文件。FreeBSD包括一个基本的日志文件处理器 newsyslog(8) ,它还可以压缩文件、重启守护进程,并通常处理日志文件洗牌的所有常规任务。cron(1) 每小时运行一次 newsyslog(8)

newsyslog(8) 运行时,它读取 /etc/newsyslog.conf/etc/newsyslog.conf.d/ 中的文件。/etc/newsyslog.conf 文件用于核心系统功能,而 /etc/newsyslog.conf.d/ 中的文件用于附加软件。newsyslog程序尝试将 /etc/newsyslog.conf.d/ 中的任何文件解析为newsyslog配置。两者都使用相同的格式,因此为了清楚起见,我们将参考 newsyslog.confnewsyslog.conf 中的每一行都给出了轮换一个日志文件的条件。如果满足旋转日志的条件,则会旋转日志并采取其他适当的行动 /etc/newyslog.conf 每个日志文件使用一行;每行有七个字段,如下所示:

让我们依次检查每个字段。

日志文件路径

每行的第一个条目(示例中为 /var/log/ppp.log )是要处理的日志文件的完整路径。

所有者和群组

第二个字段(在我们的示例中为 root:network )列出了旋转文件的所有者和组,用冒号分隔。此字段是可选的,在许多标准条目中都不存在。

newsyslog(8) 可以更改旧日志文件的所有者和组。默认情况下,日志文件归root用户和wheel组所有。虽然更改所有者并不常见,但您可能需要在多用户计算机上使用此功能。

您还可以选择仅更改所有者或仅更改组。在这些情况下,您可以使用仅在一侧有名称的冒号。例如,:www 将组更改为www,而 mwlucas: 将文件的所有权授予我。

权限

第三个字段(在我们的示例中为 640)以标准Unix三位数表示法给出了权限模式。

计数

此字段指定 newsyslog(8) 应保留的最旧的旋转(rotates )日志文件。newsyslog(8) 按从最新到最旧的顺序对存档日志进行编号,从最新的日志开始为日志0。例如,/var/log/messages 的默认count5 ,您将找到以下消息日志:

你们中那些能数数的人会认识到,这会使一周的日志有六个存档,而不是五个,再加上当前的日志文件。一般来说,日志太多总比太少好;但是,如果磁盘空间紧张,删除一两个额外的日志可能会为您争取时间。

大小

第五个字段(在我们的示例中为 100 )是文件大小,单位为千字节。当 newsyslog(8) 运行时,它会将此处列出的大小与文件的大小进行比较。如果文件大于此处给出的大小,newsyslog(8) 将旋转文件。如果您不希望文件大小影响文件旋转的时间,请在此处加上星号。

时间

到目前为止,这似乎很容易,对吧?第六个字段,旋转时间,改变了这一点。时间字段有四种不同的合法值类型:星号、数字和两种不同的日期格式。

如果您根据日志大小而不是年龄进行轮换,请在此处加上星号。

如果你在这个字段中输入一个纯裸数字,newsyslog(8) 会在数小时后旋转日志。例如,如果你想让日志每24小时轮换一次,但不关心具体发生的时间,请在此处输入24。

日期格式稍微复杂一些。

ISO 8601 时间格式

任何以@符号开头的条目都是受限的ISO 8601时间格式。这是 newsyslog(8) 在大多数类Unix系统上使用的标准;这是麻省理工学院原始 newsyslog(8) 中使用的时间格式。受限的ISO 8601有点迟钝,但每个类Unix操作系统都支持它。

受限制的ISO8601格式的完整日期是14位数字,中间有一个 T 。前四位数字是年份,下两位是月份,下两位数是月份中的某一天。T 插入中间,作为一种小数点,将一天的整数与一天的小数点分隔开来。接下来的两位数字是小时,接下来的两分钟,最后两秒。例如,2008年3月2日晚上9:15分8秒的日期在受限的ISO 8601中表示为 20080302T211508

虽然受限的ISO 8601中的完整日期相当简单,但如果不列出整个日期,就会产生混淆。您可以选择仅指定T附近的字段,将更远的字段留空。空白字段是通配符。例如,1T 匹配每月的第一天。4T00 匹配每月第四天的午夜。T23 匹配每天的第23小时,即晚上11点。newsyslog.conf 的时间为 @T23,日志每天晚上11点轮换。

cron(1) 一样,您必须详细指定时间单位。例如,@7T ,即每月的第七天,在每月的第7天每小时旋转一次日志。毕竟,它整天都在比赛!@7T01 的时间将在每月的第7天凌晨1点旋转日志,这可能更可取。然而,你不需要超过一个小时的详细信息,因为newsyslog(8) 每小时只运行一次。

FreeBSD特定时间

受限的ISO 8601时间系统不允许您轻松指定每周作业,也不可能指定每月的最后一天。这就是为什么FreeBSD包含一种时间格式,可以让你轻松执行这些常见任务。任何带有前导现金符号($)的条目都是以FreeBSD特定的月-周-日(month week day)格式编写的。

此格式使用三个标识符:M(月中的第几天)、W(一周中的第一天)和 H(一天中的小时)。每个标识符后面都有一个数字,表示特定的时间。小时数从0到23,而天数从0(星期日)到6(星期六)。一个月的天数从1开始向上,L 表示该月的最后一天。例如,要在每月五号中午轮换一根原木,我可以使用$M5H12 。要在每月最后一天的晚上10点开始月末日志会计,请使用 $MLH22

按大小和时间旋转 您可以在给定时间旋转日志,当它们达到一定大小时,或两者兼而有之。如果同时指定大小和时间,则只要满足任一条件,日志就会旋转。

标志

flags 字段指示了日志旋转时要采取的任何特殊操作。这通常告诉 newsyslog(8) 如何压缩日志文件,但您也可以在进程的日志从它们下面旋转出来时向进程发出信号。

日志文件格式和压缩

日志可以是文本或二进制文件。

二进制文件只能以非常特定的方式写入。newsyslog(8) 用一条“logfile turn over”消息启动每个新日志,但将此文本添加到二进制文件会损坏它。B 标志告诉 newsysog(8) 这是一个二进制文件,不需要此头。

其他日志文件是以纯旧ASCII文本编写的,newsyslog(8) 可以而且应该在文件顶部添加一条带时间戳的消息,指示日志何时被旋转。如果您使用的是UFS,压缩旧日志文件可以节省大量空间。-J 标志告诉newsysog(8)使用 bzip(1) 压缩档案;-Z 标志指定gzip压缩;-X 标志,xz(1)-Y 标志,压缩中的新热度,zstd(1)

不过,如果你使用的是ZFS,文本日志文件会在数据集层与其他所有可压缩文件一起压缩。无论如何,您都可以以传统方式压缩日志文件,但这样做没有任何好处。此外,在查看文件之前,您需要手动解压缩文件。让ZFS为您处理压缩。

特殊日志文件处理

当它创建和旋转日志文件时,newsyslog(8)可以执行一些特殊任务。以下是最常见的;您可以在 newsyslog.conf(5) 中阅读其他内容。

也许您有许多类似的日志文件,希望以相同的方式处理。-G 标志告诉newsyslog,行开头的日志文件名实际上是一个shell glob,所有与表达式匹配的日志文件都将以这种方式旋转。要了解shell表达式,请阅读 glob(3) 。带上阿司匹林。

如果newsyslog不存在,您可能希望它创建一个文件。为此使用 -C 标志。syslogd程序不会记录到不存在的文件。

-N 标志明确地告诉newsyslog在旋转此日志时不要发送信号。

最后,当您不需要这些标志时,使用连字符(-)作为占位符。它在这里创建了一个列,这样你就可以有一个pidfile路径。

Pidfile

下一个字段是pidfile路径(在我们的示例中没有显示,但可以查看 /etc/newsyslog.conf 中的几个示例)。pidfile记录程序的进程ID,以便其他程序可以轻松查看它。如果你列出pidfile的完整路径,newsyslog(8) 会在程序旋转日志时向该程序发送 kill -HUP 。这指示进程关闭其日志文件并重新启动。并非所有进程都有pidfiles,也并非所有程序在旋转日志时都需要这种特殊的注意。

信号

大多数程序在 SIGHUP上执行日志文件旋转,但有些程序在旋转日志时需要特定的信号。您可以在pidfile后面的最后一个字段中列出所需的确切信号。

示例 newsyslog.conf 条目

让我们把所有这些放在一起,做成一个最坏的情况,你必须做的例子。数据库日志文件需要在每月最后一天的晚上11点轮换。数据库文档规定,您必须在轮换时向服务器发送中断信号(SIGINT,或信号号2)。您希望存档的日志归用户 dbadmin 所有,并且只能由该用户查看。你需要六个月的日志。此外,日志是二进制文件。您的 newsyslog.conf 行看起来像这样:

这是一个蓄意卑鄙的例子;在大多数情况下,只需输入文件名和旋转(rotation)条件,即可完成。

FreeBSD 和 SNMP

电子邮件报告很好,但很笼统,日志很难分析长期趋势。网络、服务器和服务管理的行业标准是简单网络管理协议(Simple Network Management Protocol —— SNMP)。许多不同的供应商支持SNMP作为从网络上的许多不同设备收集信息的协议。FreeBSD包括一个SNMP代理 bsnmpd(8) ,它不仅提供标准的SNMP功能,还提供了FreeBSD特定功能的可见性。

FreeBSD的 bsnmpdBegemot SNMPD 的缩写)是一个专为可扩展而设计的极简主义SNMP代理。所有实际功能均通过外部模块提供。FreeBSD包括用于标准网络SNMP功能的bsnmpd模块和用于特定FreeBSD功能的模块,如PF和 netgraph(4)bsnmpd(8) 提供了一个基础,每个人都可以构建一个只做他们需要的事情的SNMP实现,而不是试图为所有人提供一切。

SNMP 101

SNMP在经典的客户端-服务器模型上工作。SNMP客户端,通常是某种管理工作站或监控服务器,通过网络向SNMP服务器发送请求。SNMP服务器,也称为代理(agent),从本地系统收集信息并将其返回给客户端。FreeBSD的SNMP代理是 bsnmpd(8)

SNMP代理还可以向SNMP服务器发送更改请求。如果系统配置正确(或不正确,取决于您的观点),您可以通过SNMP发出命令。这种“写”配置最常用于路由器、交换机和其他嵌入式网络设备。大多数类Unix操作系统都有一个命令行管理系统,通常不接受通过SNMP的指令。通过SNMP编写系统配置或发出命令需要仔细设置,并引发各种安全问题;这是整本书的一个很好的主题。据我所知,没有一个系统管理员愿意通过SNMP管理他们的系统。考虑到所有这些,我们将特别关注只读SNMP。

除了让SNMP服务器应答来自SNMP客户端的请求外,客户端还可以将SNMP陷阱传输到网络上其他地方的陷阱接收器。SNMP代理根据服务器上的特定事件生成这些陷阱。SNMP陷阱与 syslogd(8) 消息非常相似,除了它们遵循SNMP要求的非常特定的格式。FreeBSD目前不包括SNMP陷阱接收器;如果需要,请查看net-snmp( net-mgmt/net-snmps )中的snmptrapd(8)

SNMP MIBs

SNMP通过管理信息库(management information base —— MIB)管理信息,MIB是一种树状结构,包含ASN.1格式的分层信息。我们之前见过MIB树的一个例子:第6章中讨论的 sysctl(8) 接口。

每个SNMP服务器都有一个可以从本地计算机提取的信息列表。服务器将这些信息位排列成层次树。每个SNMP MIB树都有非常通用的主要类别:网络、物理、程序等,每个类别都有更具体的细分。把这棵树想象成一个组织良好的文件柜,每个抽屉里都有特定的信息,抽屉里的文件里有特定的事实。同样,最上面的MIB包含其下方的MIB列表。

MIB可以按名称或编号引用。例如,以下是从示例系统中提取的MIB:

这个MIB中的第一个术语“接口”向我们展示了我们正在研究这台机器的网络接口。如果这台机器没有接口,第一类甚至不会存在。ifTable 是接口表,或系统上所有接口的列表。ifEntry 显示了一个特定的接口,ifDescr 意味着我们正在查看这个接口的描述。该MIB可以概括为:“此机器上的接口1称为em0。”

MIB可以表示为数字,大多数SNMP工具都是在数字MIB中本地工作的。大多数人更喜欢单词,但你可怜的大脑必须能够处理其中任何一个。MIB浏览器可以为您在SNMP MIB的数字和单词形式之间进行转换,或者您可以安装 net-mgmt/net-snmp 并使用snmptranslate(1),但现在,请相信我。前面的示例可以转换为:

用文字表示,这个MIB有5个术语,用点分隔。用数字表示,MIB有11个部分。如果它们应该是同一件事,那看起来就不太对了。什么给?

数字MIB较长,因为它包含默认的 .1.3.6.1.2.1 ,即 .iso.org.dod.internet.mgmt.mib-2 。这是互联网上使用的MIB的标准子集。绝大多数SNMP MIB(但不是全部)前面都有这个前导字符串,所以没有人再费心把它写下来了。

如果你处于这种困难的情绪中,你甚至可以把单词和数字混在一起:

此时,国际条约允许你的同事用干草叉和燃烧的火炬开车送你离开大楼。选择一种表达MIB的方法并坚持下去。

MIB定义和MIB浏览器

MIB是根据非常严格的语法定义的,并记录在MIB files中。每个SNMP代理都有自己的MIB文件;bsnmpd位于 /usr/share/snmp 中。这些文件是非常正式的明文。虽然你可以用大脑阅读和解释它们,但我强烈建议将它们复制到工作站并安装MIB浏览器,这样你就可以更容易地理解它们。

MIB浏览器解释MIB文件,并以完整的树状形式呈现它们,包括树的每个部分的定义和每个单独MIB的描述。一般来说,MIB浏览器允许您输入特定的MIB,并显示该MIB的数字和单词定义,同时向SNMP代理查询该MIB的状态。

如果您的工作站上有FreeBSD(或较小的Unix),请使用 mbrowse(net-mgmt/mbrowse)浏览MIB。如果您不想使用图形界面进行SNMP工作,请查看net-snmp(net-mgmt/net-snmp)以获取各种命令行SNMP客户端工具。

SNMP 安全

许多安全专家表示,SNMP实际上代表“安全:不是我的问题!”(Security: Not My Problem!)这是相当不友好的,但非常真实。SNMP只需要在受信任网络的防火墙后使用。如果您必须在裸互联网上使用SNMP,请使用数据包过滤来防止公众查询您的SNMP服务。SNMP代理在UDP端口161上运行。

更常见的SNMP版本1和2c不提供加密。这意味着任何拥有数据包嗅探器的人都可以捕获您的SNMP社区名称,因此请绝对确定您仅在专用网络上使用SNMP。在不受信任的网络上进行未加密的SNMP查询是让陌生人窥探您的系统管理的好方法。SNMP版本3使用加密来保护线路上的数据。

SNMP通过社区(communities)提供基本安全。如果你四处看看,你会发现各种各样的解释,为什么社区与密码不同,但社区就是密码。默认情况下,大多数SNMP代理有两个社区:公共(只读访问)和私有(读写访问)。是的,有一个默认设置提供读写访问。每当您在任何主机、任何操作系统上配置SNMP代理时,您的第一个任务就是禁用这些默认社区名称,并用几十年来没有广泛记录的名称替换它们。

FreeBSD的 bsnmpd(8) 默认为SNMPv2c,但可以执行SNMPv3。SNMPv3是一个更复杂的协议,所以我们不打算在这里介绍它。如果你了解SNMPv3协议和配置FreeBSD bsnmpd的基础知识,那么在bsnmpd中启用SNMPv3就不会有任何问题。

配置 bsnmpd

在使用SNMP监视系统之前,必须配置SNMP守护进程。在 /etc/snmpd.config 中配置bsnmpd(8) 。除了包括公共和私有的默认社区外,默认配置不启用任何使 bsnmpd(8) 成为理想的FreeBSD特定功能。

bsnmpd 变量

bsnmpd使用变量为配置语句赋值。大多数高可见性变量都设置在配置文件的顶部,如下所示:

这些顶级变量定义了应在每个SNMP代理上设置的MIB值。位置描述了机器的物理位置。每个系统都需要一个合法的电子邮件联系人。bsnmpd(8) 在FreeBSD以外的操作系统上运行,因此您可以在此处设置特定的操作系统。最后,如果你有一个陷阱主机,你可以在这里设置服务器名称和端口。

在文件下方,您可以设置SNMP团体名称:

read 字符串定义了此SNMP代理的只读社区。默认配置文件建议您更改它。接受这个建议。write 字符串是读写社区名称,默认情况下在配置文件的后面禁用。您还可以为此代理发送的SNMP陷阱设置团体名称。

仅使用此配置,bsnmpd(8) 将启动、运行并为您的网络管理系统提供基本的SNMP数据。只需在 /etc/rc.conf 中设置 bsnmpd_enable=“YES” ,即可在启动时启动bsnmpd。但是,你不会得到任何特殊的FreeBSD功能。让我们继续看看如何处理这个问题。

详细的bsnmpd配置

bsnmpd(8) 使用您在配置文件顶部设置的变量,在稍后的配置中为不同的MIB分配值。例如,在文件的顶部,您将变量 read 设置为 public 。在配置文件的后面,您将找到以下语句:

这将MIB begemotSnmpdCommunityString.0.1 设置为等于 read 变量的值。

为什么不直接设置这些值呢?bsnmpd(8) 是专门为可扩展和可配置而设计的。在文件顶部设置一些变量比直接在文件下方编辑规则要容易得多。

让我们回到这里设置的 begemotSnmpdCommunityString MIB。我们为什么要设置这个?在MIB浏览器中搜索字符串,您将看到这是定义SNMP团体名称的MIB。您可能已经从 read 变量的赋值中猜到了这一点,但很高兴确认这一点。

同样,你会发现这样一个条目:

检查MIB浏览器显示,这指定了 bsnmpd(8) 绑定到的IP地址和UDP端口(在这种情况下,端口161上的所有可用地址)。所有MIB配置都是以这种方式完成的。

正在加载bsnmpd模块

最有趣的 bsnmpd(8) 功能是通过模块配置的。通过为 begemotSnmpdModulePath MIB提供模块处理的类以及实现该功能支持的共享库的完整路径,在配置文件中启用模块。例如,在默认配置中,您将看到PF bsnmpd(8) 模块的注释条目:

这支持PF MIB。当您启用此功能时,您的网络管理软件将能够直接查看PF,让您跟踪从丢包到状态表大小的所有内容。

在撰写本文时,FreeBSD的 bsnmpd(8) 附带了以下模块,但已禁用。有些是FreeBSD特有的,而另一些则支持行业标准。通过取消注释其配置文件条目并重新启动bsnmpd来启用这些选项。

在配置文件中启用其中任何一个后,重新启动 bsnmpd(8) 。如果程序无法启动,请检查 /var/log/messages 是否有错误。

借助bsnmpd(8)syslogd(8) 和各种性能分析工具,您可以使您的FreeBSD系统成为网络上最受监控的设备。现在您可以看到系统提供的所有功能,在我们探索FreeBSD的一些黑暗角落时,请拿一个手电筒。