介绍
CoreOS 引入了一些有趣的技术,使构建分布式系统变得容易,然而,这些工具可能对新用户不熟悉,并且有自己的异常性。
在本指南中,我们将讨论一些基本的故障排除程序,用于与CoreOS主机工作,他们运行的Docker容器和服务管理工具,这些工具将一些不一样的部件聚集在一起。
调试您的云配置文件
当一个群集未能正确出现时,新的和经验丰富的CoreOS用户遇到的最常见的问题之一是无效的云配置文件。
CoreOS 需要在创建时将云配置文件传输到您的服务器中。它使用该文件中包含的信息来启动并启动或加入现有集群。
一些事情要检查你的云配置文件:
- 联合国 ** 它从"#云-相通"开始吗? **: 每传入的云配置文件,都必须从"#云配置"开始,在一行独站. 虽然这通常是YAML中被忽略的注释,但在此情况下,此行用于向云init系统发出信号,表示其中包含配置数据.
- ** 您的文件是否包含有效的YAML? ** : Cloud-config文件是用YAML编写的,一种数据序列化格式,以可读性为重点. 如果您有问题, 请将您的云配置粘贴到在线 [YAML 验证符 (http://codebeautify.org/yaml-validator ) 中 。 您的文件不应包含错误 。 CoreOS提供了一个有用的工具,可以检查您云配置文件的语法,Cloud-Config 校验器. 你用的是新的发现标志吗? 发现地址会跟踪你的机器数据 即使整个集群都下来了 发现注册会失败 当你启动一个旧的代号, 特别是如果你已经注册了同一个IP地址。 每次启动集群时使用新的发现符来避免这个问题.
- 你开始提供舰队等服务了吗? **: 为使组群正确运作,必须启动两项服务,即
快取'和
快取'。 您应该看看我们的指南 [在数字海洋上运行 CoreOS (https://andsky.com/tech/tutorials/how-to-set-up-a-coreos-cluster-on-digitalocean) , 用于一个满足这些最低要求的基本云配置文件 。 (英语)
您只能在机器创建时传入云配置文件,所以如果您犯了错误,请摧毁服务器实例并重新启动(在大多数情况下使用新代币)。
一旦您确信云配置文件本身是正确的,下一步是登录主机,以确保文件被正确处理。
在大多数情况下,这应该很容易,因为在DigitalOcean上,您需要在创建过程中向服务器添加 ssh 密钥,这意味着您通常可以在服务器中 ssh 来解决问题。
通过数字海洋控制面板登录
然而,某些时候,您的云配置可能实际上会影响您的服务器的网络可用性。在这种情况下,您将不得不通过DigitalOcean控制面板登录。
要处理此问题,您必须使用一个新的云配置文件重新创建服务器,该文件包含核心
用户的密码输入。由于重建要求,如果您一直在看到这个问题,并且想要获取更多信息,这可能只会是有用的。
密码必须以哈希的形式来生成,您可以通过几种不同的方式来生成这些密码,这取决于您所拥有的软件。下列任何一种都将奏效,因此使用哪种选项最适合您:
1mkpasswd --method=SHA-512 --rounds=4096
2openssl passwd -1
3python -c "import crypt, getpass, pwd; print crypt.crypt('password', '\$6\$SALT\$')"
4perl -e 'print crypt("password","\$6\$SALT\$") . "\n"'
一旦你有一个哈希,你可以将一个新的部分添加到你的云配置(在coreos
部分之外),称为用户
,以放置此信息:
1#cloud-config
2users:
3 - name: core
4 passwd: hashed_password
5coreos:
6 . . .
验证您的YAML语法,然后在重新创建服务器时使用这个新的云配置,然后可以使用您选择的密码通过DigitalOcean控制面板登录。
检查个人主机
一旦您登录,您应该检查一些事情,看看您的云配置是否被正确处理。
检查基本服务中的错误
一个简单的方法是问fleetctl
它知道哪些机器,如果它返回没有错误,这意味着fleet
和etcd
已经正确启动,并且他们正在与其他主机进行通信。
1fleetctl list-machines
如果你在这里收到错误,你应该看看一些事情. 一个常见的错误看起来像这样:
12014/09/18 17:10:50 INFO client.go:278: Failed getting response from http://127.0.0.1:4001/: dial tcp 127.0.0.1:4001: connection refused
22014/09/18 17:10:50 ERROR client.go:200: Unable to get result for {Get /_coreos.com/fleet/machines}, retrying in 100ms
32014/09/18 17:10:50 INFO client.go:278: Failed getting response from http://127.0.0.1:4001/: dial tcp 127.0.0.1:4001: connection refused
42014/09/18 17:10:50 ERROR client.go:200: Unable to get result for {Get /_coreos.com/fleet/machines}, retrying in 200ms
因为这代表了彼此上面的不同组件堆栈,让我们从顶层开始,然后工作下来。
1systemctl status -l fleet
1● fleet.service - fleet daemon
2 Loaded: loaded (/usr/lib64/systemd/system/fleet.service; static)
3 Drop-In: /run/systemd/system/fleet.service.d
4 └─20-cloudinit.conf
5 Active: active (running) since Thu 2014-09-18 17:10:50 UTC; 2min 26s ago
6 Main PID: 634 (fleetd)
7 CGroup: /system.slice/fleet.service
8 └─634 /usr/bin/fleetd
9
10Sep 18 17:13:07 dumb1 fleetd[634]: INFO client.go:278: Failed getting response from http://localhost:4001/: dial tcp 127.0.0.1:4001: connection refused
11Sep 18 17:13:07 dumb1 fleetd[634]: ERROR client.go:200: Unable to get result for {Update /_coreos.com/fleet/machines/795de101bcd24a3a96aa698f770f0074/object}, retrying in 800ms
12Sep 18 17:13:08 dumb1 fleetd[634]: INFO client.go:278: Failed getting response from http://localhost:4001/: dial tcp 127.0.0.1:4001: connection refused
正如您所看到的,该服务正在运行,但无法连接到4001
端口,即etcd
端口,这表明问题可能是etcd
。
对于我们每个基本服务,我们应该检查状态和日志,一般的方式是:
1systemctl status -l service
2journalctl -b -u service
状态
命令为我们提供服务的状态和最后几行日志,日志命令为我们提供完整的日志。
如果我们尝试这些与etcd
接下来,我们可以看到etcd
服务在我们的情况下不运行:
1systemctl status -l etcd
1● etcd.service - etcd
2 Loaded: loaded (/usr/lib64/systemd/system/etcd.service; static)
3 Drop-In: /run/systemd/system/etcd.service.d
4 └─20-cloudinit.conf
5 Active: activating (auto-restart) (Result: exit-code) since Thu 2014-09-18 17:17:03 UTC; 9s ago
6 Process: 938 ExecStart=/usr/bin/etcd (code=exited, status=1/FAILURE)
7 Main PID: 938 (code=exited, status=1/FAILURE)
8
9Sep 18 17:17:03 dumb1 systemd[1]: etcd.service: main process exited, code=exited, status=1/FAILURE
10Sep 18 17:17:03 dumb1 systemd[1]: Unit etcd.service entered failed state.
如果我们检查etcd
日志,我们会看到这样的东西:
1journalctl -b -u etcd
1Sep 18 17:21:27 dumb1 systemd[1]: Starting etcd...
2Sep 18 17:21:27 dumb1 systemd[1]: Started etcd.
3Sep 18 17:21:27 dumb1 etcd[1160]: [etcd] Sep 18 17:21:27.966 INFO | The path /var/lib/etcd/log is in btrfs
4Sep 18 17:21:27 dumb1 etcd[1160]: [etcd] Sep 18 17:21:27.967 INFO | Set NOCOW to path /var/lib/etcd/log succeeded
5Sep 18 17:21:27 dumb1 etcd[1160]: [etcd] Sep 18 17:21:27.967 INFO | Discovery via https://discovery.etcd.io using prefix /.
6Sep 18 17:21:28 dumb1 etcd[1160]: [etcd] Sep 18 17:21:28.422 WARNING | Discovery encountered an error: invalid character 'p' after top-level value
7Sep 18 17:21:28 dumb1 etcd[1160]: [etcd] Sep 18 17:21:28.423 WARNING | 795de101bcd24a3a96aa698f770f0074 failed to connect discovery service[https://discovery.etcd.io/]: invalid character 'p' after top-level value
8Sep 18 17:21:28 dumb1 etcd[1160]: [etcd] Sep 18 17:21:28.423 CRITICAL | 795de101bcd24a3a96aa698f770f0074, the new instance, must register itself to discovery service as required
9Sep 18 17:21:28 dumb1 systemd[1]: etcd.service: main process exited, code=exited, status=1/FAILURE
10Sep 18 17:21:28 dumb1 systemd[1]: Unit etcd.service entered failed state.
突出列表表明,这个特定的实例没有发现代币。
检查文件系统查看由云配置生成的配置文件
接下来要检查的是云配置生成了哪些服务文件。
当您的 CoreOS 机器处理云配置文件时,它会生成一个systemd
单元文件,它会使用它来启动fleet
和etcd
。
1cd /run/systemd/system
2ls -F
1etcd.service.d/ fleet.service.d/ oem-cloudinit.service
您可以看到由 CoreOS 自动处理的通用 oem-cloudinit.service
文件,以及其中包含服务信息的目录。
1cat etcd.servicd.d/20-cloudinit.conf
1[Service]
2Environment="ETCD_ADDR=10.132.247.162:4001"
3Environment="ETCD_DISCOVERY=https://discovery.etcd.io/"
4Environment="ETCD_NAME=795de101bcd24a3a96aa698f770f0074"
5Environment="ETCD_PEER_ADDR=10.132.247.162:7001"
正如你可以在这里看到的,ETCD_DISCOVERY 地址与我们在日志中发现的错误相匹配:没有发现令牌附在末尾.我们需要使用一个有效的发现令牌的云配置重新构建我们的机器。
您可以通过键入获取有关float
的类似信息:
1cat fleet.service.d/20-cloudinit.conf
1[Service]
2Environment="FLEET_METADATA=region=nyc,public_ip=104.131.1.89"
3Environment="FLEET_PUBLIC_IP=10.132.247.162"
在这里,我们可以看到‘ fleet’在云配置中获得了一些元数据信息,这可以在创建服务单元文件时用于编程。
检查对元数据服务的访问
当使用DigitalOcean创建CoreOS服务器时提供的实际云配置文件是使用元数据服务存储的. 如果您无法在您的服务器上找到云配置的任何证据,则可能无法从DigitalOcean元数据服务中提取信息。
从您的主机内部,类型:
1curl -L 169.254.169.254/metadata/v1
1id
2hostname
3user-data
4vendor-data
5public-keys
6region
7interfaces/
8dns/
您必须包含-L
来跟随重定向。169.254.169.254
地址将用于 every 服务器,因此您不应该修改此地址。这会显示包含有关您的服务器信息的元数据字段和目录。如果您无法从您的 DigitalOcean CoreOS 服务器中获取此信息,您可能需要打开支持票。
您可以通过额外的弯曲命令来探索这里的每个条目,但包含云配置文件的条目是用户数据
字段:
1curl -L 169.254.169.254/metadata/v1/user-data
1#cloud-config
2users:
3 - name: core
4 passwd: $6$CeKTMyfClO/CPSHB$02scg00.FnwlEYdq/oXiXoohzvvlY6ykUck1enMod7VKJrzyGRAtZGziZh48LNcECu/mtgPZpY6aGCoj.h4bV1
5coreos:
6 etcd:
7 # generated token from https://discovery.etcd.io/new
8 discovery: https://discovery.etcd.io/
9 # multi-region and multi-cloud deployments need to use $public_ipv4
10 addr: $private_ipv4:4001
11 peer-addr: $private_ipv4:7001
12 fleet:
13 public-ip: $private_ipv4
14 metadata: region=nyc,public_ip=$public_ipv4
15 units:
16 - name: etcd.service
17 command: start
18 - name: fleet.service
19 command: start
如果您可以从这个位置读取云配置,这意味着您的服务器有读取云配置数据的能力,并且在启动服务器时应该执行其指令。
解决 CoreOS 主机中的其他问题
如果你需要做进一步的调试,你可能会很快发现CoreOS包含一个非常小的基础安装,因为它预计所有的软件都将在容器中运行,它甚至不包括一些最基本的实用程序。
幸运的是,CoreOS开发人员为此问题提供了优雅的解决方案. 通过使用每个主机中包含的工具箱
脚本,您可以启动一个Fedora容器,可以访问主机系统。
要启动它,只需使用工具箱
命令:
1toolbox
这将拉下最新的 Fedora 图像,并将您放入容器内的命令行. 如果您做一些快速检查,您将意识到您可以访问主机系统的网络:
1ip addr show
11: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
2 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
3 inet 127.0.0.1/8 scope host lo
4 valid_lft forever preferred_lft forever
5 inet6 ::1/128 scope host
6 valid_lft forever preferred_lft forever
72: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
8 link/ether 04:01:28:7c:39:01 brd ff:ff:ff:ff:ff:ff
9 inet 169.254.180.43/16 brd 169.254.255.255 scope link eth0
10 valid_lft forever preferred_lft forever
11 . . .
您还可以完全访问主机的流程:
1ps aux
1USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
2root 1 0.0 0.1 106024 4912 ? Ss 17:10 0:04 /usr/lib/systemd/systemd --switched-root --system --deserialize 19
3root 2 0.0 0.0 0 0 ? S 17:10 0:00 [kthreadd]
4root 3 0.0 0.0 0 0 ? S 17:10 0:00 [ksoftirqd/0]
5root 5 0.0 0.0 0 0 ? S< 17:10 0:00 [kworker/0:0H]
6root 6 0.0 0.0 0 0 ? S 17:10 0:00 [kworker/u4:0]
7root 7 0.0 0.0 0 0 ? S 17:10 0:00 [rcu_sched]
8root 8 0.0 0.0 0 0 ? S 17:10 0:00 [rcu_bh]
9. . .
例如,我们可以通过使用Fedora包管理器安装htop
,一个具有额外功能的顶级克隆:
1yum install htop -y && htop
这将带来流程监视器,所有主机的流程都已加载。
要退出容器环境,键入退出
,或按CTRL-]
三次快速,您将被放回主机的壳会话。
任何主机的故障排除服务
您可能需要解决的问题的另一个领域是您正在运行的实际服务. 由于我们有fleet
和fleetctl
来管理我们服务的集群范围内,我们的第一步可以在集群中的任何服务器上预装。
首先,我们应该从舰队
的角度来了解您的服务的健康状况,从每个服务运行的个别主机的角度来了解。
首先,通过键入,了解舰队
如何看待服务状态:
1fleetctl list-unit-files
1UNIT HASH DSTATE STATE TARGET
2apache-discovery@4444.service 06d78fb loaded loaded 04856ec4.../10.132.249.212
3apache-discovery@7777.service 06d78fb loaded loaded 197a1662.../10.132.249.206
4apache-discovery@8888.service 06d78fb loaded loaded e3ca8fd3.../10.132.252.37
5apache@4444.service 0f7f53b launched launched 04856ec4.../10.132.249.212
6apache@7777.service 0f7f53b launched launched 197a1662.../10.132.249.206
7apache@8888.service 0f7f53b launched launched e3ca8fd3.../10.132.252.37
8nginx_lb.service c8541af launched launched 96ec72cf.../10.132.248.177
这将为您提供有关舰队
所知道的所有服务的概述。这个输出包含一些非常重要的信息。
- ** UNIT**:这是该单位的名称。 就我们的情况而言,前六个服务都是实例单元(在此查找更多关于[templades and example (https://andsky.com/tech/tutorials/how-to-create-flexible-services-for-a-coreos-cluster-with-fleet-unit-files)),底部似乎是一个静态实例. 这些名字可以用来发布影响每个服务的命令.
- HASH:这是用于控制此服务的单位文件的散列. 如您所见,所有
apache-discovery ' 实例都来自同一模板文件。
apache ' 事件都是由另一个事件引起的。 这可以帮助查看您的任何服务是否通过使用过时的单位文件表现出了奇怪的行为. - **DSTAE **:这是单位的理想状态. 当您发出命令以
fleetctl
来改变一个单位的状态时,此列更改以反映该单位的理想状态。 - STATE:这是单位的_实际_状态,称为"出击". 如果这不同于DSTATE,则可能意味着一个操作失败了.
- TARGET:已预定运行此服务的机器. 当一个单元启动或装入时,即可使用。 它包含了机器ID和机器的IP地址. (英语)
正如您所看到的,有很多信息可以帮助您解决问题。
然而,这不是唯一重要的地方来检查,重要的是要意识到有时舰队
会不同意机器的本地systemd
实例关于服务的状态,这可能出于各种原因,例如如果一个单位在内部启动或停止另一个单位。
要获取有关每个服务的状态的信息,从运行该服务的主机的systemd
实例中获取,请使用list-units
命令:
1fleetctl list-units
1UNIT MACHINE ACTIVE SUB
2[email protected] 04856ec4.../10.132.249.212 active running
3[email protected] 197a1662.../10.132.249.206 active running
4[email protected] e3ca8fd3.../10.132.252.37 active running
5[email protected] 04856ec4.../10.132.249.212 active running
6[email protected] 197a1662.../10.132.249.206 active running
7[email protected] e3ca8fd3.../10.132.252.37 active running
8nginx_lb.service 96ec72cf.../10.132.248.177 active running
在这里,我们可以看到所有服务都列为正在运行的,这与列表单元文件
显示的信息不一致,这是因为每个apache
服务都会启动相关的apache-discovery
服务,而不会让fleet
知道。
要获取有关任何服务的更多信息,您可以使用fleetctl
访问主机系统的systemctl状态
和journalctl -u
信息。
1fleetctl status service_name
1● apache@4444.service - Apache web server service on port 4444
2 Loaded: loaded (/run/fleet/units/apache@4444.service; linked-runtime)
3 Active: active (running) since Thu 2014-09-18 18:50:00 UTC; 7min ago
4 Process: 3535 ExecStartPre=/usr/bin/docker pull imchairmanm/apache (code=exited, status=0/SUCCESS)
5 Process: 3526 ExecStartPre=/usr/bin/docker rm apache.%i (code=exited, status=0/SUCCESS)
6 Process: 3518 ExecStartPre=/usr/bin/docker kill apache.%i (code=exited, status=0/SUCCESS)
7 Main PID: 3543 (docker)
8 CGroup: /system.slice/system-apache.slice/apache@4444.service
9 └─3543 /usr/bin/docker run -t --name apache.4444 -p 10.132.249.212:4444:80 imchairmanm/apache /usr/sbin/apache2ctl -D FOREGROUND
或者通过键入阅读日记:
1fleetctl journal service_name
1-- Logs begin at Mon 2014-09-15 14:54:12 UTC, end at Thu 2014-09-18 18:57:51 UTC. --
2Sep 17 14:33:20 lala2 systemd[1]: Started Apache web server service on port 4444.
3Sep 17 14:33:20 lala2 docker[21045]: AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.17.0.10. Set the 'ServerName' directive globally to suppress this message
4Sep 18 18:49:29 lala2 systemd[1]: Stopping Apache web server service on port 4444...
5Sep 18 18:49:39 lala2 docker[3500]: apache.4444
6Sep 18 18:49:39 lala2 systemd[1]: Stopped Apache web server service on port 4444.
7Sep 18 18:49:58 lala2 systemd[1]: Starting Apache web server service on port 4444...
8Sep 18 18:49:58 lala2 docker[3518]: apache.4444
9Sep 18 18:49:58 lala2 docker[3526]: apache.4444
10Sep 18 18:49:58 lala2 docker[3535]: Pulling repository imchairmanm/apache
11Sep 18 18:50:00 lala2 systemd[1]: Started Apache web server service on port 4444.
例如,如果您的单元文件宣布一个不可用依赖,这将出现在这里(如果依赖尚未被加载到舰队
时,这可能会发生)。
您在发出这些命令时可能遇到的一个错误是:
1Error running remote command: SSH_ AUTH _SOCK environment variable is not set. Verify ssh-agent is running. See https://github.com/coreos/fleet/blob/master/Documentation/using-the-client.md for help.
这是一个迹象表明,当您连接到这个主机时,您没有转发您的 ssh 用户代理,以便舰队
获取群集中的其他机器的信息,它使用您在本地计算机上保留的 SSH 凭证连接。
要做到这一点,您必须在本地计算机上运行 ssh 代理,并添加您的私钥。
1eval $(ssh-agent)
2ssh-add
1Identity added: /home/username/.ssh/id_rsa (/home/username/.ssh/id_rsa)
一旦您的 ssh 代理被允许访问您的私钥,您应该使用 -A
选项连接到您的 CoreOS 主机以传输此信息:
1ssh -A core@coreos_host
这将允许你正在使用的机器使用你的身份证来连接到群集中的其他机器. 它允许你读取远程群集成员的systemd
信息。
从运行服务的主机处理集装箱
虽然您可以使用仅fleetctl
获取大量信息,但有时您必须去负责运行服务的主机来解决问题。
正如我们上面提到的,当您在连接时传递您的SSH信息时,这很容易。从您连接的主机,您可以使用fleetctl``跳跃
到其他机器。您可以指定机器ID,或者只是服务名称。
1fleetctl ssh service_name
这将为您提供一个 ssh 连接到指定运行该服务的主机. 服务必须处于加载
或启动
状态才能工作。
例如,您可以访问更完整的journalctl
旗帜,这些旗帜可能无法通过fleetctl journal
命令访问:
1journalctl -b --no-pager -u apache@4444
此时,您可能需要解决 Docker 问题. 若要查看运行容器列表,请键入:
1docker ps
1CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2b68139630337 imchairmanm/apache:latest "/usr/sbin/apache2ct 30 minutes ago Up 30 minutes 10.132.249.212:4444->80/tcp apache.4444
我们可以看到目前有一个正在运行的集装箱. 突出显示的集装箱 ID 对于更多 Docker 操作有用。
如果您的服务无法启动,您的集装箱将无法运行. 若要查看所有集装箱的列表,包括那些已退出/失败的集装箱,请通过-a
旗帜:
1docker ps -a
1CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2b68139630337 imchairmanm/apache:latest "/usr/sbin/apache2ct 31 minutes ago Up 31 minutes 10.132.249.212:4444->80/tcp apache.4444
34389108bff1a imchairmanm/apache:latest "/usr/sbin/apache2ct 28 hours ago Exited (-1) 28 hours ago apache.8888
45af6e4f95642 imchairmanm/lalala:latest "/usr/sbin/apache2ct 3 days ago Exited (-1) 3 days ago apache.7777
若要查看已启动的 last 容器,无论其状态如何,您可以使用-l
标志:
1docker ps -l
1CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2b68139630337 imchairmanm/apache:latest "/usr/sbin/apache2ct 33 minutes ago Up 33 minutes 10.132.249.212:4444->80/tcp apache.4444
一旦你有你正在寻找的容器的容器ID,你可以开始在Docker级别的调查。
1docker logs container_id
这将为您提供可以从容器中收集的日志信息,无论容器是否在运行,这都应该起作用。如果容器是互动地运行(带有i
和t
旗帜和壳会话),整个会话将在日志中可用。
您可以通过键入任何活跃的容器的运行流程列表:
1docker top container_id
在一个集装箱内进行壳会话
最有用的步骤之一是实际上在运行容器上打开壳会话,以便从内部看到发生了什么。
Docker 容器通过设置内核名空间来工作,此工具可以在这些环境中启动会话,第一步是获取您想要输入的容器的 PID:
1PID=$(docker inspect --format {{.State.Pid}} container_id)
现在,您可以通过键入该容器环境中打开壳会话:
1sudo nsenter -t $PID -m -u -i -n -p
您将在容器环境中进行壳会话,从这里您可以查看日志或进行任何其他必要的故障排除。
取决于容器是如何构建的,你可能会收到一个消息称bash
没有找到,在这种情况下,你将不得不使用一般的sh
壳,在你的命令的末尾附上它:
1sudo nsenter -t $PID -m -u -i -n -p /bin/sh
结论
这些只是您可以用来解决 CoreOS 集群问题的一些程序,这些程序应该帮助您跟踪您可能遇到的云配置文件问题,并解决您的机器正确集群和启动服务的能力。
要记住的最重要的事情之一是,调试变得越容易,你就越有关于你的系统的更多信息. 对每个组件的作用以及它们如何相互作用,有助于帮助系统的功能有一个坚实的了解是有用的。