网络问题判断:供系统管理员使用的 AIX 工具
2010-09-26 00:00:00 来源:WEB开发网本文介绍一些可以在 IBM AIX® 上使用的命令,其中许多命令也可以在其他风格的 UNIX® 上使用。当您的主机与另一个主机的通信发生问题时,这些命令有助于尽可能详细地了解实际情况。也详细讨论符合逻辑的常见问题诊断方法。
常用缩写词
ACL: Access control list
DNS: Domain Name System
I/O: Input/output
MAC: Media Access Control
TCP/IP: Transmission Control Protocol/Internet Protocol
对于本文,所有样例命令和输出中使用的目标主机系统都称为 testhost。
获得更多信息
根据要诊断的网络问题的性质,有时候有必要了解失败的应用程序或命令是否有详细输出、跟踪或调试选项。例如,ssh (Secure Shell) 和 scp (Secure Copy) 命令有详细输出开关(-v),这可以提供关于客户机和服务器之间的通信、密钥交换和身份验证的大量跟踪信息(见 清单 1)。
清单 1. 用提供详细输出的 ssh 会话连接远程主机
# ssh —v testhost
OpenSSH_4.2p1, OpenSSL 0.9.7d 17 Mar 2004
debug1: Reading configuration data /opt/freeware/etc/ssh_config
debug1: Connecting to testhost [10.217.1.206] port 22.
debug1: Connection established.
debug1: permanently_set_uid: 0/0
debug1: identity file /root/.ssh/identity type -1
debug1: identity file /root/.ssh/id_rsa type 1
debug1: identity file /root/.ssh/id_dsa type -1
debug1: Remote protocol version 1.99, remote software version OpenSSH_4.1
debug1: match: OpenSSH_4.1 pat OpenSSH*
debug1: Enabling compatibility mode for protocol 2.0
debug1: Local version string SSH-2.0-OpenSSH_4.2
debug1: SSH2_MSG_KEXINIT sent
debug1: SSH2_MSG_KEXINIT received
debug1: kex: server->client aes128-cbc hmac-md5 none
debug1: kex: client->server aes128-cbc hmac-md5 none
debug1: SSH2_MSG_KEX_DH_GEX_REQUEST(1024<1024<8192) sent
debug1: expecting SSH2_MSG_KEX_DH_GEX_GROUP
debug1: SSH2_MSG_KEX_DH_GEX_INIT sent
debug1: expecting SSH2_MSG_KEX_DH_GEX_REPLY
debug1: Host 'testhost' is known and matches the RSA host key.
debug1: Found key in /root/.ssh/known_hosts:14
debug1: ssh_rsa_verify: signature correct
debug1: SSH2_MSG_NEWKEYS sent
debug1: expecting SSH2_MSG_NEWKEYS
debug1: SSH2_MSG_NEWKEYS received
debug1: SSH2_MSG_SERVICE_REQUEST sent
debug1: SSH2_MSG_SERVICE_ACCEPT received
debug1: Authentications that can continue: publickey,password,keyboard-interactive
debug1: Next authentication method: publickey
debug1: Trying private key: /root/.ssh/identity
debug1: Offering public key: /root/.ssh/id_rsa
debug1: Authentications that can continue: publickey,password,keyboard-interactive
debug1: Trying private key: /root/.ssh/id_dsa
debug1: Next authentication method: keyboard-interactive
debug1: Authentications that can continue: publickey,password,keyboard-interactive
debug1: Next authentication method: password
root@testhost's password:
debug1: Authentication succeeded (password).
debug1: channel 0: new [client-session]
debug1: Entering interactive session.
Last unsuccessful login: Wed 27 Jan 13:30:23 2010 on ssh from 10.216.163.37
Last login: Wed 10 Feb 16:05:48 2010 on /dev/pts/0 from 10.216.163.37
******************************************************************************
* *
* *
* Welcome to AIX Version 5.3! *
* *
* *
* Please see the README file in /usr/lpp/bos for information pertinent to *
* this release of the AIX Operating System. *
* *
* *
******************************************************************************
#
如果可以登录进入有问题的主机(理论上,服务器无法向特定端口发送服务网络请求,但是有时候也可以在发出请求的客户机上报告错误),那么您应该在系统日志中检查相关的消息。这些文件包括 /var/adm/messages、/var/log/syslog 和 /var/log/mail 等,具体文件取决于在 /etc/syslog.conf 中如何配置系统日志守护进程;如果有 ftpd、sshd、telnetd 等守护进程,还应该检查与守护进程相关的日志。这些日志中的一个或多个常常会记录警告、错误或失败。因此,在这些日志中找到的信息可能有助于判断问题的根源。
一些服务可以配置详细、调试或跟踪型日志记录,这会在日志中记录标准信息或错误消息之外的更多信息。如果问题是可再现的,那么有必要检查是否能够在测试期间使用这种诊断日志记录。但是,不要一直启用详细日志记录,因为这么做会造成磁盘和文件系统空间问题。
为了更好地了解进程正在执行的操作,可以使用 truss 跟踪进程执行的系统调用。truss 命令既可以执行指定的命令,也可以附加到现有的进程上生成跟踪(假设您拥有这个正在运行的进程或者具有根特权)。若是后者,随时可以按 Control-C 停止跟踪。
清单 2 是部分基本跟踪命令,以及 ssh testhost 的片段。-l 开关在每个跟踪条目前面加上进程 ID 作为前缀,-d 开关显示相对于跟踪起点的时间戳。
清单 2. 一个命令的基本系统调用跟踪
# truss —ld ssh testhost
2785347: 0.0000: execve("/usr/bin/ssh", 0x2FF22B70, 0x2FF22B7C) argc: 2
2785347: 0.0137: __loadx(0x03020000, 0x2FF22A40, 0x00000080, 0xDEADBEEF,
0xDEADBEEF) = 0x00000000
2785347: 0.0141: __loadx(0x0C000000, 0xF0208964, 0xF1422004, 0xF020832C,
0x00000001) = 0x00000000
2785347: 0.0143: thread_init(0x0000000000000000, 0x00000000D011A9BC) =
2785347: 0.0146: sbrk(0x00000000) = 0x20015B5C
2785347: 0.0148: vmgetinfo(0x2FF22958, 7, 16) = 0
2785347: 0.0151: sbrk(0x00000000) = 0x20015B5C
2785347: 0.0153: vmgetinfo(0x2FF22410, 7, 16) = 0
2785347: 0.0156: sbrk(0x00000000) = 0x20015B5C
2785347: 0.0158: sbrk(0x00000004) = 0x20015B5C
2785347: 0.0160: __libc_sbrk(0x00000000) = 0x20015B60
2785347: 0.0163: getrpid(-1, -1, 10) = 475322
2785347: 0.0165: _getpid() = 475322
.
.
.
.
2785347: 35.9732: kioctl(0, 1074295912, 0x2FF22520, 0x00000000) = 0
2785347: 35.9735: getsockopt(3, 6, 1, 0x2FF22554, 0x2FF22550) = 0
2785347: 35.9737: setsockopt(3, 6, 1, 0x2FF22554, 4) = 0
2785347: 35.9739: ngetsockname(3, 0x2FF22498, 0x2FF22490) = 0
2785347: 35.9741: setsockopt(3, 0, 3, 0x2FF22560, 4) = 0
2785347: 35.9743: _select(7, 0x2004E738, 0x2004FA48, 0x00000000, 0x00000000) = 1
2785347: kwrite(3, " H14 l95121D i86 H Q o10".., 384) = 384
2785347: 35.9748: _select(7, 0x2004E738, 0x2004FA48, 0x00000000, 0x00000000) = 1
2785347: kread(3, " t x "0699841A E a S y\n".., 8192) = 768
2785347: 35.9837: _select(7, 0x2004E738, 0x2004FA48, 0x00000000, 0x00000000) = 2
Last unsuccessful login: Sat 13 Feb 22:16:28 2010 on ssh from myhost.testdomain.com
Last login: Sat 13 Feb 22:16:56 2010 on /dev/pts/4 from myhost.testdomain.com
*******************************************************************************
* *
* *
* Welcome to AIX Version 5.1! *
* *
* *
* Please see the README file in /usr/lpp/bos for information pertinent to *
* this release of the AIX Operating System. *
* *
* *
*******************************************************************************
2785347: kwrite(5, " x ".., 567) = 567
2785347: 35.9849: _select(7, 0x2004E738, 0x2004FA48, 0x00000000, 0x00000000) = 1
2785347: kread(3, " x d o e x10 # 0 A1C c17".., 8192) = 48
2785347: 36.1103: _select(7, 0x2004E738, 0x2004FA48, 0x00000000, 0x00000000) = 1
2785347: kwrite(5, " t e s t h o s t : r o o".., 17) = 17
testhost:root>
2785347: 219.4781: _select(7, 0x2004E738, 0x2004FA48, 0x00000000, 0x00000000)
(sleeping...)
2785347: 219.4781: _select(7, 0x2004E738, 0x2004FA48, 0x00000000, 0x00000000) = 1
2785347: kread(4, "04 n a80 n V\f a\0\0\010".., 16384) = 1
2785347: 220.1322: _select(7, 0x2004E738, 0x2004FA48, 0x00000000, 0x00000000) = 1
2785347: kwrite(3, " O8D d r 013 g1982 o\n i".., 48) = 48
2785347: 220.1327: _select(7, 0x2004E738, 0x2004FA48, 0x00000000, 0x00000000) = 1
2785347: kread(3, " p h1A 1 a I J E031D9D1C".., 8192) = 80
2785347: 220.1347: _select(7, 0x2004E738, 0x2004FA48, 0x00000000, 0x00000000) = 1
2785347: kwrite(5, "\r\n", 2) = 2
2785347: 220.1352: close(5) = 0
2785347: 220.1354: _select(7, 0x2004E738, 0x2004FA48, 0x00000000, 0x00000000) = 1
2785347: kread(3, " O a *901C ^81 . B e83 R".., 8192) = 96
2785347: 220.1358: close(4) = 0
2785347: 220.1360: kioctl(0, 22528, 0x00000000, 0x00000000) = 0
2785347: 220.1362: kioctl(0, 21507, 0x200151F8, 0x00000000) = 0
2785347: 220.1365: close(6) = 0
2785347: 220.1367: _select(7, 0x2004E738, 0x2004FA48, 0x00000000, 0x00000000) = 1
2785347: kwrite(3, "1A | B O # E c v9D e93 >".., 32) = 32
2785347: 220.1372: sigprocmask(2, 0xF1423790, 0x2FF22630) = 0
2785347: 220.1374: _sigaction(28, 0x00000000, 0x2FF226E0) = 0
2785347: 220.1375: thread_setmymask_fast(0x00000000, 0x00000000, 0x00000000, 0x102A8043,
0x00000000, 0x00000135, 0x00000000, 0x00000000) = 0x00000000
2785347: 220.1377: sigprocmask(2, 0xF1423790, 0x2FF22630) = 0
2785347: 220.1379: _sigaction(28, 0x2FF226D0, 0x00000000) = 0
2785347: 220.1381: thread_setmymask_fast(0x00000000, 0x00000000, 0x00000000, 0x102A8043,
0x00000000, 0x0000017C, 0x00000000, 0x00000000) = 0x00000000
2785347: 220.1383: kioctl(0, 22528, 0x00000000, 0x00000000) = 0
2785347: 220.1385: kioctl(1, 22528, 0x00000000, 0x00000000) Err#25 ENOTTY
2785347: 220.1387: kfcntl(1, F_GETFL, 0x00000000) = 67108869
2785347: 220.1389: kioctl(1, -2147195266, 0x2FF22640, 0x00000000) = 0
2785347: 220.1391: kioctl(1, -2147195267, 0x2FF22640, 0x00000000) = 0
2785347: 220.1393: kfcntl(1, F_SETFL, 0x04000001) = 0
2785347: 220.1395: kioctl(2, 22528, 0x00000000, 0x00000000) Err#25 ENOTTY
2785347: 220.1397: kfcntl(2, F_GETFL, 0x00000000) = 67108865
Connection to testhost closed.
2785347: kwrite(2, " C o n n e c t i o n t".., 32) = 32
2785347: 220.1402: shutdown(3, 2) = 0
2785347: 220.1404: close(3) = 0
2785347: 220.1406: kfcntl(1, F_GETFL, 0x102A8043) = 67108865
2785347: 220.1408: kfcntl(2, F_GETFL, 0x102A8043) = 67108865
2785347: 220.1410: _exit(0)
#
清单 3 把一个正在运行的进程(进程 ID 976)的详细跟踪发送到输出文件并显示简短摘要。使用了以下开关:
表 1. 对正在运行的进程进行详细跟踪使用的开关
-o | 指定将跟踪写到输出文件 (/var/tmp/truss.out) |
-a | 显示传递给系统调用的所有参数 |
-e | 显示传递给系统调用的所有环境字符串 |
-f | 在跟踪输出中显示 fork 系统调用生成的所有子进程,包括它们的信号、错误和系统调用 |
-l | 列出发出调用的进程 ID |
-D | 显示自前一个事件以来经过的时间 |
-r all | 显示 Read 调用的 I/O 缓冲区的内容 |
-w all | 显示 Write 调用的 I/O 缓冲区的内容 |
-x all | 以十六进制格式显示系统调用的指定参数的数据 |
-p | 指定要跟踪的正在运行的进程(在这个示例中是 976) |
清单 3. 把正在运行的进程的详细跟踪发送到文件
# truss —o /var/tmp/truss.out —aeflD —r all —w all —x all —p 976
^C
# cat /var/tmp/truss.out
1003752: psargs: sshd: testuser@pts/1 AIA,, ts/1
1003752: 1798193: 0.0000: _select(0x00000008, 0x2002D788, 0x2002D798,
0x00000000, 0x00000000) (sleeping...)
1003752: 1798193: 0.0000: _select(0x00000008, 0x2002D788, 0x2002D798,
0x00000000, 0x00000000) = 0x00000001
1003752: 1798193: 0.7196: sigprocmask(0x00000000, 0x2FF22598, 0x2FF225A0)
= 0x00000000
1003752: 1798193: 0.0002: sigprocmask(0x00000002, 0x2FF225A0, 0x00000000)
= 0x00000000
1003752: 1798193: kread(0x00000003, 0x2FF1E590, 0x00004000) = 0x00000034
1003752: ? 2 q q A> Ao A' A,8E ) A, Au A?9D 8 A,87 {90 A1 A^ l p 0 !02 A— A% A4 A!9C\n
1003752: A| | &8E A!9F G A2 )1C M1E A^ AZ / AE p AI Az A
1003752: 1798193: 0.0003: _select(0x00000008, 0x2002D788, 0x2002D798,
0x00000000, 0x00000000) = 0x00000001
1003752: 1798193: 0.0003: sigprocmask(0x00000000, 0x2FF22598, 0x2FF225A0)
= 0x00000000
1003752: 1798193: 0.0002: sigprocmask(0x00000002, 0x2FF225A0, 0x00000000)
= 0x00000000
1003752: 1798193: kwrite(0x00000006, 0x200A6F98, 0x00000001) = 0x00000001
1003752: p
1003752: 1798193: 0.0003: kioctl(0x00000006, 0x00005800, 0x00000000,
0x00000000) = 0x00000000
1003752: 1798193: 0.0002: kioctl(0x00000006, 0x00005401, 0x2FF224C0,
0x00000000) = 0x00000000
1003752: 1798193: 0.0003: _select(0x00000008, 0x2002D788, 0x2002D798,
0x00000000, 0x00000000)
= 0x00000001
1003752: 1798193: 0.1359: sigprocmask(0x00000000, 0x2FF22598,
0x2FF225A0) = 0x00000000
1003752: 1798193: 0.0002: sigprocmask(0x00000002, 0x2FF225A0,
0x00000000) = 0x00000000
1003752: 1798193: kread(0x00000007, 0x2FF1E4F0, 0x00004000) = 0x00000013
1003752: t e s t h o s t : t e s t u s e r >
.
.
.
.
1003752: 1798193: kread(0x00000007, 0x2FF1E4F0, 0x00004000) = 0x0000003F
1003752:
1003752: M o z i l l a\r\n
1003752: 1798193: 0.0003: _select(0x00000008, 0x2002D788, 0x2002D798,
0x00000000, 0x00000000) = 0x00000002
1003752: 1798193: 0.0003: sigprocmask(0x00000000, 0x2FF22598,
0x2FF225A0) = 0x00000000
1003752: 1798193: 0.0002: sigprocmask(0x00000002, 0x2FF225A0,
0x00000000) = 0x00000000
1003752: 1798193: kread(0x00000007, 0x2FF1E4F0, 0x00004000) = 0x00000051
1003752:
1003752:
1003752: t r u s s . t x t\r\n f p d g
1003752: 1798193: 2.0001: _select(0x00000008, 0x2002D788, 0x2002D798,
0x00000000, 0x00000000) (sleeping...)
^C
#
可以使用系统调用跟踪寻找潜在问题根源的错误。应该寻找带 #Err 标志的调用,这表示返回码非零,可以在 /usr/include/sys/errno.h 中查找返回码。还可以在使用 -D 开关时寻找调用之间的长 delta,通过这种方法寻找潜在的性能延迟原因。例如,清单 3 中跟踪输出示例中最后两个事件的运行时间是 2.0001 秒。
休斯顿,我们遇到问题了!
既然已经掌握了可以帮助诊断网络问题的工具集,现在就来逐步看看解决常见问题的逻辑方法。下面列出与 AIX 网络相关的一些常见问题并提供诊断方法。
主机未知
如果无法识别在命令中或由应用程序使用的主机名,那么通过查看 /etc/irs.conf 和 /etc/netsvc.conf 中的 hosts 记录检查解析主机名的搜索次序。对于通过名称引用的主机,必须通过名称解析机制解析它。
如果在 hosts 记录中指定 local,那么在 /etc/hosts 文件中寻找这个主机名。在 清单 4 所示的示例中,可以看到用简单的 grep 命令在这个文件中寻找主机 testhost 会返回成功的匹配。主机名必须出现在第一个字段(IP 地址)后面的任何字段中。在这个示例中,这个服务器还有两个别名:testhost.testdomain.com 和 aixserver。这意味着,在需要主机名参数的命令中,可以用这三个名称中的任意一个引用此主机。
清单 4. 在 /etc/hosts 中寻找主机
# grep testhost /etc/hosts
10.217.1.206 testhost testhost.testdomain.com aixserver
#
如果在 hosts 记录中指定 bind 或 dns,那么使用 nslookup 确认可以通过 DNS 解析主机名。在 清单 5 所示的示例中,可以看到解析已经成功了,DNS 服务器 testdns.testdomain.com(显示其 IP 地址)返回了主机 testhost 的 IP 地址 10.217.1.206。
清单 5. 通过 DNS 解析主机名
# nslookup testhost
Server: testdns.testdomain.com
Address: 158.177.79.90
Name: testhost.testdomain.com
Address: 10.217.1.206
#
可以在配置文件中指定的其他名称解析服务,这超出了本文的范围,这里不作讨论。
无响应的主机
如果主机是已知的,但是用户抱怨这个主机本身或它上面运行的应用程序没有响应,那么使用 ping 并查看数据包丢失率是否为 0%(见 清单 6)。如果不是 0%,就意味着目标主机或网络有问题。
清单 6. Ping 一个有响应的主机
# ping testhost
PING testhost: (10.217.1.206): 56 data bytes
64 bytes from 10.217.1.206: icmp_seq=0 ttl=253 time=0 ms
64 bytes from 10.217.1.206: icmp_seq=1 ttl=253 time=0 ms
64 bytes from 10.217.1.206: icmp_seq=2 ttl=253 time=0 ms
64 bytes from 10.217.1.206: icmp_seq=3 ttl=253 time=0 ms
----testhost PING Statistics----
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 0/0/0 ms
#
另外,在 time= 字段中寻找比较长的响应时间,或报告的值中出现的高峰值。这两种现象都表明网络或主机性能差,这可能就是您的用户抱怨的应用程序超时的原因。
使用 route get 查明路由(见 清单 7),检查网络管理员是否使用了正确的网关,从而确认有到目标主机的路由。
清单 7. 获取主机的路由表信息
# route get testhost
route to: testhost
destination: 10.203.35.128
mask: 255.255.255.128
gateway: 10.203.35.1
interface: en2
interf addr: myhost
flags: <UP,GATEWAY,DONE,PRCLONING>
recvpipe sendpipe ssthresh rtt,msec rttvar hopcount mtu expire
0 0 0 0 0 0 0 -9751026
#
使用 ifconfig(见 清单 8)确保已经为 AIX 配置了报告的 interface,而且其状态是 UP 和 RUNNING。
清单 8. 显示网络接口状态
# ifconfig en1
en1: flags=7e080863,40<UP,BROADCAST,NOTRAILERS,RUNNING,SIMPLEX,MULTICAST,GROUPRT,64BIT,
CHECKSUM_OFFLOAD,CHECKSUM_SUPPORT,PSEG>
inet 10.216.163.37 netmask 0xffffff00 broadcast 10.216.163.255
tcp_sendspace 131072 tcp_recvspace 65536
# ifconfig -a
en2: flags=7e080863,40<UP,BROADCAST,NOTRAILERS,RUNNING,SIMPLEX,MULTICAST,GROUPRT,64BIT,
CHECKSUM_OFFLOAD,CHECKSUM_SUPPORT,PSEG>
inet 10.203.35.14 netmask 0xffffff80 broadcast 10.203.35.127
en1: flags=7e080863,40<UP,BROADCAST,NOTRAILERS,RUNNING,SIMPLEX,MULTICAST,GROUPRT,64BIT,
CHECKSUM_OFFLOAD,CHECKSUM_SUPPORT,PSEG>
inet 10.216.163.37 netmask 0xffffff00 broadcast 10.216.163.255
tcp_sendspace 131072 tcp_recvspace 65536
en0: flags=7e080822,10<BROADCAST,NOTRAILERS,SIMPLEX,MULTICAST,GROUPRT,64BIT,
CHECKSUM_OFFLOAD,CHECKSUM_SUPPORT,PSEG>
lo0: flags=e08084b<UP,BROADCAST,LOOPBACK,RUNNING,SIMPLEX,MULTICAST,GROUPRT,64BIT>
inet 127.0.0.1 netmask 0xff000000 broadcast 127.255.255.255
inet6 ::1/0
tcp_sendspace 65536 tcp_recvspace 65536
#
使用 ping 检查是否能够从您的主机到达 ifconfig 报告的 gateway。如果无法到达这个网关,那么从您主机上的网络适配器到网关的物理连接可能有问题(例如交换机端口、线路和网卡有故障)。
使用 traceroute(见 清单 9)跟踪到目标主机和来自目标主机的完整路由。有到主机的路由不一定意味着有反向的路由,所以要让网络管理员确认两个路由都存在,而且没有任何防火墙阻止发送或接收的应用程序通信流。如果路由上的任何一站没有返回数据(由星号 [*] 表示),就表明路由有问题。但是,traceroute 用来跟踪路由的数据包也可能被防火墙阻止。这个命令的输出应该有助于网络管理员判断是否真的有路由问题。
清单 9. 跟踪到一个主机的成功路由
# traceroute testhost
trying to get source for testhost
source should be 10.216.163.37
traceroute to testhost (10.217.1.206) from 10.216.163.37 (10.216.163.37), 30 hops max
outgoing MTU = 1500
1 10.216.163.2 (10.216.163.2) 1 ms 0 ms 0 ms
2 10.217.189.6 (10.217.189.6) 0 ms 0 ms 0 ms
3 testhost (10.217.1.206) 1 ms 1 ms 1 ms
#
无响应的 TCP 端口
如果一个主机是已知的而且能够响应 ping,但是应用程序或远程服务使用的某个 TCP 端口似乎没有响应,那么使用 telnet 尝试连接目标主机上的这个端口,见 清单 10 所示的示例,这个示例尝试连接主机 testhost 上的端口 25。
清单 10. 测试主机上的端口 25 (SMTP)(成功)
# telnet testhost 25
Trying...
Connected to testhost.
Escape character is '^]'.
220 testhost.testdomain.com ESMTP Sendmail Wed, 10 Feb 2010 15:52:28 GMT
^]
telnet> quit
Connection closed.
#
/etc/services 中列出常用的端口。成功的连接应该会产生消息 Escape character is '^]',还可能从邮件服务器等远程服务返回消息,见 清单 10。如果没有收到这些消息而且连接超时或被拒绝,那么让网络管理员检查路由上是否有防火墙阻止发送的通信流类型。另外,让目标主机的网络管理员检查应用服务器或远程服务是否正在运行并监听指定的端口,以及主机上运行的防火墙是否阻止通信流。
没有连接到有响应的 TCP 端口
如果一个主机是已知的,能够响应 ping,而且在某个 TCP 端口上对其他主机有响应,但是不响应您的主机,那么使用 telnet 按 无响应的 TCP 端口 中说明的逻辑尝试连接这个端口。
使用 netstat 检查到此主机的连接及其状态,见 清单 11 中的第二个示例,这个示例检查到某个 IP 地址和端口(10.217.1.206 上的端口 22)的所有连接。除非连接状态是 ESTABLISHED,否则连接仍然在建立过程中或已经终止了。例如 SYN_SENT 状态表示您的主机已经发起了三阶段握手,但是还没有从目标主机收到确认。这意味着对于此类型的通信流有到目标主机的路由,但是没有反向的路由。在这种情况下,让网络管理员检查反向的路由上是否有防火墙阻止此类型的通信流。
清单 11. 显示到主机的连接的状态
# netstat -an | grep 10.217.1.206
tcp4 0 0 10.203.35.14.22 10.217.1.206.1023 ESTABLISHED
tcp4 0 0 10.203.35.14.46183 10.217.1.206.22 ESTABLISHED
# netstat -an | grep 10.217.1.206.22
tcp4 0 0 10.203.35.14.46183 10.217.1.206.22 ESTABLISHED
# netstat -an | grep ESTABLISHED
tcp4 0 0 10.203.35.14.22 10.217.1.206.1023 ESTABLISHED
tcp4 0 0 10.203.35.14.46183 10.217.1.206.22 ESTABLISHED
tcp4 0 0 10.216.163.37.1521 10.216.163.37.44122 ESTABLISHED
tcp4 0 0 10.216.163.37.44122 10.216.163.37.1521 ESTABLISHED
tcp4 0 0 127.0.0.1.199 127.0.0.1.32769 ESTABLISHED
tcp4 0 0 127.0.0.1.32769 127.0.0.1.199 ESTABLISHED
tcp4 0 0 10.203.35.14.46183 10.203.35.170.22 ESTABLISHED
tcp4 0 0 10.216.163.37.32770 10.216.163.37.32771 ESTABLISHED
#
使用 tcpdump 显示发送到主机上的指定端口或从其接收的数据包,见 清单 12 中的示例。如果只显示您主机发送的数据包,这也表明从目标主机发送回的通信流有问题,因此反向路由有问题。
清单 12. 显示发送到特定主机上的特定端口或从其接收的数据包
# tcpdump -i en2 host testhost port 22
12:15:38.033833162 myhost.47216 > testhost.22: . ack 610148954 win 17520 (DF) [tos 0x10]
12:15:38.113807903 myhost.47216 > testhost.22: P 145:193(48) ack 192 win 17520 (DF)
[tos 0x10]
12:15:38.114291921 testhost.22 > myhost.47216: P 192:240(48) ack 193 win 24820 (DF)
[tos 0x10]
12:15:38.241718122 myhost.47216 > testhost.22: P 193:241(48) ack 240 win 17520 (DF)
[tos 0x10]
12:15:38.242344703 testhost.22 > myhost.47216: P 240:288(48) ack 241 win 24820 (DF)
[tos 0x10]
12:15:38.243844593 myhost.47216 > testhost.22: . ack 288 win 17520 (DF) [tos 0x10]
12:15:38.497817604 myhost.47216 > testhost.22: P 241:289(48) ack 288 win 17520 (DF)
[tos 0x10]
12:15:38.503088328 testhost.22 > myhost.47216: P 288:336(48) ack 289 win 24820 (DF)
[tos 0x10]
12:15:38.503154802 testhost.22 > myhost.47216: P 336:432(96) ack 289 win 24820 (DF)
[tos 0x10]
^C
145 packets received by filter
0 packets dropped by kernel
#
登录时间长
如果用户抱怨说登录某个主机时响应时间很长,那么登录此主机,使用 dig 对用户的计算机的 IP 地址执行反向查找,见 清单 13 中的示例。
清单 13. 在 DNS 中反向查找 IP 地址
# dig -x 10.217.1.206
; <<>> DiG 9.2.0 <<>> -x 10.217.1.206
;; global options: printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 21351
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;206.1.217.10.in-addr.arpa. IN PTR
;; ANSWER SECTION:
206.1.217.10.in-addr.arpa. 3600 IN PTR testhost.testdomain.com.
;; Query time: 11 msec
;; SERVER: 10.217.1.206#53(10.217.1.206)
;; WHEN: Fri Feb 12 13:28:16 2010
;; MSG SIZE rcvd: 82
#
在登录期间,主机可能会对它收到的数据包的源地址的 IP 地址执行反向查找。根据主机的配置不同,查找失败会花费一定的时间,然后继续登录。这个过程让用户觉得登录时间很长。
在 dig 返回的输出中寻找 ANSWER SECTION — 具体地说,寻找 PTR 记录,这是主机名的指针。如果没有返回这个指针,则说明登录延迟就是由此造成的。
MAC 地址查询
如果应用程序需要 MAC 地址 — 例如,由于 ACL 基于 MAC 地址、防火墙规则基于 MAC 地址或配置需要 MAC 地址(例如 Linux® 和 Sun® Solaris® 上的 KickStart 或 JumpStart 安装服务) — 那么使用 entstat 并查看输出中的 Hardware Address,即可查明本地接口的 MAC 地址,见 清单 14 中的示例。
清单 14. 显示网络适配器的以太网统计数据
# entstat -d en2
-------------------------------------------------------------
ETHERNET STATISTICS (en2) :
Device Type: 10/100/1000 Base-TX PCI-X Adapter (14106902)
Hardware Address: 00:02:55:d3:37:be
Elapsed Time: 114 days 22 hours 48 minutes 20 seconds
Transmit Statistics: Receive Statistics:
-------------------- -------------------
Packets: 490645639 Packets: 3225432063
Bytes: 9251643184881 Bytes: 215598601362
Interrupts: 0 Interrupts: 3144149248
Transmit Errors: 0 Receive Errors: 0
Packets Dropped: 0 Packets Dropped: 0
Bad Packets: 0
Max Packets on S/W Transmit Queue: 109
S/W Transmit Queue Overflow: 0
Current S/W+H/W Transmit Queue Length: 0
Broadcast Packets: 442 Broadcast Packets: 10394992
Multicast Packets: 0 Multicast Packets: 349
No Carrier Sense: 0 CRC Errors: 0
DMA Underrun: 0 DMA Overrun: 0
Lost CTS Errors: 0 Alignment Errors: 0
Max Collision Errors: 0 No Resource Errors: 0
Late Collision Errors: 0 Receive Collision Errors: 0
Deferred: 0 Packet Too Short Errors: 0
SQE Test: 0 Packet Too Long Errors: 0
Timeout Errors: 0 Packets Discarded by Adapter: 0
Single Collision Count: 0 Receiver Start Count: 0
Multiple Collision Count: 0
Current HW Transmit Queue Length: 0
General Statistics:
-------------------
No mbuf Errors: 0
Adapter Reset Count: 0
Adapter Data Rate: 200
Driver Flags: Up Broadcast Running
Simplex 64BitSupport ChecksumOffload
PrivateSegment DataRateSet
10/100/1000 Base-TX PCI-X Adapter (14106902) Specific Statistics:
--------------------------------------------------------------------
Link Status: Up
Media Speed Selected: 100 Mbps Full Duplex
Media Speed Running: 100 Mbps Full Duplex
PCI Mode: PCI-X (100-133)
PCI Bus Width: 64-bit Jumbo
Frames: Disabled
TCP Segmentation Offload: Enabled
TCP Segmentation Offload Packets Transmitted: 260772859
TCP Segmentation Offload Packet Errors: 0
Transmit and Receive Flow Control Status: Disabled
Transmit and Receive Flow Control Threshold (High): 32768
Transmit and Receive Flow Control Threshold (Low): 24576
Transmit and Receive Storage Allocation (TX/RX): 16/48
#
如果一个远程主机对于您的主机是已知的,因此在缓存中存在条目,那么可以使用 arp 查明这个主机的 MAC 地址(见 清单 15)。
清单 15. 显示 arp 表中的主机条目
# arp testhost
testhost (10.217.1.206) at 0:c:29:44:90:28 [ethernet] stored in bucket 0
#
如果 arp 缓存中没有远程主机的条目,可以通过使用 ping 添加条目。
是否正在发送数据包?
如果主机在某种程度上没有响应(完全没有响应或者在某一端口上没有响应),需要检查您的主机是否正在发送数据包,用本地应用程序或命令再现问题。然后,使用 tcpdump 显示发送到目标主机的数据包,见 清单 16 中的示例。
清单 16. 显示发送到特定主机的数据包
# tcpdump -i en2 dst host testhost
tcpdump: listening on en2
10:08:24.912057892 myhost.46183 > testhost.22: P 1299060979:1299061027(48)
ack 3373421618 win 17520 (DF) [tos 0x10]
10:08:25.009291439 myhost.46183 > testhost.22: P 1:49(48) ack 48 win 17520 (DF)
[tos 0x10]
10:08:25.093832676 myhost.46183 > testhost.22: . ack 96 win 17520 (DF)
[tos 0x10]
10:08:25.249319253 myhost.46183 > testhost.22: P 1299061075:1299061123(48) ack 3373421714
win 17520 (DF) [tos 0x10]
^C
53 packets received by filter
0 packets dropped by kernel
#
如果没有看到数据包离开您的主机,那么要么是发送数据的应用程序有问题,要么是接口或路由有问题(可以用本节前面介绍的步骤进行诊断)。
是否正在接收数据包?
如果主机在某种程度上没有响应(完全没有响应或者在某一端口上没有响应),需要检查是否正在从此主机接收数据包,那么用本地应用程序或命令再现问题。然后,使用 tcpdump 显示从此主机接收的数据包,见 清单 17。
清单 17. 显示特定主机发送的数据包
# tcpdump -i en2 src host testhost
tcpdump: listening on en2
10:10:38.505848354 testhost.22 > myhost.46183: . ack 130 win 24820 (DF) [tos 0x10]
10:10:38.505916972 testhost.22 > myhost.46183: F 529:529(0) ack 225 win 24820 (DF)
[tos 0x10]
10:10:43.855153846 testhost > myhost: icmp: echo reply
10:10:44.855224394 testhost > myhost: icmp: echo reply
^C
102 packets received by filter
0 packets dropped by kernel
#
如果已经确认您的主机正在发送数据包(使用 是否正在发送数据包? 中说明的步骤),但是没有收到数据包,就意味着此主机没有响应、主机上的服务没有响应或者没有反向路由(不存在反向路由或路由上的防火墙阻止通信流)。
已建立连接但应用程序或命令失败了
如果用户抱怨说应用程序或命令看起来已经成功地建立了连接,但是之后就失败了,那么看看这个命令是否有调试、跟踪或详细输出选项,重新运行,看看生成的额外输出是否能够指出问题的根源。例如,ssh 和 scp 有详细输出开关 (-v),这可以提供客户机和服务器之间协议交换的详细信息:
建立到远程主机的 TCP 端口 22 的连接。
找到本地私有密钥文件。
交换协议版本并答成一致。
找到远程主机密钥并与本地 known_hosts 文件中此主机的条目匹配。
对于在本地找到的每个私有密钥类型,尝试执行密钥身份验证。
当这些操作失败时,提示用户输入身份验证密码。
用户输入密码,登录成功,出现 shell 提示。
详细输出选项有助于查明哪个步骤失败了,可能是问题的原因。
使用 truss 跟踪命令或运行远程服务的进程(见 跟踪有问题的应用程序或守护进程)。
跟踪有问题的应用程序或守护进程
如果前面的步骤无法查明问题的准确原因,需要进一步诊断连接问题,那么使用 truss 对命令进行详细的系统调用跟踪。
另外,使用 truss 对运行您试图连接的远程服务的守护进程进行详细的系统调用跟踪。如果您无权访问运行此进程的用户或根用户,可能需要向远程主机的系统管理员求助。
当某个系统命令返回错误时,显示非零的返回码,显示形式是 Err#,后面跟着错误号和错误码(例如 ENOSPC)。可以在 /usr/include/sys/errno.h 中找到标准的错误码,这有助于查明错误的原因。例如,如果一个系统调用返回 Err#2 ENOENT(没有这样的文件或目录),就表示此命令要寻找一个文件或目录,但是无法找到,因此运行失败。如果一个系统调用返回 Err#28 ENOSPC(设备上没有剩余空间),就表示磁盘或文件系统满了,这可能导致守护进程无法响应服务请求。
详细的跟踪会显示来自系统调用参数的数据 (-x all) 以及 Read (-r all) 和 Write (-w all) 调用的缓冲区的内容。这些缓冲区的内容有时候能够指出问题的原因。
还可以使用 -D 开关显示每个系统调用的时间差,时间差表示自前一个事件以来流逝的秒数。应该寻找比较长的时间差,这些情况可能表示存在延迟,会导致响应时间长且性能不佳。
结束语
网络问题诊断不一定像某些系统管理员认为的那样困难。本系列说明,只要具备适当的知识,您就可以诊断、分析和查明许多需要向网络管理员求助的问题的原因,让网络管理员能够更轻松地纠正问题。在某些情况下,您甚至可以自己解决问题。祝您顺利解决问题!
更多精彩
赞助商链接