原文:Basic Linux Terminal Tips and Tricks
协议:CC BY-NC-SA 4.0
五、使用 SSH
在本章中,我们将了解 SSH(安全 Shell)。SSH 是系统管理中最常用的工具之一。它允许您通过加密连接连接到远程服务器或设备。它也是构建在 SSH 之上的其他程序的基础,例如 X2Go,它是一个 Linux,相当于 RDP(远程桌面协议)客户端,如 VNC。
通过使用 SFTP(安全文件传输协议)命令,SSH 也可以以类似于 FTP(文件传输协议)的方式用于文件传输(下一章将详细介绍)。
在某些情况下,SSH 只是用作代理流量的一种手段,以隐藏用户或脚本的位置或 IP 地址。这可以通过 SSH 隧道和 SOCKS 代理来实现。
SSH 的历史
虽然 SSH 只能追溯到 1995 年,但它实际上是建立在早在 1969 年的早期程序上的,比如telnet
。SSH 默认监听端口 22,离telnet
使用的端口 23 只有一个端口。历史上,几乎所有的 Linux 系统都是通过分时系统使用的,在分时系统中,一台中央计算机可以通过几个不同的基于文本的终端连接。这些基于文本的终端除了远程连接到中央计算机所需的软件之外,不包括任何东西。
这段历史对 Linux 操作系统有很大的影响。很明显,SSH 等基于文本的工具仍在广泛使用,允许多个用户连接到一个服务器来运行作业、访问数据和管理系统。
像telnet
(电传网络的缩写)这样的早期程序的主要缺陷是它们缺乏安全性。使用telnet
,客户端和服务器之间的通信是完全未加密的明文(包括任何密码)。双向加密和更高级的安全特性使得 SSH 在流行程度上迅速超越了早期的工具,如telnet
。
虽然telnet
几乎已经被 SSH 完全取代,但今天仍然有一些有趣的在线服务,包括 ASCII 格式的星球大战,telnet 上基于文本的在线象棋,以及 telnet 上的天气查询服务。
telnet towel.blinkenlights.nl
telnet freechess.org 5000
telnet rainmaker.wunderground.com
图 5-1 显示了来自towel.blinkenlights.nl
的基于文本的开场动画。
图 5-1
基于文本的远程登录星球大战再现
基本的 SSH 使用
您想要熟悉的用于连接服务器的最重要的命令是 SSH。SSH 是用于远程连接到服务器、计算机和嵌入式设备的程序。它提供到服务器或设备的安全加密连接,并被广泛使用。当谈到远程管理服务器时,除了非常有限的特定于供应商的管理仪表板之外,确实没有 SSH 的替代方案。
要检查您的系统是否预装了 SSH,请尝试运行
which ssh
如果您获得了一个ssh
文件的文件位置,就可以开始了。否则,继续安装它:
sudo apt-get install ssh
如果您已经运行了一个打开连接的服务器或设备,那么它就像运行
ssh <username>@<address>
之后会提示您输入密码。
使用 ssh-keygen 的密钥对
如果您已经使用 SSH 和密码成功登录到服务器或设备,您首先要做的事情之一就是切换到使用公钥鉴定。有两个主要好处:
-
密钥对被认为比密码更安全。
-
密钥对更方便,因为它们不需要密码。
一对密钥由两部分组成,第一部分是私钥,它将保留在您的计算机上,永远不应该共享;第二部分是公钥,它可以公开共享,用于签署请求,任何拥有公钥的人都可以验证请求来自您。
要开始创建密钥对,首先运行
ssh-keygen
系统会提示您选择密码;这是可选的。密码短语只是用来在本地加密您的私钥。这样,如果有人获得了你的笔记本电脑和私人密钥,他们将无法读取它,假设你选择了一个强密码。
如果您正确地遵循了这些说明,您应该会得到如图 5-2 所示的输出。
图 5-2
ssh-keygen 的输出
接下来,我们将把新的公钥复制到我们的远程 SSH 服务器/设备上;SSH 有一个内置命令来简化这一过程:
ssh-copy-id <username>@<address>
您将再次被提示输入登录服务器的密码。一旦该命令成功运行,您将能够自动登录到服务器,而无需使用服务器密码。但是,如果您选择一个密码来加密您的私钥,您将需要在使用该密钥之前输入该密码。
PEM 和其他关键文件
在某些情况下,服务器可能会使用 PEM 文件,这是隐私增强邮件的缩写。一个流行的例子是 Amazon EC2 服务器。这些键使用-i
标志指定,例如:
ssh -i <pem-file-location> <username>@<address>
使用-i
标志的另一种方法是使用ssh-add
将您的密钥添加到会话中,例如:
ssh-add <pem-file-location>
这将向身份验证代理添加密钥文件。它将保持活动状态,直到 SSH 重新启动,这主要发生在计算机重新启动时。
上述方法并不特定于 PEM 文件,而是可以用于 SSH 服务器所需的任何密钥文件。其他的还有 PPY,Putty 私钥的简称,或者.pub
files,公钥的简称。
禁用服务器上的密码登录
我们提到过使用 ssh 密钥对的主要好处之一是它比密码认证更安全。为了获得这种附加安全性的好处,您必须在服务器上禁用密码登录。当您第一次添加密钥对时,服务器将允许使用这两种方法中的任何一种登录。由于 keypair 更安全,建议您关闭使用密码的功能,以避免任何类型的暴力攻击。
首先,使用 SSH 连接到服务器。然后你需要找到文件/etc/ssh/sshd_config
。打开sshd_config
,修改提及ChallengeResponseAuthentication
的行;您需要确保它被设置为no
,如下所示:
ChallengeResponseAuthentication no
其次,在同一个文件中,找到提到PasswordAuthentication
的那一行,将其设置为 no:
PasswordAuthentication no
这两个设置将确保密码不能用于登录服务器。因此,在更改这些值之前,确保公钥身份验证正常工作非常重要。否则,您可能会发现自己完全被锁定在服务器之外。
最后,还有最后一个步骤,让 SSH 服务器重新加载已经更改的设置,这样它们才能生效。为此,请运行以下命令:
service sshd restart
重启 SSH 服务器的最后一步值得注意,因为它并不特定于这个设置。每当您对 SSH 配置进行任何更改时,您都需要在服务器上重新启动服务,以使这些更改生效。
带有 SSH 配置文件的服务器昵称
使 SSH 变得简单一点的另一个便利技巧是创建一个客户端 SSH 配置文件。您可以使用它为您经常登录的每台服务器创建默认用户名、服务器 IP 和身份验证密钥文件。当您经常需要在多个服务器或设备之间切换时,这变得特别有用。
您需要做的第一件事是创建 SSH 配置文件,该文件应该位于~/.ssh/config
:
touch ~/.ssh/config
接下来,您需要确保它拥有正确的权限:
chmod 600 ~/.ssh/config
完成后,您可以打开配置文件并为您的每台服务器创建一个条目。例如,我将使用我目前正在使用的 AWS 服务器:
Host aws
Hostname ec2-35-174-116-189.compute-1.amazonaws.com
User ubuntu
现在,我可以不指定完整的主机名和用户,而是
ssh -i ~/.ssh/file.pem aws
您可能不需要-i ~/.ssh/file.pem
,这取决于您的服务器是否需要身份文件。关键文件类型.pub
或.ppk
也可以与-i
一起使用。
我们可以通过将身份文件添加到我们的配置中来进一步简化这一过程:
Host aws
Hostname ec2-35-174-116-189.compute-1.amazonaws.com
User ubuntu
IdentityFile ~/.ssh/file.pem
现在我们可以简单地做
ssh aws
要为多个服务器添加条目,只需在配置文件中添加下面的附加块。这使得连接到不同的服务器更加容易,因为你不需要记住每个服务器的地址。
Note
IdentityFile
也可用于指定公钥/私钥登录的 RSA 密钥。尽管默认情况下该值是~/.ssh/id_rsa
。因此,如果您使用默认的密钥位置,就不需要添加它。
在连接上运行命令
有时您只想连接到服务器来运行一个命令。这通常与必须连续在几个相似的设备或服务器上执行一些修复有关。在一个例子中,我工作的一家公司有几个设备有一个错误,破坏了我们的配置管理设置。修复方法是简单地删除这些设备上的一个锁定文件。我们能够通过创建一个 for 循环来快速修复所有这些问题,该循环获取每个设备的 IP,连接,然后运行所需的命令。
Note
如果您经常发现自己必须连接到多个系统来运行相同的命令、修改配置或更新程序,那么您会想要查看 Ansible 程序,这是一个轻量级的开源程序,用于在几台机器上同时进行相同的更改。Ansible 构建在 SSH 之上,因此当您编写一个配置发送到多个设备时,它实际上是通过 SSH 连接并在幕后运行命令。Ansible 的其他受欢迎的替代品包括木偶、厨师和盐。
为此,您只需在 ssh 命令的末尾提供一个带引号的命令,例如:
ssh user@server.com "touch /tmp/testing123"
连接后,您几乎会立即断开连接并返回到您的本地机器命令行,如图 5-3 所示。
图 5-3
指定在 SSH 连接上运行的命令
如果您想在连接上运行一个命令,但不想立即断开连接,您可以修改命令 run on connection 来启动一个 bash 会话:
ssh user@server.com "touch /tmp/testing123; bash"
这将运行命令,然后将您置于 bash 会话中,不会断开连接。
中断挂起的 SSH 会话
使用 SSH 时可能出现的一个常见问题是,您让一个会话在后台或另一个窗口中运行,当您返回时,它完全冻结了。连接问题也可能是 SSH 会话挂起的常见原因。当客户端失去与服务器的连接时,它将挂起,直到服务器重新连接。您可能会想尝试按 ctrl+c 或 ctrl+d,但即使这样也不会结束冻结的 SSH 会话。
当这种情况发生时,退出会话的最简单方法是按 enter 键,然后按~
,再按.
。这样做应该会退出会话并返回如下消息
Connection to yourServer.com closed.
这种组合键是最广为人知的转义序列,但不是唯一的。如果你改为按回车键,~
,然后?
,你将得到所有支持的转义序列列表,包括表 5-1 中的那些。
表 5-1
转义序列列表
|顺序
|
描述
|
| — | — |
| ~. | 终止连接(以及任何多路复用会话) |
| ~B | 向远程系统发送中断 |
| ~C | 打开命令行 |
| ~R | 请求重置密钥 |
| ~V/v | 减少/增加详细程度(日志级别) |
| ~^Z | 暂停 ssh |
| ~# | 列出转发的连接 |
| ~& | 后台 ssh(等待连接终止时) |
| ~? | 列出所有序列 |
| ~~ | 通过键入两次来发送转义字符 |
在大多数情况下,您主要希望使用常规的~.
,当然,除非您刚刚输入了一个换行符,并且您确实希望键入~
字符;在这种情况下,只需第二次点击它。还要注意的是,如果~
是一行的第一个字符,它只会被作为转义序列读取;如果你已经进入了一行,你需要先按回车键或者清除输入。
保持健康
有时当你不得不中断连接时,或者如果你曾经不得不使用类似minicom
的程序或者有时甚至是 SSH 来使用串行端口连接到一个设备,你将会有如图 5-4 所示的终端窗口故障。当这种故障发生时,您键入的字符可能不会像您预期的那样出现。这可能会导致意外的行为,使终端屏幕的大部分内容不可读,或者只是看起来不正确。
图 5-4
终端中的 ASCII 乱码故障(又名 mojibake)
或者您可能没有得到图中所示的 ASCII 类型的字符,但是您的空格是关闭的,终端通常不按预期运行;参见图 5-5 了解可能出现的奇怪间距类型。
图 5-5
视觉间距毛刺
如果这些小故障或任何视觉上的事情发生,你可以使用stty sane
来修复你的终端,而不必关闭并重新打开。简单地跑
stty sane
在这种情况下可以使用的另一个命令是reset
,它不带任何参数独立运行(不要与 reboot 混淆,reboot 将重新启动系统)。
reset
停止 SSH 挂起
能够从一个挂起的 SSH 会话中断开连接是很好的,但是如果能够完全避免这种情况发生就更好了。根据您的系统,默认情况下这可能不是问题,但是可以在您的客户端的/etc/ssh/ssh_config
文件中更改ServerAliveInterval
设置。
此设置告诉客户端多久向服务器发送一次信号,以确认您仍然连接并使用该连接。如果您在文件中没有看到ServerAliveInterval
的实例,请添加以下几行:
Host *
ServerAliveInterval 100
您必须在出现问题的服务器上编辑同一个文件/etc/ssh/sshd_config
:
ClientAliveInterval 60
TCPKeepAlive yes
ClientAliveCountMax 10000
这告诉服务器,如果没有收到任何保持会话活动的消息,则每 60 秒向客户端发送一条保持活动消息。TCPKeepAlive
确保防火墙不会丢弃空闲连接,而ClientAliveCountMax
指定服务器将在多长时间内保持发送保活消息,即使没有从客户端听到任何消息。
SSH 隧道
SSH 隧道是通过 SSH 将一台计算机上的端口转发到远程计算机的过程。SSH 隧道有多种用途,我们将在接下来的章节中介绍。
本地 SSH 隧道
最简单的 SSH 隧道之一是本地隧道,它将本地端口绑定到远程机器上的地址。例如,我们可以使用-L
标志将本地端口 8080 绑定到一个通过远程机器访问的网站:
ssh -L 8080:textfiles.com:80 user@server.com
在写这篇文章的时候,这在 textfiles.com 网站上运行得很好(这是一段有趣的互联网历史。查看 Jason Scott 的 Defcon 17 演讲,了解背后的故事)。不幸的是,这取决于你想隧道网站,它可能会或可能不会工作。像nginx
这样的现代服务器软件实际上会检查你的浏览器中正在使用的主机名,但由于不匹配而无法工作。
在某些情况下,网站无法通过隧道工作,因为它们会检查浏览器使用的 URL,并且在使用“localhost”时会出现故障。Youtube 等大多数流行的网络应用都是如此。如果你想通过隧道访问一个不工作的网站,你可以通过更新/etc/hosts
将该 URL 映射到你自己的服务器的 IP 地址,或者你可以发送一个虚假的标题,声称你的主机名实际上是预定的网站。根据您的操作系统,您可能需要安装curl
。
sudo apt-get install curl
下面是一个使用curl
手动设置带有-H
标志的主机头的例子:
curl -H "Host: youtube.com" -L localhost:8080
这应该会返回 YouTube 的源代码。如果您想要一种更实用的方法来使用 SSH 隧道进行 web 浏览,我们在下一节关于 SOCKS 代理的内容中提供了一个更好的解决方案。
虽然这个例子向我们展示了本地 SSH 隧道是如何工作的,但它并没有确切地展示为什么会使用它。对于任何与浏览相关的内容,下一节中显示的 SOCKS 代理方法将是首选。
当您想要通过 SSH 访问服务器上运行的服务时,SSH 隧道就很方便了。这是一种特别安全的方式来为一个小团体提供 web 服务,而不必担心很多安全问题。由于该网站只对那些通过端口 22 上的 SSH 访问它的人可用,因此不存在可能以公开登录页面为目标的攻击威胁。
用 SSH 创建 SOCKS 代理
SSH 非常适合连接到远程服务器和设备,但它实际上可以用于各种用途。其中之一是创建一个 SOCKS 代理连接,当使用像 web 浏览器这样的应用时,它可以用来在本地计算机上引导流量。
SOCKS 代理具有与使用 VPN(虚拟专用网络)相关的大部分好处,包括
-
匿名网页浏览
-
绕过地理定位封锁
-
绕过本地网络或 ISP 的网站阻止
-
比 VPN 还快
请记住,第一个好处“匿名网页浏览”只是部分真实,这取决于你打算匿名的人和你用来代理流量的服务器。如果你试图向政府隐藏你的身份,并且你使用的服务器是以你的名字注册的,这可能不会有效。
然而,从你正在访问的网站的角度来看,他们只会看到你的终端服务器的 IP 地址。例如,他们可能看到流量来自位于美国东部的 AWS 服务器。
当使用您自己的服务器作为 SOCKS 代理时,需要记住的另一个警告是,一些服务器提供商的 IP 可能会被标记为 SOCKS 代理,并受到一些服务和网站的限制。这是因为许多自动化脚本和恶意服务都来自这些类型的服务器。如果您使用的是较小的主机提供商的服务器,您可能会绕过这类问题。
要开始,只需运行以下命令,用用户名和主机替换您自己的用户名和主机:
ssh -D 8123 -f -C -q -N user@server.com
这里包含的标志如表 5-2 所示。
表 5-2
使用的标志
|旗
|
描述
|
| — | — |
| -D 8123 | 绑定到端口 8123 的连接 |
| -f | 将进程转移到后台 |
| -丙 | 发送前压缩数据 |
| q | 安静模式 |
| 同-EN | 不要执行远程命令 |
如果运行没有错误,您应该让 SOCKS 代理监听端口 8123 ( 随意用另一个替换端口号)。我们可以使用ps
和grep
进行双重检查:
ps aux | grep ssh
如果正在运行,您应该看到您运行的命令被列为正在运行的进程。使用代理取决于您使用的具体应用。作为一个例子,我们来看看 Firefox。在 Firefox 中打开偏好设置,然后向下滚动到“网络设置”在网络设置中,如图 5-6 所示,您可以使用“localhost”配置“手动代理配置”,并将您选择的端口作为 SOCKS 主机。
图 5-6
设置 web 浏览器使用 SOCKS 代理
在 Firefox 上更新您的代理并保存后,您需要验证它是否按预期工作。要做到这一点,你需要找到一个网站来检查你的 IP 地址。我的首选方法是去 www.duckduckgo.com
(面向隐私的搜索引擎),搜索“我的 ip 是什么”这样做应该会显示你的 IP 地址和位置,如图 5-7 所示,而不必点击进入任何第三方网站。
图 5-7
DuckDuckGo 显示我们的远程 SSH 服务器的 IP
反向 SSH 隧道
SSH 是连接远程服务器和设备的一个很好的工具,但是有时防火墙和路由器会碍事。例如,如果你家里有一个运行 Linux 服务器的 Raspberry Pi,并且想从你的本地网络之外通过 SSH 连接到它,你可能会因为路由器和互联网提供商的限制而遇到麻烦。
一个很好的解决方法是创建一个反向 SSH 隧道。反向 SSH 隧道依赖于相关设备来维持活动的传出连接。例如,我们的 Raspberry Pi 将持续保持与远程服务器的连接。因为是 Pi 对传入连接有限制,而不是相反,所以 Pi 进行传出连接没有问题。
当我们准备好 SSH 到 Pi 时,我们实际上在隧道内创建了我们的连接,这是 Pi 的输出连接。因此,Pi 在其自己的输出连接中接收输入连接。
要建立一个反向 SSH 隧道,首先在相关的服务器上打开一个终端会话;在这种情况下,我们的树莓派在防火墙后面。运行以下命令:
ssh -R 9876:localhost:22 user@server.com
-R
标志在作为主要 SSH 连接的隧道内创建一个较小的隧道;-R
代表远程,作为隧道入口点在远程机器上;这类似于-L
旗,除了-L
旗在本地侧有入口点。
另请注意,我们已经选择端口 9876 作为进入远程端的内部隧道在本地端结束的位置。请随意将端口 9876 与设备上任何未使用的端口交换。
一旦准备好连接到运行反向代理的设备,只需像平常一样使用 SSH,但要指定上一步中使用的端口。因此,在我们的示例中,我们将使用以下命令:
ssh -p 9876 user@server.com
通过反向代理服务网站
这种类型的 SSH 隧道是流行的开发工具 ngrok 的基础。Ngrok 允许开发人员立即将运行在本地机器上的 web 应用发布到 web URL 上,供任何人查看。您可以使用自己的 web 服务器做同样的事情。
为了演示,首先我们将创建一个运行在端口 8080 上的最小站点。如果你运行的是最新版本的 Ubuntu,默认情况下你应该已经安装了python3
;否则你需要安装它。
cd /tmp
echo Hello World > index.html
python3 -m http.server 8080
运行这三行代码后,您将能够在 web 浏览器中转到 localhost:8080,并看到文本“Hello World”。我们的小站点运行在端口 8080 上,现在我们可以运行以下命令:
ssh -R 8080:localhost:8080 user@myServer.com
这将把我们本地机器上的端口 8080 镜像到远程服务器上的端口 8080,从而允许我们在一个活动的 IP 上演示我们的本地主机网站。
SSH 代理跳转
有时您不想直接连接到 SSH 服务器。使用跳转框有两个主要原因:
-
通过仅允许从特定 IP 或非公共网络连接到最终目标服务器来降低安全风险。
-
您不希望最终的目的服务器记录您的实际 IP 地址。
在第一种情况下,您的目标服务器可能在公共互联网上不可用。在这种情况下,跳转框充当一个 DMZ ( 非军事区),您可以从这里进行连接。这意味着受保护的盒子是完全隐藏的,不会被端口扫描器或任何扫描开放互联网的恶意脚本发现。
您可以使用-J
标志来使用跳转服务器,如下所示:
ssh -J user@server1.com user@server2.com
当使用跳转服务器时,使用 SSH 配置文件会很方便,因为您不能使用-i
标志直接指定跳转服务器的身份文件,但是如果您使用本章中描述的 SSH 配置文件,您可以在那里定义身份文件。
如果你的情况更符合试图隐藏你的起源,你甚至可以使用一系列的跳转服务器。有了多个跳转服务器,即使是连接到目的服务器的跳转服务器也不会知道你的 IP 地址。通过提供多个以逗号分隔的跳转服务器,您可以使用多个跳转服务器:
ssh -J user@jump1.com,user@jump2.com user@server.com
更改 SSH 服务器上的默认端口
有几个原因可能导致您想要更改 SSH 服务器的默认端口——如果您知道您将从一个网络连接到服务器,该网络限制了除端口 80 或 443 之外的任何出站连接。
或者,如果您将使用密码验证,并且希望降低服务器被可能尝试暴力攻击的爬虫发现的机会,在这种情况下,请使用不常见的端口,如 79279。如果您不确定您选择的随机端口是否不常见,您可以使用nmap
进行检查。nmap
默认情况下不会安装,因此您必须通过您的软件包管理器安装它:
sudo apt-get install nmap
一旦安装了’nmap
’,使用以下命令:
nmap --top-ports 1000 localhost -v -oG -
这将返回 1000 个最受欢迎的端口列表,您可以reference
查看您的端口是否匹配。
打开防火墙
在更改端口之前,务必确保您没有防火墙或其他会阻止传入流量的配置。要检查是否启用了防火墙,请运行
sudo ufw status
如果ufw
正在运行,您可能需要将其配置为接受来自您想要的端口的流量。如果它没有运行,您可能仍然需要处理您的云提供商安全设置。例如,Amazon AWS 安全实例的安全规则是在服务器本身之外的安全组规则中设置的。许多其他云提供商遵循相同的模式,只开放端口 22(可能还有端口 80 和 443),以使服务器在默认情况下是安全的。请咨询您的服务器提供商,了解是否需要额外的步骤来允许端口访问。
如果ufw
正在运行,你可以通过运行告诉它允许你的端口
sudo ufw allow <port-number>
修改 sshd_config
可以通过编辑文件/etc/ssh/sshd_config
来修改 SSH 服务器的设置。在更改活动服务器上的端口之前,请确保该端口是可访问的。如果您将端口更改为阻止传入请求的端口,可能会将您自己锁定在服务器之外。要更改默认端口,只需找到如下注释行
#Port 22
取消对线路和交换机 22 的注释,使用您选择的端口:
Port 7929
Note
SSH 服务器的默认端口也可以在您的客户端 SSH 配置文件中指定,这样您就不需要在连接到服务器时使用-p 标志来指定它。
更新文件后,您需要重新启动 SSH 服务:
sudo service ssh restart
摘要
在本章中,我们了解了如何使用 SSH 和一些常见的配置远程连接到服务器或设备。这些配置包括关闭密码登录以使用密钥对,切换默认端口,以及通过修改保持活动设置来停止挂起。我们研究了 SSH 隧道和常见用法,比如创建 SOCKS 代理。
虽然这个列表很难涵盖 SSH 使用的所有地方和方式,但是它为使用一些常用设置连接到远程服务器打下了良好的基础。
六、文件传输
在这一章中,我们将看看在机器之间传输文件的各种程序。
文件传送协议
传输文件最常见的协议之一是 FTP ( 文件传输协议)。要开始使用 FTP,你应该安装lftp
,一个复杂的文件传输程序。该程序主要用于 FTP,但也可用于其他协议:
sudo apt-get install lftp
安装lftp
后,您可以使用以下命令进入交互模式
lftp
这将打开一个交互式 shell,您可以在其中运行特定于lftp
的命令。它看起来应该类似于图 6-1 。
图 6-1
lftp 交互模式
lftp
shell 的行为很像普通的 bash shell,让您可以访问几个命令,比如ls
和cd
。您还可以获得额外的命令。要查看可用的命令,只需输入?
并按回车键。
需要知道的最重要的命令是connect
,它被简单地用作
connect -u <username> <server-address>
之后,系统会提示您输入密码。连接后,您可以使用下载文件
get <file-name>
或使用上传
put <file-name>
Note
如果你正在寻找 FTP 服务器来练习,并且不想建立自己的 FTP 服务器,使用谷歌呆子寻找不安全的 FTP 服务器可能是有用的。Google dork 是一个搜索词,用于使用搜索词查找特定的应用或不安全的网站。寻找 FTP 服务器的一个好方法是intitle:"index of" inurl:ftp
。
science for the people 为人类服务的科学
Note
对于 SFTP 和 SCP(下一节),您可以在本地主机上测试这些命令,而不是指定一个远程服务器。只需使用本地主机和您的用户名。当然,从一个本地主机到另一个本地主机并没有比类似于mv
的命令提供更多的好处,但是它确实允许您在没有远程服务器设置的情况下测试这些命令。
您可能熟悉 FTP,它是文件传输协议的缩写。它通常与 FileZilla 等 GUI 程序一起使用,用于向服务器上传和下载文件。在 PHP 最流行的时候,使用 FileZilla 更新服务器的www
目录是标准做法。
虽然像 FileZilla 这样的程序仍然被广泛使用,但这些程序现在使用了一种叫做 FTPS 的新的安全版本的 FTP。FTP 有一个主要弱点,使得攻击者能够在用户连接到服务器时,嗅探到 FTP 服务器的流量并获取用户凭据。
FTP 的另一个流行且易于使用的替代方法是 SFTP。SFTP 支持文件传输,看起来和感觉上像 FTP,但通过端口 22,SSH 会话使用的同一端口。如果您已经在服务器上使用了 SSH,那么使用 SFTP 连接它应该没有问题。它不需要在服务器或连接客户端上安装任何额外的软件。大多数 SSH 安装都应该包含 SFTP,除了极少数轻量级版本。
首先,只需使用您已经在使用的命令通过ssh
连接到您的服务器,并使用sftp
代替,例如:
sftp ubuntu@myserver.com
或者,如果您使用 PEM 文件进行身份验证(这在 AWS 服务器中很常见),请使用
sftp -i ~/.ssh/key.pem ubuntu@myserver.com
连接前需要注意的一点是,您连接的目录将是您打算下载或上传的目录。
一旦登录到服务器,您将能够使用一些通常在ssh
会话中可用的命令,但不是全部。最重要的是,您将能够使用ls
和cd
( 就像使用 FTP )来浏览您的文件系统。
如果您想下载一个文件,导航到相关文件夹并使用get
命令:
get readme.txt
如果一切正常,您应该会看到一些确认下载的输出,如图 6-2 所示。
图 6-2
使用 lftp 从远程服务器获取文件
从那时起,通过按 ctrl+c 断开sftp
连接。一旦回到本地机器,运行ls
,您应该会看到下载的文件。
你可能想利用的另一个上传文件的功能是put
。与get
一样,在通过sftp
连接之前,导航到包含您想要上传的文件的文件夹。然后与sftp
连接;在服务器上,导航到您想要上传文件的位置。键入put
,确保包含put
后的空格,然后按 tab 键。在put
之后按 tab 应该会显示目录中的文件列表。在图 6-3 中,你可以看到鸟、猫和狗的图像文件。
图 6-3
使用自动完成功能查看可以放入哪些文件
从这一点来说,我可以简单地完成三个选项中的一个,或者如果您意识到您在错误的文件夹中,您可以开始键入替代路径,例如,../
或/
,然后再次按 tab 以帮助找到您想要上传的文件。
Note
在章节 5 中,我们看了如何创建一个~/.ssh/config
文件来创建包含服务器、用户名和其他选项的快捷方式。这个相同的配置文件也适用于 SFTP 和 SCP。
单细胞蛋白质
SCP 是 secure copy protocol 的缩写,是 SSH 附带的另一种文件协议。功能类似于 SFTP,但它没有交互方面。使用 SCP 的上传或下载必须在一个命令中声明,而不是首先连接到一台机器,然后才能浏览目录。
总的来说,SCP 似乎比 SFTP 更糟糕,因为它没有提供额外的功能,交互性也更差。但是,SCP 的优势是文件传输速度比 SFTP 快。对于中小型文件,这可能会被忽视,但如果你是移动一个大文件,你可能会决定用 SCP 而不是 SFTP。如果您将文件作为脚本的一部分进行传输,您也可以考虑使用 SCP,交互模式实际上是一种阻碍而不是一种好处。
要从服务器下载文件,只需运行scp
,然后运行username@serverName
,然后运行:/file/location
( ,不带空格,然后作为第二个参数运行您希望在本地机器上保存文件的路径,例如:
scp ubuntu@myserver.com:/tmp/myFile.txt ./
许多在ssh
和sftp
上起作用的标志也将在scp
上起作用——例如,如果您需要使用 PEM 文件登录到您的服务器:
scp -i ~/.ssh/mykey.pem ubuntu@myserver.com:/tmp/myFile.txt ./
如果您需要将文件上传到服务器,只需切换路径的顺序:
scp ./ ubuntu@myserver.com:/tmp/myFile.txt
备份
Note
如果您使用密码登录您的服务器,您需要设置公钥认证,如第五章“ssh-keygen 的密钥对”一节所述除了设置 SSH 之外,您的远程服务器唯一需要安装的是rsync
。
Rsync 是另一个在 Linux 系统上上传和下载文件的工具,但它的功能更像是一个自动备份系统,类似于 Dropbox 提供的服务。设置完成后,它将监控一个系统上的目标文件夹,如果有任何文件被添加或更改,它们将被同步到远程服务器。这很方便,因为与一些定制备份脚本不同,它将只保存新的或更改的文件,而不是定期运行备份文件夹的scp
命令。
要开始使用,请安装rsync
:
sudo apt-get install rsync
要使用该程序,您需要运行以下命令:
rsync -r --progress \
~/backup ubuntu@<myserver.com>:/home/ubuntu/backup
在前面的命令中,我们首先指定我们的本地文件夹~/backup
,这是我们想要备份的文件夹。在文件夹之后,我们指定用户名和服务器ubuntu@<myserver.com>
,您将用您的服务器信息替换它。如果没有空格,我们就有了:/home/ubuntu/back
,这是我们将要备份文件的文件夹位置。
虽然我们首先指定本地文件夹,但这不是必需的。如果我们想将远程服务器备份到本地文件夹,我们只需交换参数的顺序,然后运行以下命令:
rsync -r --progress \
ubuntu@<myserver.com>:/home/ubuntu/backup ~/backup
我们使用的可选标志是-r
和--progress
,前者导致文件夹被递归备份,后者提供一些关于备份过程进行到什么程度的视觉反馈。
如果您正在使用一个身份文件,您将需要使用-e
标志并指定用于启动会话的特定 SSH 命令。我们使用添加身份文件的例子,但是如果您想以任何方式修改 SSH,您可以使用-e
标志。然而,在某些情况下,比如更改远程服务器用于 SSH 的端口,rsync
提供了自己的标志--port
(和往常一样,您可以查看手册页以获得选项的完整列表)。
rsync -r --progress \
-e "ssh -i /home/philip/.ssh/key.pem" \
~/backup ubuntu@myserver.com:/home/ubuntu/backup
如前所述,我们使用了-r
标志。如果没有-r
选项,文件夹中的文件将不会被备份。有几个选项可以和rsync
一起使用;表 6-1 中列出了一些最常见的。
表 6-1
常见 rsync 选项
|短旗
|
满旗
|
描述
|
| — | — | — |
| -v | -冗长 | 更详细的输出 |
| q | 安静 | 无文本输出 |
| [构成动植物的古名或拉丁化的现代名] | -存档 | 同步时归档文件 |
| -r | -递归 | 递归同步目录 |
| -b | -备份 | 制作备份 |
| -你 | -更新 | 如果目的地较新,不要复制文件 |
| -我 | -链接 | 复制符号链接 |
| 同-EN | -预演 | 试验 |
| -e | -rsh="command " | 指定远程 Shell 命令 |
| z | -压缩 | 同步时压缩数据 |
| -h | -人类可读 | 人类可读格式的尺寸 |
| | -进步 | 同步过程中显示进度 |
为 Rsync 设置 Cron 作业
我们已经看到使用rsync
备份整个文件夹或一组文件夹是多么容易,但是它还不是完全自动的。为了让生活变得简单一点,我们可以创建一个 cron 作业来自动执行定期调用命令的过程。
为此,我们将创建一个 cron 作业,但首先让我们在脚本文件中移动备份命令。您可以在您喜欢的任何位置创建该文件;定制脚本的一个常见位置是/usr/local/bin/
。打开您的脚本文件,在我们的例子中,我们将使用/usr/local/bin/backup.sh
,添加一个 shebang,并粘贴特定于您的服务器和备份文件夹位置的rsync
命令:
#!/usr/bin/env bash
rsync -r --progress \
~/backup ubuntu@myserver.com:/home/ubuntu/backup
确保将用户、服务器和文件夹替换到您的特定设置中。如果您想要备份多个文件夹,您可以在第一个文件夹下添加额外的rsync
命令。保存后,请确保为新文件添加执行权限:
chmod +x /usr/local/bin/backup.sh
最后,我们将通过运行crontab -e
创建 cron 作业,并在文件底部添加
0 0 * * * /usr/local/bin/backup.sh
有了这个设置,你的系统应该在每天午夜进行备份。
同音双向同步
我们已经看到了rsync
如何使从一台机器到另一台机器的备份变得容易,但这与像 Dropbox 这样提供双向同步的流行服务不太一样。如果你需要以两种方式同步文件,你可以使用建立在rsync
之上的unison
程序,它提供双向同步。
确保在您想要同步的两台机器上都安装了unison
:
sudo apt-get install unison
由于没有用unison
指定一个.pem
键的选项,你只能将它添加到ssh
中,并让ssh
在需要时提供它。你可以通过运行(你必须在每次系统重启时运行这个步骤)
ssh-add <path/to/file.pem>
完成后,您就可以运行unison
:
unison -auto -batch \
~/backup \
ssh://ubuntu@server.com//home/ubuntu/backup/
建议使用-auto
和-batch
标志来使过程自动化;如果没有它们,您将被手动要求验证每个同步的文件。
当文件同步更改时自动同步
不幸的是,包括 Ubuntu 在内的一些包管理器上可用的版本unison
不包括监控文件系统的配套二进制文件unison-fsmonitor
。这给你留下了两个选择:
-
使用 cron 作业定期检查,就像我们使用 rsync 一样。
-
从源代码手动编译 unison。
如果您想使用 cron 的简单方法,只需参考上一节关于 rsync 的内容,用一个unison
命令替换backup.sh
中的rsync
命令;您可能还想增加 cron 作业的频率。如果您想从源代码编译以获得在文件改变时立即自动同步的能力,请继续阅读,我们将介绍从源代码编译所需的步骤。为避免任何错误,请确保两台机器上的rsync
版本相同。
首先,我们需要卸载包管理器版本的unison
并安装ocaml
,这是编写 unison 的语言:
sudo apt-get remove unison
sudo apt-get install ocaml
接下来转到 https://github.com/bcpierce00/unison/releases
并记下最新的可用版本。在写的时候,是 2.51.2。无论版本号是多少,都要设置一个环境变量,因为我们会多次使用它:
UNISON_VERSION=2.51.2
设置好版本号后,运行以下一系列命令;注意,我们使用了为版本号设置的环境变量:
wget \
github.com/bcpierce00/unison/archive/v$UNISON_VERSION.tar.gz
tar -xzvf v$UNISON_VERSION.tar.gz
rm v$UNISON_VERSION.tar.gz
pushd unison-$UNISON_VERSION
make
sudo cp -t /usr/local/bin ./src/unison ./src/unison-fsmonitor
popd
rm -rf unison-$UNISON_VERSION
您需要在想要同步的两台服务器上运行前面卸载、构建和安装unison
的步骤。完成后,您可以在两台服务器中的一台上运行以下命令:
unison -batch -auto ~/backup \
ssh://ubuntu@server.com//home/ubuntu/backup/ \
-repeat watch
运行该程序后,您可以尝试在任一服务器上的备份目录中创建一个文件,并查看文件是否同步。
Note
设置unison
时,注意不要互相备份两个主目录。在测试过程中,我们发现每次使用主文件夹备份后,都会更新一个日志文件,它本身会触发另一个备份,从而导致无限循环。
同音设置文件
正如我们在注释中提到的,由于日志文件的原因,我们在尝试创建两个主目录之间的备份时遇到了一个错误。但是,如果需要,可以修改 unison 日志文件的位置以及程序运行的许多其他方面。unison 的设置在文件.unison/default.prf
中指定。如果我们想改变日志的位置,我们可以添加下面一行。
logfile = /tmp/unison.log
其他可以设置的选项包括忽略某些文件类型;在此查看忽略 mp4 文件的示例:
ignore = Name *.mp4
有关 unison 上可配置内容的更多信息,请参见 www.cis.upenn.edu/~bcpierce/unison/docs.html
的官方文档。
创建一个服务来保持 Unison 运行
虽然我们已经在两台服务器上实现了双向自动同步,但仍然存在一些问题。首先,你不得不保持终端窗口运行一致,其次,如果你重启电脑,它会关闭。
作为这两个问题的解决方案,我们将创建一个systemd
服务,它将在启动时打开unison
,并确保它保持运行,这样您的文件夹总是同步的,而无需您运行命令或考虑它。
我们要做的第一件事是移动调用 unison 时使用的所有命令行参数,并将它们转换成位于~/.unison/bidirsync.prf
的 unison 配置文件。创建~/.unison/bidirsync.prf
并添加以下内容:
# Unison preferences
label = bi-directonal sync with server
root = /home/<user>/backup
root = ssh://<user>@<server-name>//home/<user>/backup
batch = true
auto = true
repeat = watch
logfile = /home/<user>/.unison/unison.log
#debug=all
如果您的服务器需要一个像 PEM 这样的身份文件,您还需要添加一行来指定该文件,格式如下:
sshargs = -oIdentityFile=/home/<user>/.ssh/<privkey-name>
通过运行unison bidirsync
测试配置。注意,bidirsync
既是我们创建的文件名,也是我们配置文件中的标签。您可以使用~/.unison/
文件夹创建任意多的 unison 配置,并以这种方式快速运行它们。
现在我们有了一个工作配置,我们将创建一个systemd
服务(参见第十一章了解更多信息)。首先创建一个新文件夹~/.config/systemd/user
:
mkdir -p ~/.config/systemd/user
然后在那个文件夹中,创建一个名为unison.service
的文件。它应该包含以下内容(确保将用户和组更新为您自己的值):
[Unit]
Description=Unison
[Service]
Environment="PATH=/usr/local/bin:/usr/bin"
ExecStart=/usr/local/bin/unison bidirsync
User=<yourUser>
Group=<yourUser>
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
一旦创建了服务文件,就可以运行以下命令来启动它:
sudo systemctl start unison
您可以通过运行以下命令来检查一切是否正常,并查看日志
systemctl status unison
摘要
在这一章中,我们看了几个可以用于跨机器下载、上传和同步文件的服务。我们从经典的ftp
和更安全的替代品开始,如sftp
和scp
。然后我们看了看rsync
如何轻松同步文件夹,甚至看了看unison
,它能够在不同机器上的文件夹发生变化后立即自动保持同步。
七、网络扫描
通常,您会想要查看本地网络上有哪些设备,包括设备的 IP 地址。这在几种情况下很方便,包括但不限于
-
你想得到你的路由器的 IP 地址。
-
您到达一家酒店,想要检查网络是否有漏洞或隐藏设备,例如可能被遗忘的流氓 Raspberry Pi。
-
你想看看网络上其他电脑的 IP 地址,看看有没有不安全的地方。
-
对网络上有哪些设备的普遍好奇。
在这一章中,我们将介绍如何检测网络上有哪些设备以及它们打开了哪些端口。在某些情况下,甚至可以确定设备运行的操作系统、某个端口上运行的应用的版本或者服务器的物理位置。
用 Ping 检查连接
在我们开始扫描网络之前,有必要提及一个最简单但有用的命令。ping
允许您检查您是否已连接到互联网,以及您的目标网站是否已打开。为了检查你的互联网连接是否良好,许多人会向8.8.8.8
发送一个ping
;这是谷歌的主要 DNS 服务器,众所周知非常可靠。你可以用
ping 8.8.8.8
Note
由于其长寿和高正常运行时间,8.8.8.8 经常被用作发送 pings 的虚拟服务器。然而,由于这是一个企业(Google)使用的活动服务器,您可能希望考虑周到,不要给他们的负载增加额外的流量。互联网数字地址分配机构专门保留网站example.com
作为示例网站,用于上述目的。出于这个原因,我们将使用example.com
来代替 8.8.8.8。然而,知道 8.8.8.8 经常被用于这个目的是很好的,这样如果你在一个脚本中看到它,你可以识别正在发生的事情。
大约每秒钟你都会得到一个响应,告诉你连接是好的。可以用ctrl+c
退出程序;如果您只想 ping 一次或固定次数,您可以使用-c
标志后跟一个数字。如果您想在连接到互联网或目标网站启动的情况下执行某些操作,这可能会很有用,例如:
ping -c 1 example.com && echo connected
如果我们用一个不活跃的 IP 或网站来改变example.com
,那么echo connected
将永远不会运行。
arp 扫描方法
最简单的方法是安装一个名为 arp-scan 的程序。arp-scan
是一个向网络上的所有设备发送 arp 数据包并显示收到的响应的程序。
在基于 Ubuntu/Debian 的系统上,您应该能够安装它
sudo apt-get install arp-scan
安装后,使用--localnet
选项查看本地网络上的所有设备;该命令需要 root 权限:
sudo arp-scan --localnet
该程序将返回一个设备列表,包括 IP 地址,唯一的 MAC 地址,如果可能的话,还有设备的制造商。
当我在酒店房间写这篇文章时,我可以看到本地的 Cisco 路由器,毫不奇怪,它可以使用设备的默认用户名和密码登录。
此外,我有时可以看到我的 Android 手机也连接到网络。对于 android 设备来说,看到它取决于发送 arp 数据包时是否收到响应,这在睡眠模式下通常不会发生。
记下设备的唯一 MAC 地址会很有用,例如,如果您想稍后查看某人是否在另一个位置。说我在朋友家;我可能会记录下他笔记本电脑和手机的 MAC 地址。然后,当在单个网络上的大型建筑物(例如,图书馆)时,我可以扫描网络以查看他的设备是否连接,从而知道他是否在所述位置。
nmap 方法
虽然我发现 arp-scan 为找到的设备提供了最完整的信息,因为它返回 IP、MAC 地址和制造商,但也有设备不包括在扫描范围内的情况——例如,如果某个设备存在于网络上,但尚未分配 IP 地址。
要获得更完整的列表,请使用第二种方法。它需要安装 nmap,即“网络映射器”的缩写。同样在 Ubuntu/Debian 上,你应该能够安装它
sudo apt-get install nmap
一旦安装完毕,你会想要使用选项-sn
,它代表无端口扫描。在 nmap 的旧版本中,可以使用选项-sP
来代替-sn
。此选项通常被称为“ping 扫描”。
完整的命令如下,确保使用 root 权限和sudo
(否则结果会不同):
sudo nmap -sn 192.168.1.0/24
前面的命令假设您的网络正在使用 IP 范围192.168.1.*
;在某些情况下,第三个数字可能不同。如果您没有从nmap
ping 扫描中得到任何结果,您应该手动检查您的网络正在使用的 IP 范围。在这种情况下,您可以通过运行(“a
”是地址的简称)来查找
ip a
在结果中,查找带有无线或以太网接口的部分(取决于您使用的接口),并在本地网络中查找您自己的 IP。以我为例,我的无线接口叫wlp3s0
,我的本地 IP 地址范围是 192.168.30。*如图 7-1 所示。
图 7-1
使用ip a
查找本地使用的 IP 地址
所以在我的情况下,我实际上需要运行
sudo nmap -sn 192.168.30.0/24
该命令中的0/24
指定了 CIDR 符号的范围。用nmap
指定范围有三个选项:
-
cid 符号( 0/24
-
范围( 1-5 )
-
通配符( *** )
因此,相同的命令可以表示为
nmap 192.168.1.0/24
nmap 192.168.1.0-255
nmap 192.168.1.*
Note
想观看网络直播吗?在运行nmap
之前,打开第二个终端并运行ip monitor
。这将使你能够实时观看网络上发生的一切。或者,如果您只想查看活动表单nmap
,您可以在命令中添加-d
标志。
查看开放端口
一旦你有了一个设备的 IP 地址,你经常想看看哪些端口是开放的。这也适用于服务器,毕竟服务器只是位于互联网上某个 IP 地址的设备,与本地计算机、智能手机或物联网设备没有什么不同。这可能会派上用场的情况包括
-
根据开放端口判断网络上的设备类型
-
寻找可能被黑客利用的开放端口
-
找到一个可以在浏览器中访问的开放端口,或者通过其他方式进行设备交互
因为我们之前安装了nmap
,我假设你已经安装了它。
扫描设备开放端口的最常见方法是简单地使用 nmap,后跟要扫描的设备的 IP 地址。例如,使用前面的提示,我能够发现我的酒店的路由器的 ip 地址是 192 . 168 . 1 . 1;然后,我将使用以下命令来查找开放端口:
nmap 192.168.1.1
在我的例子中,输出如下:
Host is up (0.82s latency).
Not shown: 999 closed ports
PORT STATE SERVICE
80/tcp open http
Note
从nmap
获得这种输出依赖于设备实际上位于您输入的 IP 上。可能192.168.1.1
不是您网络上的任何设备。
它显示端口 80 是打开的;这是基本的 http 端口,基于 web 的界面在此为路由器的设置面板提供服务。
您可能希望检查您自己的计算机上打开了哪些端口;你可能会惊讶于你的发现:
nmap localhost
需要指出的是,默认情况下,nmap 仅扫描指定设备上 1000 个最常用的端口。当服务器或设备想要谨慎时,可以使用不太流行的端口。如果你真的想扫描所有可能的端口,你应该使用-p-
标志,例如:
nmap -p- localhost
这将扫描所有 65535 个端口,也就是说,是默认端口的 65 倍以上,因此需要很长时间才能完成。
同样的方法也可以用在网址上,例如:
nmap -p- example.com
这将为 example.com 返回服务器上开放的端口。在撰写本文时,只有端口 80 和 443 是开放的——端口 80 用于 http 流量,端口 443 用于 https。稍后,我将列出一些最常见的端口及其最可能的用途。牢记“最有可能”这句话;没有什么可以阻止服务器使用一个通常用于一件事的端口来做另一件事。一些最常用的端口如表 7-1 所示。
有时,有人可能会在意外的端口上运行服务,例如,在端口 80 而不是端口 22 上运行 ssh,以破坏不允许 SSH 的限制性网络策略。防火墙阻止端口 22,试图阻止在网络上使用 ssh,但是如果服务器侦听端口 80(通常用于 web 流量),这种阻止方法就会失效。
表 7-1
通常易受攻击的端口
|通道数
|
多畜共牧
|
| — | — |
| Eighty | 超文本传送协议(Hyper Text Transport Protocol 的缩写) |
| Four hundred and forty-three | 安全超文本传输协议 |
| Twenty-one | 文件传送协议 |
| Twenty-two | 嘘 |
| Twenty-five | 简单邮件传输协议 |
| One hundred and thirty-five | Windows RCP |
| One hundred and thirty-seven | 网络基本输入输出系统(Network Basic Input / Output System) |
| Three thousand three hundred and six | 关系型数据库 |
| Three thousand three hundred and eighty-nine | 远端桌面协定 |
在非默认端口上运行服务的另一个常见用途是避免利用 bot,这些 bot 可能会使用这里使用的扫描技术。例如,假设有人正在大规模扫描 IP 地址,以查找运行在默认端口 3306 上的 MySQL 实例;在端口 7777 上运行服务的服务器将不会被检测到。尽管像 MySQL 这样的东西,最好的策略是对公众完全关闭端口,只对需要它的内部应用开放。对于 SSH 之类的东西,您可能没有完全关闭端口的选项。正是因为这个原因,SSH 密钥认证比密码认证更受推荐,因为它使得暴力攻击几乎不可能。
如果您想查看一个更完整的列表,您可以解析列出了nmap
已知的所有服务的/usr/share/nmap/
文件。列表太长,没有用,所以您可能会发现删除所有标记为未知的条目是有用的:
cat /usr/share/nmap/nmap-services | grep -v unknown
即使在删除所有未知条目后,我们仍然得到超过 12,000 个结果。我建议颠倒线路,从编号较低的端口开始。你可以通过将前面的命令输入tac
( cat
命令,行颠倒)来实现:
cat /usr/share/nmap/nmap-services \
| grep -v unknown \
| tac
这样,您可以从端口 1 开始向上滚动。或者,你可以通过管道将结果输入到’less
’,该功能在第一章中探讨,通过简单的滚动来查看结果。
设备和端口
如果您想扫描本地网络上的所有设备,并扫描这些设备上的开放端口,您可以将前面的两个提示合并到一个命令中。
这既可以用简单但缓慢的方法,也可以用快速的方法。
简单但缓慢
简单但缓慢的方法是,通过在 IP 范围而不是 IP 上运行nmap
,在一个步骤中简单地对整个过程使用 nmap。这意味着将对指定范围内的所有 IP 尝试 nmap 如果您想扫描所有端口而不是 1000 个最常用的端口,只需添加-p-
:
sudo nmap 192.168.1.0/24
Note
根据您的网络,这种方法可能会非常慢。
快速方法
更快的方法是使用 arp-scan 获取 IP,grep 提取 IP,最后使用xargs
和nmap
对每个 IP 执行扫描。看起来是这样的:
sudo arp-scan --localnet \
| grep -o \
'[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}' \
| xargs nmap
操作系统检测
如果您从结果中发现一些有趣的机器 IP 地址,您可以让nmap
尝试猜测机器上运行的操作系统:
sudo nmap -O <ip-address>
如果您想检测使用上一节中的脚本扫描的每个设备的操作系统,您可能需要使用--osscan-limit
来将操作系统检测扫描限制在有希望的目标上。或者如果你想让nmap
更积极地猜测操作系统并显示最接近的匹配,使用--osscan-guess
。
用 masscan 扫描互联网
Masscan 是一款互联网规模的端口扫描器,适用于互联网或内部网络的大规模调查。虽然默认传输速率仅为 100 包/秒,但它可以选择高达 2500 万包/秒,这一速率足以在 3 分钟内扫描一个端口的互联网。
—masscan 手册页
Note
与nmap
一样,如果您想获得最新的特性(例如- top-ports flag ),您将希望从源代码构建masscan
,尽管在大多数包管理器中都有一个旧版本。你可以在 www.github.com/robertdavidgraham/masscan
找到出处。
Masscan 是一个与nmap
非常相似的工具,但它是后来发布的,能够以更快的速度扫描端口。在这两者之间切换很容易,因为masscan
使用了与nmap
兼容的语法。您甚至可以通过运行以下命令获得masscan
和nmap
之间相似特性的列表
masscan --nmap
虽然masscan
比nmap
快得多,但它的功能较少,也不太准确。通常masscan
将用于初始侦察以寻找目标,一旦目标被选定,nmap
将用于更大的准确性和细节。
当使用masscan
时,您可能会注意到它的运行速度比手册页中描述的最大速度慢得多。这是因为还有其他几个限制masscan
运行速度的因素,包括你的路由器上传和下载流量的速率。
也就是说,我们可以运行一个相当于nmap
的脚本来进行比较:
time sudo masscan --top-ports 192.168.1.0/24
完成后,尝试nmap
中的相同操作:
time sudo nmap 192.168.1.0/24
您会发现masscan
运行速度明显更快,因为它在发送下一个请求之前不等待响应,尽管一旦发现设备,它仍然必须扫描每个端口以找到哪些端口是打开的。
正如描述中提到的,默认速度是每秒 100 个包,尽管可以一直提高到每秒 2500 万个包。该速率将受到网络和设备处理能力的限制。如果你想改变速率,使用--rate
标志,例如:
sudo masscan -p 22 --rate 1000 192.168.1.0/24
当扫描公共范围时,要小心,因为向非常大范围的 IP 发送大量的无限制信息可能会触发您的互联网服务提供商的危险信号。可能更好的方法是 SSH 到一个便宜的服务器上,然后从那里高速测试大型扫描。
使用 nmap 运行脚本
除了扫描端口和检测操作系统,nmap
还通过脚本模块提供高级功能。默认情况下,程序附带了很多这样的脚本,还可以从头开始安装或编写其他脚本。要获得nmap
附带的脚本的完整列表,请查看usr/share/nmap/scripts
文件夹:
ls /usr/share/nmap/scripts
在撰写本文时,默认情况下,nmap
附带了超过 600 个预先编写好的脚本。
Note
从apt-get
或其他包管理系统获得的版本可能不是最新的,因为nmap
仍然是一个非常活跃的项目。您可以在 www.github.com/nmap/nmap
找到最新版本。
要使用脚本,只需像下面这样传递带有--script
标志的脚本:
nmap --script http-headers example.com
在这个例子中,我们使用了一个脚本来获取 example.com 的 http-headers;您的结果应该包括端口 80 和 443 的报头,如图 7-2 所示。
图 7-2
http-headers nmap 脚本中的标头信息
traceroute 脚本
一些像前面提到的脚本可以直接运行。其他选项可能需要与其他选项结合使用。例如,traceroute-geolocation
处理来自--traceroute
标志的数据。所以使用这个脚本需要:
sudo nmap --traceroute \
--script traceroute-geolocation example.com
--traceroute
标志用于跟踪所有跳或中间路由器;结合traceroute-geolocation
,我们可以得到沿途每个路由器的地理位置。图 7-3 显示了使用--traceroute
标志的结果示例。
图 7-3
使用 nmap - traceroute 查看服务器的位置
http-enum 脚本
编写http-enum
脚本是为了测试网站的几个路径,以检测可能提示服务器上正在运行什么应用或内容管理系统的信息。
sudo nmap --script http-enum example.com
http-enum
也是一个可以传递参数的脚本示例。如果您希望脚本使用一个基本路径运行,例如,example.com/blog
而不是website.com
,您可以这样做
sudo nmap --script http-enum --script-args \
http-enum.basepath='blog/' example.com
为 nmap 编写自己的脚本
nmap
附带了许多有用的脚本,这些脚本对于使用它进行端口扫描功能的大多数人来说是相对陌生的。更鲜为人知的是,您实际上可以通过编写 NSE 文件并将其放在 scripts 文件夹中来创建自己的脚本。
NSE 代表 Nmap 脚本引擎,是一种特定于领域的语言,构建在 Lua 编程语言之上。如前一节所述,脚本可以用于各种用途,包括
-
网络发现
-
版本/操作系统检测
-
漏洞检测
-
后门检测
-
漏洞利用
每个 NSE 在一个文件中包含三个部分:
-
页眉
-
规则
-
行动
头部分通常包含一个描述并导入任何需要的库。一个非常简单的例子是
-- Header --
local shortport = require "shortport"
前面的脚本导入了 shortport 库,该库可用于确定端口是否属于服务类型。标题之后是规则部分。我们的示例应用将使用 shortport 库来检查端口是否是 http:
-- Rule --
portrule = shortport.http
接下来是剧本的动作部分。我们将告诉脚本在端口是 http 常用端口的情况下应该做什么:
-- Action --
action = function(host, port)
return "Hello World!"
end
写完这三节,保存你的脚本,另存为/usr/share/nmap/scripts/testing.nse
。然后在网站上运行以下内容:
sudo nmap --script testing <website.com>
如果您已经正确地复制并运行了脚本,您应该会在任何找到的 http 端口下看到一个子部分,如图 7-4 所示。
图 7-4
示例脚本的输出
我们的“hello world”NSE 脚本不是特别有用,但它为您提供了 NSE 脚本的三个主要部分的概要(标题、规则、动作)。如果你想尝试制作一个高级的 NSE 脚本,看看/usr/share/nmap/scripts
中的其他预构建脚本;这些为构建您自己的脚本提供了很好的示例或起点。
wireshark/tshar
另一个值得了解的工具是 Wireshark,我们不会在这里深入讨论。这是一个用于数据包分析的全功能 GUI 应用。它允许您捕获和分析网络上的流量。Wireshark 有一个面向终端的版本叫做tshark
。大多数包管理器上都有这两个版本。如果您想要 Wireshark 的体验,但没有在机器上访问 GUI 的权限,您也可以查看社区项目termshark
,它在终端中模拟 Wireshark 的 UI。
Wireshark 通常用于信息安全、网络质量测试和网络使用软件的质量保证。
虽然arp-scan
和nmap
是查找网络设备最简单的工具,但 Wireshark 在查找可能隐藏的设备方面实际上更强大。例如,如果一个设备不响应任何请求,nmap
、masscan
、arp-scan
和ping
将永远无法找到它,即使有 IP。但是,如果这些设备在某个时候想要使用网络,并且 Wireshark 正在进行记录,它们将会被发现,并且它们的存在会为人所知。
要查看使用tshark
的所有流量,只需在没有任何选项的情况下运行它(需要 root 权限):
sudo tshark
根据您的网络,这将返回显示网络流量的快速滚动屏幕,类似于图 7-5 所示。
图 7-5
运行 tshark 时的输出示例
随着流量的快速移动,将输出保存到文件中通常更有用:
sudo tshark > /tmp/output.txt
该命令将一直运行,直到您按下“ctrl+c”取消。运行的时间越长,样本量就越大。稍后可以解析该文件以提取更具体的细节,并按照您自己的速度进行分析。
如果您想更具体地了解所记录的数据包,tshark
有各种各样的过滤器,例如,如果我们想查看特定的设备:
sudo tshark host <ip-address>
如果您要解析结果来查找单个设备,这将节省您大量的时间和精力。您还可以按流量类型进行过滤,例如,仅显示 http 流量:
sudo tshark -Y http
您可以使用以下命令显示 http 请求的完整路径
sudo tshark -Y http.request.full_uri
对于tshark
和 GUI 等价物Wireshark
,有各种各样的过滤器。我们不会深入研究所有这些工具,但如果您想分析本地网络流量,这是一个值得研究的强大工具。另外,在 GUI 版本中,Wireshark 是主版本。这是一个非常有用的工具,有很多关于如何使用它的书。
更多网络工具
到目前为止概述的工具经常会派上用场,但是它们只是 Linux 上可用的网络工具的一小部分。表 7-2 是一个更长的 Linux 网络工具列表,你可以更深入地研究。
Note
我们在列表中包括了几个不推荐使用的实用程序。虽然不再对它们进行维护,但它们仍然在旧系统上广泛使用,或者由继续使用它们的系统管理员使用。出于这个原因,它们是值得注意的,尽管我们会确保列出最新的替代方案。
表 7-2
网络实用程序
|通道数
|
多畜共牧
|
| — | — |
| 挖苦 | 获取域信息 |
| 显示网络连接 | 网络统计数据(已弃用) |
| 命令 | 列出系统网络接口(已弃用) |
| 阿尔普 | 使用 ARP 缓存(不推荐) |
| 途径 | 显示/操作 IP 路由表(已弃用) |
| 互联网协议(Internet Protocol 的缩写) | 显示/操作路由、网络设备、接口和隧道 |
| 悬浮物 | 套接字统计 |
| ngrep | 就像grep
但是对于网络流量 |
| 显示路由信息 | 查找数据包到达服务器的路由 |
| 平均拆卸时间(Mean Time of Remove) | 网络诊断工具 |
| (美国)北卡罗来纳州 | “ncat”的缩写,类似于cat
,但用于网络数据。也可用作其他程序的网络接口模块 |
| 神经原纤维紊乱 | 用于包过滤和分类的网络工具 |
| 防火墙 | 管理防火墙设置(已弃用) |
| sysctl | 在运行时配置内核参数(一些与网络相关,如套接字缓冲区大小 |
| ethtool | 分析以太网连接 |
| 谁是 | 获取域名的 whois 信息 |
| lsof | 查找哪些程序正在使用哪些端口 |
| 平 | 与 ping 类似,但有更多的方法和选项 |
| 惊呆 | “窝猫”的简称,像nc
( 网猫)但是有更多的特性 |
挖苦
Dig 是一个 DNS 查找工具。如果您的系统上没有安装它,您可以在基于 Debian 的软件包管理器上的dnsutils
和 Fedora、CentOS 和 Arch 上的bind-utils
中找到它。
Dig 的使用方法是将一个 web 域作为参数传递给它,它将返回网站上的 DNS 信息。如果没有选项,来自dig
的信息会有些混乱并且缺少条目。我们建议使用选项+noall
和+answer
:
dig +noall +answer
Dig 应该返回该域的所有 DNS 条目。我们在图 7-6 中的例子包括一个对 example.com 的查询和另一个对 yahoo.com 的查询。我们包含了第二个查询来展示一个域有多个 A 记录时的输出示例。
图 7-6
对 example.com 和 yahoo.com 的质疑
Netstat(已弃用)
Netstat 是一个多用途实用程序,用于检查网络连接、路由表、网络接口统计和其他网络诊断。虽然您可能仍然会看到对netstat
的引用,而且它确实有效,但是它已经被弃用了。
由于netstat
已被弃用,建议您使用替代它的实用程序,包括dig
、ip
和ss
。
ifconfig(已弃用)
像netstat
一样,实用程序ifconfig
已经被弃用。尽管如此,您可能会发现它存在于许多机器上,并可能在脚本中使用。这是一个使用网络接口的工具。建议您使用iproute2
包附带的ip
命令。
如果您还记得本章前面的内容,我们使用了命令ip a
来找出网络 IP 范围。在ip
成为这方面的首选工具之前,运行ifconfig
也是用来做同样的事情。ifconfig
还能够与接口交互,例如,启用或禁用接口(假设您的以太网接口名为 eth0):
ifconfig eth0 up
现在同样的事情可以通过使用ip
来完成
ip link set eth0 up
arp(已弃用)
arp
代表地址解析协议,用于将设备的 MAC 地址(全球唯一标识号)映射到 IP。计算机包含一个 ARP 表,映射映射和 IP 地址。要查看表中的所有条目,请运行以下命令:
arp -a
由于arp
现在已被弃用,建议您使用ip
来实现相同的功能。与前面的ip
函数等价的是
ip n
其中n
是邻居的简称。有关更多高级功能,请参见arp
或ip
的手册页。
路线(已弃用)
route
命令用于显示/操作 IP 路由表。带有’'的最简单命令是不带任何选项或参数运行它,这将返回 IP 路由表。与ip
等效的命令如下:
ip r
其中r
代表路线。
互联网协议(Internet Protocol 的缩写)
如前所述,ip
实用程序是包括ifconfig
和route
在内的几个实用程序的替代品,它包含在iproute2
包中。运行ip route
或简称ip r
可以看到路线。还有另外的路由命令用于添加或删除,如ip route del unreachable 10.1.0.0/24
,其中“不可到达”是路由名称,“10.1.0.0/24”是路由。
悬浮物
ss
是一个监控套接字使用的实用程序。名字中的首字母代表套接字统计。如果没有安装ss
,你可以在iproute2
包含的大多数包管理器中找到它。当独立运行ss
时,您将得到一个所有已连接插座的长列表,如图 7-7 所示。为了使读取输出更易于管理,您可以通过运行ss | less
将结果传输到less
。
图 7-7
运行ss
返回的套接字统计示例
理解默认情况下所有这些套接字是什么有点困难。为了使事情变得简单,您可以添加标志-p
,它将告诉您每个套接字连接的进程名称和 ID。这允许您将套接字连接与机器上运行的进程相关联。
ngrep
ngrep
是一个网络实用程序,它提供了类似于grep
的解析网络数据的能力。给定一些要监听的特定文本,ngrep
将监控网络流量并报告任何匹配的连接数据。例如,我们将查看访问 example.com 产生的流量;首先,我们将告诉ngrep
监听字符串“example ”,如下所示:
sudo ngrep example
ngrep
现在正在解析网络流量中的字符串“example”。如果您在 web 浏览器中查看 example.com,应该会看到匹配结果。为了演示 https 的重要性,让我们使用curl
向示例发送一些未加密的数据。在ngrep
仍然运行的情况下打开第二个终端,并运行以下命令:
curl --data "user=name&password=secret" example.com
您应该在运行ngrep
的窗口中看到该请求。如果您仔细阅读文本,您应该能够看到用户和密码字段,如图 7-8 所示。
图 7-8
使用 ngrep 记录的未加密数据
如果运行相同的命令,但指定 https,如下所示
curl --data "user=name&password=secret" https://example.com
您仍然可以看到请求,但是看不到发送的数据,甚至看不到访问的具体网站。
显示路由信息
traceroute
实用程序允许您向主机发送数据包,并获得到达主机的路由的详细信息。这听起来可能很熟悉,因为在第七章中,我们使用了一个“traceroute
”NES 脚本来查看流量从我们的本地机器到一个网站的跳数。如果我们运行“traceroute
”实用程序,它将作为一个独立的实用程序提供此功能
traceroute example.com
我们将看到我们的数据包在到达最终目的地之前所经过的所有机器的 IP 地址。这从本地路由器开始,到实际网站的 IP 地址结束,如图 7-9 所示。
图 7-9
使用 traceroute 显示通往 example.com 的路线
平均拆卸时间(Mean Time of Remove)
mtr
实用程序是一个结合了ping
和traceroute
的网络诊断工具。名称mtr
实际上是“我的跟踪路线”的缩写mtr
不是像traceroute
那样发送一组数据包,而是在接收到前一个数据包后继续发送额外的数据包(类似于ping
)。如图 7-10 所示,一个更新显示屏显示关于定时的详细信息。如果你的连接有问题,mtr
可以帮助你了解问题出在哪里。
图 7-10
不断更新港铁显示的 example.com 路线数据
(美国)北卡罗来纳州
nc
是 network cat 的简称,名字灵感来自cat
实用程序。nc
是一个强大的工具,它提供了通过 TCP 或 UDP 连接和监听连接的能力。这意味着它甚至可以用于在两台机器之间打开一个聊天或文件传输的通道(尽管 SSH 等其他工具是首选)。
nc
通常被称为“网络的瑞士军刀”,可用于多种网络任务,包括端口扫描、服务网站或欺骗报头。虽然许多用例有更好的选项,如用于端口扫描的nmap
,但它对于一些简单的事情仍然有用,如抓取报头或伪造自己的报头。
要伪造您自己的标题,请运行
nc example.com 80
然后,您将能够添加额外的文本。您可以基于以下示例创建欺骗标头:
GET / HTTP/1.1
Host: example
Referrer: duckduckgo.com
User-Agent: fake-browser
输入标题后,按两次回车键,你将使用伪造的标题获取网站。您将得到一个包含站点标题信息的响应。
NFL–不可战胜
nftables
是用于包过滤和分类的 nftables 框架的管理工具。虽然你可以在包管理器上找到这个名字下的nftables
,但是运行它的命令实际上是nft
。nftables
中的“nf”代表“网络过滤器”,它们用于过滤网络流量。可以是传出的也可以是传入的。例如,您可能不允许特定 IP 的传出流量,或者不允许特定端口的传入流量。nftables
通过跟踪一系列系统范围的规则来工作,这些规则可以添加或删除,并在流量过滤过程中使用。
iptables(已弃用)
iptables
工具已经被弃用,取而代之的是nftables
。iptables
是基于规则的,但缺乏nftables
所包含的功能,比如用一个规则同时针对 ipv4 和 ipv6 数据包。
sysctl
sysctl
用于在运行时配置内核参数。这不一定仅仅是网络问题,尽管有些问题是如套接字大小。对于经常发送和接收大文件的服务器,可以这样做,因为调整套接字缓冲区大小可以提高特定用例的网络性能。
ethtool
ethtool
实用程序是以太网工具的缩写,可用于获取有关以太网连接的详细信息。这包括数据传输本身和物理硬件。要查看以太网接口的信息,您首先需要获得它的名称。这可以通过运行
ip a
记录您的以太网接口的名称(可能包含一个“e”),并将其作为参数传递给ethtool
:
ethtool enp0s25
在我的例子中,以太网接口名称是“enp0s25 ”,但您的接口可能会不同。以太网接口最常见的名称之一是“eth0”。当你使用接口作为ethtool
的参数时,你应该得到关于硬件的信息(即使你没有主动使用以太网),如图 7-11 所示。
图 7-11
从ethtool
输出的以太网接口信息
谁是
whois
是一个用于检索注册服务商提供的网站所有权信息的实用程序。只需提供一个域作为参数就可以使用它。例如,运行以下命令应该会返回如图 7-12 所示的所有权和联系信息:
图 7-12
yahoo.com 的 whois 信息
whois yahoo.com
lsof
lsof
代表“打开文件列表”;默认情况下,它会返回一个很长的列表,其中包括系统中所有打开的文件。在网络方面,你想知道的关于lsof
的主要选项是-i
旗帜。-i
标志告诉lsof
寻找 IP 套接字。添加-P
来连接端口也是有用的。要演示,请尝试跑步
lsof -i -P
这将返回一个本地端口列表,这些端口连接到远程服务器上的端口以及与所述连接相关的程序。预期输出的示例如图 7-13 所示。
图 7-13
来自lsof -i -P
的示例输出
平
hping
是一个攻击性的安全网络工具,它的名字来源于ping
。像ping
一样,它通过网络向目的地发送数据包,但它有高级选项,允许定制数据包,为 TCP 和 UDP 指定目的地端口和假冒的源 IP。此外,它有一些内置的方法,如--flood
选项,可用于类似 DDOS 的攻击,如 SYN flood 攻击。
当前版本是 3,集成在大多数包管理器的命令和名称中:
sudo apt-get install hping3
在 Kali Linux 这样的攻击性安全操作系统上,你会发现默认安装了hping
。后面显示了 SYN flood 攻击的一个示例。SYN flood 攻击包括在没有完成握手的情况下打开几个连接。它可以用来测试您的网络是否免受这些攻击;以下是一个执行 SYN flood 攻击的示例,用于测试网络中目标设备使用的 IP 交换机:
hping3 --rand-source -S -d 500 -p 21 --flood 127.168.1.110
前面的命令结合了几个选项。第一个--rand-source
告诉hping
伪造一个随机的 IP 地址作为其来源。然后-S
标志指定 SYN 包网络,-d 500
是包的大小,-p 21
是目的端口,最后--flood
开启发送许多请求的洪泛模式。
惊呆
socat
类似于nc
(netcat),但具有更高级的功能。也像 netcat 一样,它的名字取自cat
,代表“socket cat”它可以在大多数包管理器上找到,名为socat
。用 netcat 可以做的任何事情用socat
都是可能的,但是它也有一些额外的特性,比如单个端口上的多个客户端和使用 UDP 的选项。
摘要
在本章中,我们学习了一些网络技术,尤其是与端口扫描相关的技术。我们还简要介绍了一些流行的网络工具,这些工具可用于通过分析、配置和打开通信通道来处理网络。
八、系统监控
在维护 Linux 系统时,您会发现自己想做的另一个常见任务是监视系统进程、内存和网络使用等情况。这有助于您衡量您正在利用多少容量。了解哪些资源可能不足,可以让您深入了解如何降低系统负载,或者应该增加哪些资源。在这一章中,我们将看看进行不同类型监控的工具。
顶端
每当系统或设备遇到性能问题时,首先要做的事情之一就是检查哪些程序正在运行以及它们使用了多少系统资源。简单的方法是安装在大多数 Linux 系统上的top
。运行它将列出所有当前正在运行的进程。通过按下z
并输入目标进程的进程 ID (PID ),您可以在不离开top
的情况下快速终止一个进程。
如果你发现自己经常使用top
,你可以考虑安装htop
。htop 是top
的增强版,具有改进的可视化界面,并显示了流程的完整路径。
如果你更喜欢使用像top
这样的内置工具,或者你在一台不能安装htop
的机器上,你实际上可以使用键盘命令的组合来获得看起来几乎和htop
一样的东西,在某些方面甚至更好。
在顶部打开的情况下,按下zxcVm1t0
(作为一个序列,而不是同时),你将得到看起来如图 8-1 所示的东西。
图 8-1
运行后顶部zxcVm1t0
我们可以通过按A
进入交替显示模式来更进一步;这将屏幕分成四个独立的字段组。一旦进入交替显示模式,您可以通过按下g
在字段组之间切换,这将提示您输入字段编号。如果你在每个字段组之间切换并输入zxcVm1t0
,你将得到一个整洁的多字段显示,如图 8-2 所示。
图 8-2
风格多样的多标签顶部
当然,你可能认为这看起来很棒,但是每次打开top
都要运行很多步骤。要保存这些设置,您只需按下W
即可。这将保存您在top
中的当前配置,当您重新打开它时,它看起来会是一样的。
如果您想回到默认值,只需删除创建的配置文件;默认应该是~/.toprc
。
类似 Top 的程序
有几个受top
启发的程序,或者监控top
中没有的系统的某些特定方面,或者以不同的布局提供相同的信息。在这一部分,我们将回顾一些名字和格式都来自top
的流行节目。
快上来
这是一个非常类似于top
的程序,与top
相比,它默认提供了一个改进的图形界面,如图 8-3 所示。它不是默认安装在大多数发行版上的,但是可以通过许多包管理系统获得,比如 Debian/Ubuntu 上的apt
。
图 8-3
htop 以默认设置运行
在顶上
这是一个类似于top
的高级系统和过程监视器,但适用于长期运行的分析。它提供了将系统监控结果作为日志文件输出以供分析的能力。如图 8-4 所示,它有一个简单的循环,但提供了top
或htop
中没有的导出为日志的功能。
默认情况下,它没有预装在大多数发行版中,但是它在包括 Debian 和 RHEL 在内的软件包管理系统中广泛存在。
图 8-4
使用默认设置运行
默认情况下,atop
中的日志文件将被保存到文件夹/var/log/atop/
中。这些日志文件可以通过用如下所示的-r
标志传递给atop
来读取,除了用您想要打开的日志的文件名替换atop_20200310
:
atop -r /var/log/atop/atop_20200310
iftop
这是受top
的启发,但专门监控网络使用,而不是 CPU 或内存使用。当给定一个网络接口时,它将侦听所有传入和传出的流量,并提供诸如起始端口和哪些外部服务器使用网络最多之类的信息。由于访问网络接口,使用iftop
需要sudo
权限。
默认情况下,它不会安装在大多数发行版上,但是可以广泛使用。我们将在本章后面的监控网络流量部分进一步研究这个程序。
恩通普
一个比iftop
更高级的选择是ntop
,它也监控网络流量。然而,与这里的其他程序不同,它是一个基于 GUI 的系统,可以通过浏览器访问。虽然这使得它不那么轻量级,但它确实提供了一些更高级的可视化,如图 8-5 所示。
不像到目前为止提到的其他程序,你不会在包管理器上找到带有标准名称的ntop
。相反,你会发现它的名字是ntopng
:
图 8-5
ntop 中的应用页面
sudo apt-get install ntopng
一旦安装并启动,它将在端口 3000 上运行,并提供几个基于网络使用的统计和可视化管理页面。
iotop
这是另一个受top
启发的程序,它专注于文件系统的读写使用。线程按磁盘读取和磁盘写入使用的顺序列出。这个包在基于 Debian 和基于 RHEL 的系统上都广泛可用。像iftop
使用iotop
将需要sudo
权限才能运行。iotop
包含每个进程的基本信息,如用户和命令,以及磁盘写入和IO>
(这是一个进程花费在 IO 上的时间百分比的度量)。iotop
动作示例见图 8-6 。
图 8-6
io 以默认设置运行
slabtop
这是一个用于监控内核 slab 缓存信息的顶级程序,如图 8-7 所示。它主要对那些需要担心内核级问题的人有好处。
像iftop
和iotop
一样,使用slabtop
将需要sudo
权限。
图 8-7
slabtop 以默认设置运行
查看流程的更多信息
像top
和atop
这样列出的程序对于查看过程来说是很棒的。也可以使用ps
手动查询所有正在运行的任务,然后通过管道将它们传递给其他程序。当单独运行ps
时,您将获得当前终端会话中运行的进程列表。该列表可能很小,仅包括bash
和ps
工艺本身,如图 8-8 所示。
图 8-8
在新的终端中运行 ps
但是,如果您的终端已经打开了一段时间,并且您已经对一些进程进行了后台处理,您可能会看到更多。我们可以手动创建一个后台流程,通过以下步骤进行演示:
-
运行睡眠 500 秒,并在后台运行进程
sleep 500 &
。 -
运行
ps
并观察新流程。 -
从 sleep 命令中取出 PID,并使用 kill
kill 123
结束该过程。 -
再次运行
ps
并观察差异。
这些步骤应该导致一个额外的过程,由ps
返回sleep
,如图 8-9 所示。
图 8-9
有后台进程的 ps
当然,大多数情况下,您会希望看到机器上运行的所有进程,而不仅仅是当前终端会话中的进程。要获得所有正在运行的进程,您可以运行ps -e
或ps -ef
,不同之处在于添加的f
显示了更多细节。详细的ps
视图如图 8-10 所示。
图 8-10
运行 ps -ef 查看系统范围的进程
虽然我们可以使用grep
来按用户解析进程,但是ps
提供了一些内置的标志来简化这一过程,例如,ps -u philip
或者带有ps --pid 123
的特定 PID。这两者都可以和-e
一起使用来获得更多的细节。
终止一个进程
经常与ps
结合使用的命令有kill
和killall
。运行ps
时,我们看到有一列显示 PID,是进程 ID 的简称。如果一个进程运行不正常、挂起,或者我们只想结束它,一种方法是使用kill
命令。只需将 PID 传递给它,例如,假设 PID 为 123:
kill 123
如果你想通过名字而不是 PID 来匹配进程,你可以使用killall
,例如,如果 Firefox 被冻结,我们想强制退出:
killall firefox
另一个与killall
非常相似的选项是pkill
。pkill
也可以通过名称匹配服务,但是会包含更多的匹配,不像killall
如果使用-i
进行模式匹配,它不需要精确匹配。例如,如果我们只是传入“Firef ”,我们仍然会杀死进程:
pkill -i Firef
同样风格的命令可以和pgrep
一起使用,在不杀死进程的情况下找到进程。例如,如果我们在 Firefox 打开的情况下运行以下命令,我们将获得与该程序相关联的 PID 列表:
pgrep -i Firef
为了让前面的命令更有用一点,可以添加-l
标志来获取每个进程的确切程序名,或者添加-a
来获取更多信息。
用 pstree 可视化流程树
要记住的另一个概念是,流程存在于一个层次结构中,有些流程有父流程和子流程;这可以在图 8-11 中看到。例如,当您在终端中运行ps
时,它是终端进程的子进程。如果我们运行sleep 500
然后关闭终端,子进程sleep 500
将随着父进程的终止而自动终止。然而,情况并非总是如此;在某些情况下,子进程将在父进程关闭后继续运行,并继承父进程的父进程。
我们的终端进程本身是另一个进程的子进程,可能systemd
取决于您的 Linux 发行版。因此,如果一个进程在关闭终端后继续运行,在我们的例子中,新的父进程将是systemd
。
可视化这种关系的一个很好的工具是pstree
,它可以用来显示我们系统上运行的所有进程,就像ps
一样,但是以可视化的方式显示进程之间的父/子关系。尝试用-p
标志运行它,这将确保进程 ID 也被返回。它应该返回一个很长的进程列表,所有这些进程都源自左边 PID 为 1 的单个进程。
图 8-11
使用-p 标志运行 pstree 以显示进程 id
正如我们在终端中运行命令时提到的,它实际上是终端进程的一个子进程。要演示这一点,请运行以下命令:
sleep 500 &
pstree -p | grep -A 5 -B 5 pstree
这将在后台创建一个休眠进程,获取pstree
,然后为pstree
进程执行 greps,这样我们就可以找到当前的终端进程。-A
旗代表比对手高出五行,-B
代表比对手低五行。结果应该类似于图 8-12 所示。
图 8-12
点击 pstree 查看特定进程
注意以绿色突出显示的pstree
流程及其下方的sleep
流程。它们都源于 bash 过程,而 bash 过程本身又源于gnome-terminal
。
处理好价值
当使用top
时,你可能已经注意到标有“NI”的列。这指的是“好的”价值观,这是 Linux 中的一个关键概念。每个进程都有一个很好的值-20 到 19。数字越小,进程在调度中的优先级越高。一种思考方式是,好的进程(例如, 10 个好值)在队列中等待,而不好的进程插在前面( -20 个好值),真正好的进程( 19 个好值)让其他进程插在队列的前面。当然,这是一种简化,因为 nice 值是相对于队列中其他值而言的。
如上所述,您可以在列NI
下的top
中查看流程的 nice 值。另一种方法是使用带有-o
标志的ps
,后跟您想要查看的列(包括 ni
,例如:
ps ax -o pid,ni,cmd
这将返回所有运行进程的进程 ID、nice 值和命令,如图 8-13 所示。
图 8-13
用 ps 获取命令、PID 和 nice 值
请注意,在启动过程中启动的几个命令(我们可以知道,因为 PID 接近 1 )有一个很好的值-20,因为它们被认为是运行操作系统的关键。
您可能还会注意到一些标有-
的进程(取决于您的操作系统);这些是系统级的进程,由一组不同的优先级控制(它们总是先运行)。在大多数情况下,您不需要担心这些底层流程。
其他优先系统
如前所述,一些流程由不同的优先级集控制。我们在用户空间中主要关心的正常进程由SCHED_OTHER
控制。
其他主调度器SCHED_FIFO
和SCHED_RR
用于需要在所有正常进程之前运行的实时进程。这两个调度器具有相同的优先级,但调度方式不同。FIFO 代表先进先出(如先来先服务,RR 代表循环法(轮流,直到流程完成)。
如果您不在内核级工作,您可能不需要处理这些调度程序。如果您想了解进程的实时和绝对优先级值,可以运行
ps -e -o class,rtprio,pri,nice,cmd
从输出中,您会发现几个进程比那些被列为-20
nice 值的进程具有更高的绝对优先级;这些都是实时过程。
更改好的值
现在你知道了 nice,你是如何使用它的?您可以使用renice
命令更改任何正在运行的进程的 nice 值。通常,更改好的值不是一项常见的任务。然而,没有什么理由让你想这么做。比方说,您已经创建了一个自定义脚本,它通过压缩旧的日志文件并将其发送到长期存储服务来清理旧的日志文件。您可能希望为这个过程赋予一个很高的 nice 值,这样使用服务器的用户总是比备份过程具有更高的优先级,备份过程没有截止日期或紧迫性。
让我们创建一个流程来使用:
sleep 500&
获取返回的进程 ID(在我们的示例中是的 1234)并与renice
一起使用:
renice -n 19 1234
现在,如果我们使用ps
检查 nice 值,我们应该看到该值已经更新。
ps -o ni 1234
僵尸进程
在下一节中,我们将编译一个 C 程序来探索僵尸进程的概念。这有点技术性,关于僵尸进程的知识并不重要。如果您觉得这一部分太专业,请随意跳过。
本节将要求您安装 C 编译器和这里使用的库。它们都可以在基于 Debian 的系统上的build-essential
包中获得。
sudo apt-get install build-essential
在查看进程时,另一个值得理解的概念是僵尸。僵尸进程是一个已经退出的子进程,但是还没有被它的父进程清除。大多数程序在退出后会很快移除其子进程,所以僵尸进程相当罕见。尽管名字邪恶,僵尸进程是相当无害的,不会对你的机器性能产生负面影响。
为了演示,我们将创建一个 C 程序来制作我们自己的僵尸进程。
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main () {
// Create variable with type of process identification
pid_t child_pid;
// Fork main process creating a child
child_pid = fork ();
// Both main script and forked child run the code below the fork point
// Child process will have a PID of 0 within script
if (child_pid > 0) {
// Only parent process runs this section
sleep (500);
}
else {
// Only forked child runs this section, exiting immediately
exit (0);
}
return 0;
}
写完前面的 C 程序,另存为zombie.c
。接下来,您需要通过运行以下命令来编译它
cc zombie.c -o zombie
一旦你成功编译了zombie
,我们就可以演示僵尸进程是什么样子的了。运行可执行文件并在后台运行:
./zombie &
接下来,我们将使用前面的一些命令来查看该过程。不带选项的第一次运行ps
。您应该会看到父进程zombie
和子进程的条目,后面跟有<defunct>
,如图 8-14 所示;这表明该进程处于僵死状态。
图 8-14
创建僵尸进程
如果你要运行top
,你也会在右上角看到一个僵尸进程正在运行的提示,如图 8-15 所示。
图 8-15
在顶部查看僵尸数量
如前所述,僵尸进程是相当无害的,并且从技术上讲已经不运行了。因此,运行kill 7450
(基于图 8-14 中的进程 ID)将无效。杀死僵尸进程的唯一方法是杀死它的父进程。
kill 7449
当然,如果你想让这个程序继续运行,这是一个问题。我们的建议是让僵尸进程自己处理,因为它们通常不会引起问题。
检查可用磁盘空间
服务器或嵌入式设备的另一个常见问题是磁盘空间不足。我遇到过一些这样的情况,由于一个程序在几个月的时间里无法压缩或删除旧的日志文件,导致一个停止工作的设备没有足够的空间来写入数据。
检查可用磁盘空间最简单的方法是使用实用程序df
,它是“空闲空间”的缩写。要找到您的可用磁盘空间,请运行命令
df -h
前面的命令将返回包含每个分区信息的分区列表。其中一个分区将是您的系统使用的主分区。您可以通过查看“挂载于”列并找到值为“/”的那个来找到它。
接下来,您需要查看该分区的“大小”和“使用%”。这将告诉你有多少磁盘空间,以及目前使用的百分比。
关于df
返回的列的完整列表,参见表 8-1 。这个表还包括可以用-i
标志启用的 inodes used 列和用-T
标志启用的 type 列。
注意我们在前面的例子中使用了-h
标志;这代表“人类可读”如果没有-h
标志,df
仍然可以工作,但是以 KB 为单位显示可用空间,而不是将大量空间转换为 MB 或 GB。建议使用-h
,除非您有特定的原因需要 KB 中的所有值。
表 8-1
df 命令返回的信息
|圆柱
|
描述
|
| — | — |
| 文件系统 | 文件系统的名称 |
| 大小 | 分区的大小(默认情况下隐藏,用-h 显示) |
| 1K 块 | 以 1K 块为单位的系统大小(使用-h 时替换为大小) |
| 二手的 | 使用的空间量 |
| 有空的 | 可用空间量 |
| 使用% | 以百分比显示的已用空间量 |
| 安装在 | 分区的目录位置 |
| IUsed | 分区上使用的索引节点(默认情况下隐藏,使用-i 显示) |
| 类型 | 分区文件系统类型(默认情况下隐藏,用-T 显示) |
查找系统中最大的文件
如果您发现系统空间不足,您可能希望在系统中搜索大文件。这里有一个超过 100 米的例子:
sudo find / -xdev -type f -size +100M -exec ls -la {} \; \
| sort -nk 5 \
| tac
前面的命令假设您想要查看系统上的每个文件。如果您想只包含特定文件夹中的文件,您可以修改find
命令的第一个参数,例如,假设我想只搜索用户 philip 的文件夹中的文件,那么我将使用
sudo find /home/username -xdev -type f \
-size +100M -exec ls -la {} \; \
| sort -nk 5 \
| tac
如果您只想查找总容量超过 1gb 的文件和目录,您可以这样做
sudo du -ahx / | grep -E '\d*\.?\d*+G\s+'
Note
通过组合-size
和-printf
标志,也可以用find
获取和打印尺寸;但是,find 只显示以 KB 为单位的大小,与 GB 相比很难阅读。详见man find
。
监控设备网络使用
您可能想要检查的另一个统计数据是系统整体的网络使用情况,以及按进程或网络接口的细分情况。这在互联网接入受限或带宽昂贵的设备上非常有用,例如,通过 GSM SIM 卡连接的物联网设备甚至笔记本电脑。在这种情况下,使用过多数据的程序会非常昂贵。
即使您不在数据有限的系统上,查看哪些程序正在使用您的互联网连接也会很有用。如果你看到一些让你吃惊的事情,你可能想进一步调查。我用了几个不错的程序来进行网络监控,每个程序都略有不同。
bmon–监控每个网络接口
使用 bmon,您可以监控每个接口(例如,Wi-Fi、以太网)。这在前面描述的 GSM SIM 卡情况下非常好。想象一下,你有一台同时支持 Wi-Fi 和 5G 的设备。你可能不介意 Wi-Fi 接口上的高网络使用率,但会希望确保 5G 使用保持在一定水平以下。
在这种情况下,您可以编写软件来检测正在使用的互联网接口,并根据连接类型减少或增加数据使用。bmon
通过分解每个接口上传输的数据量,为您提供了一种确保这些措施切实有效的方法。
默认情况下不会安装,但大多数软件包管理器上都有。当在终端运行bmon
打开时,你会看到如图 8-16 所示的界面。如果您的终端窗口没有最大化,底部的绿色/红色图形可能会被隐藏。
图 8-16
运行 bmon
nethogs 按带宽使用列出程序
大多数时候,你不会对正在使用的接口感兴趣,而是想知道哪些程序使用了最多的带宽。为此安装并运行nethogs
;你会看到如图 8-17 所示的界面。请记住,如果您关闭该程序,当您稍后打开它时,它将再次从头开始。为了清楚地了解一段时间内的使用情况,您需要打开nethogs
并让它运行一段时间。几个小时甚至几天后再回来,您会更清楚哪些程序使用了最多的带宽。
图 8-17
运行网络猪
iftop
另一个选择是iftop
,这是顶级家族的另一个项目。iftop
让我们可以根据流量大小来监控哪些外部 IP 地址的通信量最大,而不是通过接口或应用进行监控。
启动iftop
时,需要指定网络接口。如果您不知道您的网络接口,您可以通过运行
ip a
您将得到一个包含大量细节的接口列表;接口是左边的键值。在我这里,Wi-Fi 接口叫做wlp3s0
,如图 8-18 。你通常可以分辨出哪个接口是 Wi-Fi,因为它会包含一个“w”。
图 8-18
从ip a
返回的 Wi-Fi 接口
一旦有了想要监控的接口,就用-i
标志将其传递给iftop
:
sudo iftop -i wlp3s0
这将产生一个外部 IP 地址列表以及正在上传和下载的数据量,如图 8-19 所示。
图 8-19
使用 iftop 监控 Wi-Fi
为了让事情变得更清楚,你可以按下s
来隐藏左边的信号源(因为它们大部分是本地信号源)。然后按p
显示始发端口。Port 比 source 有用得多,因为它让我们对原始程序有了更好的了解,并且如果我们想进一步研究某个连接,它还提供了一种更深入的方法。图 8-20 所示为用端口替换源的iftop
界面。
图 8-20
在 iftop 中按传出端口查看流量
用于监控的其他程序
-嘘-嘘
另一个可以用来长时间监控系统使用情况的程序是sysstat
,类似于atop
,但更全面。与其检查系统的当前状态,不如让sysstat
在后台运行,然后阅读每日报告。它的工作原理是每 10 分钟运行一次 cron 作业并记录系统数据。
默认情况下它可能是可用的,但是如果不是,您可以使用
sudo apt-get install sysstat
首先打开/etc/default/sysstat
,确保下面一行设置为真;默认情况下,在 Ubuntu 上,它将被设置为 false:
ENABLED="true"
然后用systemctl
启用它:
sudo systemctl enable --now sysstat
完成这些简单的步骤后,您的系统将开始在/var/log/sysstat
文件夹中保存系统数据。将为该月的每一天创建一个新文件,例如,如果您从 26 日开始,该文件将是/var/log/sysstat/sa26
。您可以通过运行以下命令来查看当天的数据
sar
一旦它运行了一段时间,sar
将返回如图 8-21 所示的内容。
图 8-21
运行 sar
如上所述,这些统计数据保存在/var/log/sysstat
文件夹中。如果您想查看之前监控的一天,用sar
指定要打开的文件:
sar -f /var/log/sysstat/sa27
请注意,一旦您使用sysstat
超过一个月,这些文件将开始被覆盖。如果您想将日志保存更长时间,您必须手动备份它们。
平均负载
平均负载是指正在运行或等待运行的线程的平均数量。有许多方法可以获得这些信息,最简单的方法是运行
uptime
这将返回系统运行的时间、登录的用户以及三个不同的平均负载值。这三个不同的值是 1 分钟、5 分钟和 15 分钟的平均值。使用这三个值,您可以了解负载是增加还是减少。
如果你现在已经经常使用top
,你可以在顶行找到相同的三个负载平均值。
重要的是要记住,无论计算机有多少个 CPU,平均负载都是由队列中的线程来衡量的。在单 CPU 机器上平均负载为 2 比在有两个 CPU 的机器上平均负载为 3 要高。想象一下,每个线程都是一个在杂货店等待付款的人,每个 CPU 都是一个收银员。在不知道店内收银员人数的情况下,知道有多少人在排队并不一定有用。
要考虑的一个更有用的统计数据是平均负载除以 CPU。如果平均负载除以 CPU 数量大于 1,这可能表明您的系统过载。考虑一下前面探讨的友善的概念。如果一个 nice 值为 19 的进程正在运行,但是平均负载总是高于可用的 CPU,它可能永远不会结束执行,因为它一直允许进入该行的新进程首先运行。
根据一个传闻,当麻省理工学院的 IBM 7094 在 1973 年被关闭时,他们发现了一个低优先级的进程,该进程在 1967 年就已经提交,并且还没有运行。这正是所描述的队列一直存在的情况,因为进程的优先级低,所以它一直排队等待,总是让新的高优先级任务先运行。这个问题通常被称为资源匮乏。
Note
如果您忘记了一台机器上有多少个 CPU,您可以使用lscpu
来查找标题为“CPU(s)”的行
用户
在上一节中,我们看到uptime
返回的第三个值实际上是登录的用户。如果你最终看到了一个你没有预料到的数字,你可以使用who
或w
获得更多关于当前登录用户的信息。如果你的系统有,w
是首选,因为它是对who
的重写,包含了更多的用户信息。简单地跑
w
您将获得用户列表以及他们正在使用的 TTY。如果用户使用多个 tty,它们会被多次列出。用户使用单个 TTY 的示例如图 8-22 所示。
图 8-22
使用 w 查看已登录的用户
图 8-23 显示了一个用户使用多 TTY ( 通过 tmux
,一个保持终端会话打开但后台的程序)的例子。
图 8-23
在几个 tmux 会话打开的情况下运行 w
日志文件夹
在监控或调试系统时,您需要注意系统日志文件夹。最好的地方之一是/var/log
,这是存放各种日志的系统文件夹。导航到文件夹并查看文件:
cd /var/log
ls
根据正在运行的服务和系统运行的时间,您应该会在这里看到几个不同的文件和文件夹。我的日志文件夹的内容如图 8-24 所示。
图 8-24
/var/log 中的内容示例
如果你在 Ubuntu 这样的 Debian 系统上,主日志文件将会是/var/log/syslog
。如果你在 CentOS 这样的非 Debian 系统上,你应该寻找/var/log/messages
。我们会打开它
less /var/log/syslog
你会看到来自不同程序的各种信息。
在大多数系统上负责写这些日志的程序是rsyslogd
。可以通过编辑/etc/rsyslog.conf
文件进行定制。
Note
除了 syslog,另一个检查日志的好方法是 systemd 的journalctl
;参见第十一章中的Journalctl
部分。
其他 sysstat 实用程序
当您安装并启用sysstat
时,您实际上获得了一整盒实用程序和二进制文件,它们以各种方式处理和显示系统数据。这些公用设施在表 8-2 中列出。
表 8-2
sysstat 实用程序列表
|命令
|
描述
|
| — | — |
| 特别行政区 | 收集数据并显示所有系统活动 |
| 南共体 | “系统活动数据收集器”在后台运行 |
| sa1 | 从 cron 运行并处理收集的数据 |
| sa2 | 创建每日摘要,从 cron 运行 |
| 萨夫 | 将 sar 报告导出为 CSV、JSON、XML 等格式。 |
| 监视磁盘状态 | 用于查看 I/O 用途 |
| 系统的工具 | 用于查看与流程相关的统计数据 |
| 你会的 | 按进程 ID 查看数据 |
| cifsiostat | 查看 CIFS ( 通用互联网文件系统)统计信息;这是一个微软的文件系统,可以在 Linux 中通过 Samba 启用 |
显示虚拟内存状态
vmstat
是一个较旧的系统监控工具,它返回与系统内存、进程、中断、分页和块 I/O 相关的系统信息。它没有安装在大多数系统上,但可以在大多数软件包管理器中找到。
它接受两个输入值;第一个是以秒为单位的采样周期,第二个是要采集多少样本。因此,如果我们使用输入 1 和 10 运行,如下所示:
vmstat 1 10
我们退回十排。第一行永远是开机以来的总结。然后我们得到 9 行,每一行在最后一行之后 1 秒打印,显示 1 秒样本的平均值。图 8-25 显示了运行vmstat
10 个 1 秒周期的示例。
图 8-25
使用 vmstat 获取 9 秒长的样本
由于用来显示表的空间被压缩了,所以很难解释列值。表 8-3 列出了缩写形式及其含义。
表 8-3
vmstat 列列表
|顺序
|
描述
|
| — | — |
| r | 队列中等待 CPU 的线程 |
| b | I/O 上阻塞的线程 |
| swpd 的 | 使用的总交换空间(KB) |
| 自由的 | 总空闲内存 |
| 爱好者 | 用作缓冲区的内存 |
| 躲藏 | 用作缓存的内存 |
| 大音阶第七音 | 从磁盘换入的内存 |
| 因此 | 内存交换到磁盘 |
| 双性恋的 | 从块设备接收的块 |
| 呸 | 发送到块设备的块 |
| 在 | 每秒中断数 |
| 铯 | 每秒的上下文切换 |
| 我们 | 运行非内核代码花费的时间 |
| 叙利亚 | 运行内核代码花费的时间 |
| 编号 | 空闲时间 |
| 华盛顿 | 等待 I/O 花费的时间 |
| 标准时间 | 从虚拟机窃取的时间 |
r–等待运行时的线程
正如我们在讨论平均负载时提到的,队列中的线程是等待在 CPU 上运行的进程。因此,该列基本上与平均负载相同。然而,返回的第一行将是启动机器后的平均值(如果已经安装了vmstat
)。这给了你一个完整运行时间的平均值,这是用top
或uptime
无法得到的。
对于顶线以下的值,您将获得取样瞬间的值,而不是平均值。
b–被 I/O 阻塞的线程
I/O 阻塞的线程是在等待进程读取或写入存储时被内核置于等待状态的线程。如果有大量线程被 I/O 阻塞,这可能表明存在与存储设备相关的问题,或者仅仅是大量使用 I/O 的进程正在运行。
swpd–使用的总交换
交换指的是当实际 RAM 内存已满时,分配给充当 RAM 的磁盘空间。交换内存比普通 RAM 慢得多,会导致依赖该内存的程序运行缓慢。如果您经常使用交换内存,您的系统可能需要 ram,或者某个程序可能不必要地使用了过多的 RAM。
空闲–总空闲内存
这以 KB 为单位显示了系统中未使用的内存总量。这类似于运行free
命令时显示的自由栏。这让你知道你有多接近使用你所有的内存。
buff–缓冲区中使用的内存
这类似于缓存,但特定于文件元数据;有关更多详细信息,请参见下一节。
缓存–用作缓存的内存
有时内存会被用来缓存程序经常访问的数据。这加快了程序的速度,但是看起来你的可用内存比实际情况要少;如果您的系统已经运行了很长时间,这种情况经常发生。
如果free
的值很低,而cache
的值很高,那么您仍然不需要担心交换空间被使用,因为缓冲区中的内存可以被重新分配。然而,如果cache
+ buff
+ free
加在一起接近 0,这是你的机器资源紧张的迹象。
si–从磁盘换入的内存
如前所述,数据或元数据(与缓冲区一样)通常存储在内存中,以提高程序运行的速度。我们讨论了如果更多的内存最终被其他东西需要,如何释放这些内存。在其他情况下,缓存在内存中的数据可能会被其他数据换出。
通过交换,该数据实际上包含执行程序本身的方面,例如,由程序产生的仅在程序运行时存在的数据结构。这种交换就是si
列所测量的。si
是每秒从磁盘交换的内存。
交换的使用表明系统没有足够的内存可用于缓存,只能求助于使用磁盘空间。如果您有一致的或高交换率,这意味着您的系统没有足够的内存。
所以–内存从磁盘换出
顾名思义,这与内存交换密切相关。换入是将数据从磁盘加载回内存的过程,而换出是数据首次保存到磁盘的过程。
bi-从块设备接收的块
这实际上是从磁盘存储设备中读取的数据量。默认情况下,块的大小为 512 字节。
bo–发送到块设备的块
这是通过块设备保存到磁盘的块数。
输入-每秒中断次数
中断是需要立即处理的信号。例如,当按下键盘上的一个键时,就会产生一个需要处理的中断。同样,当连接到互联网的网卡产生输入信号时,就会产生一个中断。可以通过查看文件/proc/interrupts
直接查看中断。
中断发生是系统操作的正常部分,但是如果中断高于正常,可能有硬件问题。下一步可能是查看/proc/interrupts
,并找出是什么设备导致了高计数。
cs–上下文切换
当 CPU 在一个进程和另一个进程之间切换而没有完成第一个进程时,就会发生上下文切换。上下文切换需要保存第一个进程的状态,以便稍后完成。存在与上下文切换相关联的成本,因为需要资源来保存第一个进程的状态并在稍后加载该状态。
如果您看到异常大量的上下文切换,这可能与某个严重使用多线程的特定程序有关。
us——运行非内核代码花费的时间
如题,us
是运行非内核代码的时间。我们前面提到的内核是类 Unix 系统的核心,它将物理硬件连接到用户级软件。所有“花费的时间”值都是以时间的百分比来度量的,因此值 2 表示在所度量的时间段内有 2%的时间花费在非内核代码上。
sy——运行内核代码花费的时间
这是运行内核代码所用时间的百分比;一个简单的方法是,花费在用户级别之外的系统进程上的时间。花费在系统进程上的时间值异常高可能表示硬件问题、内存瓶颈或内核级锁定问题。
id–空闲时间
这是空闲时间的百分比。这用于与us
和sy
进行比较。请注意,添加us
、sy
、id
和wa
( ,我们将在下一个中查看)后的总和应该在 100%左右(由于四舍五入,可能会略有出入)。如果你在测试vmstat
时没有在后台运行很多程序,很可能大部分时间都是空闲的。较低的空闲时间表示您的系统正在进行大量处理。
wa—等待 I/O 花费的时间
第四类“花费在vmstat
上的时间”是花费在等待 I/O 上的时间百分比。在关于b
的章节中,我们提到了线程在等待写入磁盘或从磁盘读取时如何被阻塞。wa
为我们提供了一个衡量等待 I/O 时损失了多少 CPU 时间的指标。等待 I/O 的时间百分比高可能表明我们的磁盘存储很慢,或者我们只是在对磁盘进行大量的读写操作。如果您发现等待 I/O 似乎占用了您系统的大量时间,您可以通过用具有更高读/写速度的磁盘存储升级底层硬件来降低这一百分比。
如果您想模拟一个导致大量磁盘读写的进程来观察vmstat
中的效果,您可以运行以下代码片段:
(cd /tmp &&
(sync ; vmstat 1 & PID1=$! ; \
cat </dev/zero >test & PID2=$! ; \
sleep 3 ; kill $PID2 ; sync ; kill $PID1))
这个代码片段移动到/tmp
目录,启动vmstat
,然后开始从/dev/zero
读取零,并将它们写入/tmp/test
。PID1 和 PID2 包含两个正在运行的进程的进程 ID,并在休眠 3 秒后杀死它们。当运行这个命令时,您应该看到wa
值上升到一些高值。
ST-从虚拟机窃取的时间
顾名思义,st
值表示运行在您系统上的虚拟机等待访问分配给它的资源所花费的时间。这仅在您的系统运行虚拟机时才相关。值持续大于 0 可能表明您为虚拟机分配了过多的内存,这意味着您的主系统不得不从它们那里窃取时间,或者您根本没有足够的内存来运行您托管的虚拟机和主系统。
工具
“nmon
”系统监控工具可以显示 CPU、内存、网络、磁盘(迷你图或数字)、文件系统、NFS、顶级进程、资源(Linux 版本和处理器)和电源微分区信息。nmon
的独特之处在于,它允许您在这些不同的统计数据之间混合和匹配,以创建您自己的定制显示屏。nmon
不是默认安装的,但是在大多数软件包管理器上都可以找到nmon
。
当你第一次通过运行不带选项的命令打开nmon
时,你会看到一个类似于图 8-26 的开始屏幕。
图 8-26
运行 nmon
在这里,您可以按底部列出的任何按钮来打开特定的统计数据。比如我们按n
,屏幕会显示网络信息;如果我们按下c
,我们将会看到网络和 CPU 信息,如图 8-27 所示。
图 8-27
在 nmon 中查看 CPU 和网络信息
你一次可以查看多少不同的统计数据的唯一限制是你的屏幕大小。任何时候,您都可以通过按下用于激活某个部分的按钮来删除该部分。
使用 Snort 进行高级网络监控
另一个值得一提的监控系统是 Snort,这是一个开源的网络入侵预防和检测系统。Snort 的工作原理是实时分析网络流量,并根据一组定义的规则进行检查。常见的规则集包括
-
对照黑名单检查 IP 地址
-
检查来自 IP 的异常请求量
-
检查请求的内容
-
特定于 FTP、SSH 或 https 等特定服务的规则
-
任何自定义规则
Snort 还允许系统管理员连接规则来触发操作,例如向系统管理员发送通知或阻止来自违规 IP 的请求。Snort 是完全开源的,有几个社区维护的规则集,也有定期更新的高级规则集,并作为付费服务提供。
我们不会详细讨论如何安装或设置snort
,尽管它可以从大多数软件包管理器中获得。设置过程相当长,超出了本书的范围,但是如果用例适用于您的设置,这是值得研究的。
纳吉奥斯
另一个开源的全套网络监控系统是 Nagios,它配有基于 web 的 GUI。它可用于监控多台机器和基础设施上的资源,其特性包括
-
基于潜在问题的警报
-
监控你的网站,记录任何停机时间
-
捕获端口使用( http,SMTP,SNMP,FTP,SSH,POP 等。)
-
网络请求的大量日志
与 Snort 一样,Nagios 服务器对于那些运行大中型基础设施来提供基于 web 的服务的人来说更有用。
摘要
在这一章中,我们看了可以用来监控 Linux 系统的各种程序和命令,从使用top
或atop
的基本进程监控到更具体的监控程序,如nethogs
和iftop
。