Debug 是门艺术

本文分享了Debug的精髓,包括FindBug、FixBug和RecordBug的三步曲,并通过具体案例阐述了如何高效解决线上问题,强调了Debug技巧对于程序员的重要性。

【这是一猿小讲的第 78 篇原创分享】

最近想结合发生在身边码农身上的一些小故事,尝试表达一个观点“Coding 是门技术,Debug 是门艺术”。

上期的分享《Coding 是门技术》主要通过引入身边 Code farmer 撸码的一些真实故事,掰扯了一下开发规范以及重构可以改变代码的设计的理念,并且文末我又尝试总结了,人人皆知的一个看似专业而又非专业的撸码套路(一篇流水账,而却忘了升华,我就喜欢这么自嘲)。

但是,作为码农,撸码肯定是日常必须,毕竟要靠撸码吃饭,但是为了能更好的保住饭碗,Debug 则显得尤为重要,因为鲁迅先生说过「程序猿 20% 的时间在 Coding,80% 的时间在 Debug」鲁迅先生又说「他从来没说过」。

好了,话不多说,请扶稳坐好,我们正式来聊聊 Debug 这门玄幻的艺术。

01. Debug 的精髓


Debug 的艺术,我简单归纳为 「Debug 三步曲」。

第一步:FindBug。

无论遇到任何问题,Debug 时一定要清晰牢记,通过剥丝抽茧的方式,努力逐步缩小范围,最终锁定 Bug 的藏身之处。

第二步:FixBug。

依据撸码经验,经过多轮的修复-验证-修复-验证,最终让Bug扼杀于无形之中。

(图片来源于网络侵之删之)

第三步:RecordBug。

为了保证 Bug 不二过,当然一定要把 Bug 的原因、现象、解决方式记录在案,这样就以防其他老铁再入坑。

好了,接下来就一起看看,发生在身边高鸡攻城狮身上的一些有趣的 Debug。

02. Debug 的故事


故事一:运维小哥配置的 crontab 引发的 DeBug。

经常撸码的老铁都清楚,系统一般白天疯狂吸引客户,也就是疯狂吸金,晚上一般会启动 N 多个批处理,在运维小哥那儿也不例外,配置很多释放资源、机器巡检等一系列的 crontab 任务。

近期团队让运维小哥帮忙搞了一台新机器,上面部署了新服务,并且配置了一个每天凌晨 1 点 10 分定时执行清洗数据的任务。

10 1 * * * /app/clear.sh >> /app/log/clear.log

理想很丰满,现实却很骨感。每天凌晨 1 点定时任务却迟迟未执行,于是就开启了 Debug 的过程。

Step 01:FindBug。

核心原则「努力缩小 Bug 范围」。

  • 首先排除常规性的配置错误,例如目录、脚本名称配置错误;

  • 然后排除脚本是否有执行权限,通过 ls 命令,发现脚本执行权限正常,而且手动执行脚本也没毛病;

  • 接着重新调整 crontab 的执行时间,确认是否会执行,发现确实到点了不执行,不过却有一个很诡异的一个现象,那就是有一个每两分钟执行一次的测试脚本 test.sh 却能够正常执行;

  • 大胆猜测,由于每两分钟的任务正常执行,有小时配置的任务却不执行,此时不得不怀疑是机器的时间导致的?!运维小哥坚信时区没问题,因为近期刚调整过,但是处于 Debug 环节,还是需要通过命令再次确认时区信息。

如上图示意,发现时区配置确实没啥毛病。那哪里会出现问题呢?会不会是 crontab 服务启动的时候,时间还没有调整呢,导致 crontab 的时间与当前的时间不一致?

眼尖的同学,此时会发现,时区配置的确晚于 crond 启动时间。

Step 02:FixBug。

核心原则「扼杀 Bug 于无形」。

由于时区配置,但是没有重启 crontab 服务导致,那就重启 crond 服务呗,重启完,时间确实对了,效果如下。

修改完成之后,经测试完全 OK。目前再去看线上清理的批处理,一切跑的又是那么的完美。

Step 03:RecordBug。

核心原则「每一个 Bug 都载入史册」。

故事二:攻城狮玄幻的 rz 命令上传的奇葩 DeBug。

不知道大家平时喜欢用什么登录线上服务器,身边攻城狮用的最多的莫过于 SecureCRT,用这款工具日常连服务器、查日志不再话下,不过用的偏多的就是用 rz 命令、sz 命令。

假如要向服务器上传文件,用 rz 命令就可以轻松搞定;假如要下载文件,用 sz 命令也可以轻松搞定(没用过的老铁建议尝试一下,绝对会让你 WOW!)。

不过最近身边攻城狮光头强,倒是在用 rz 命令上传文件时,栽了个大跟头,先抛个情景对话,让我们感受一下光头强那种百思不得解的痛苦。

眼尖的同学会发现主要问题,在光头强同学输入 rz 命令后,总是提示如下信息。

rz waiting to receive. Starting zmodem transfer.  Press Ctrl+C to cancel.

然后就没有然后啦,汗颜。正常情况下输入完命令,会提示上传文件窗口,然后选择要上传的文件,就应该上传成功了。

何解?面对工具性的 Bug,无需花太多时间在 FindBug 上,直接可以跳到 FixBug 环节,建议直接卸掉重装就好了,但是令人匪夷所思的是重装了还是不好使啊,而且光头强还没有其它 ftp 上传工具。

此时脑海中应该弥补一个场景:紧急部署线上应用,但是就你一个人有登录堡垒机的权限,而你又无法进行上传文件,那么此情此景,只能用下面这张图来形容。

面对这种比较玄幻的问题,只能另辟蹊径,建议光头强老弟直接拖住上传的文件到 SecureCRT,未成想确实好使!

面对这种玄幻的奇葩问题,也只能奇葩对待啦。

03. Debug 的武器


武器推荐系列一:用 Debug 来发现「什么是别人家的代码?」

为什么别人家的代码,不但写的好,而且Bug 少,最重要的是从来没因为 Bug 扣过绩效,莫非有什么奇招。

撸码久了就知道了,Coding 是门技术,但是撸码也是有套路的,很多攻城狮在撸码完成之后,喜欢采用 FindBugs 工具插件,找找有没有潜在的代码风险。

不过也有很多老铁,撸码完成之后,喜欢用 sonarQube 来提升提升代码的逼格,随便贴一效果图。

上期分享我们提到了《阿里巴巴Java开发手册 v666.pdf》,其实也有一款把阿里巴巴 Java 开发手册中的规约的插件,可以在你撸码的时候,自动帮你检测是否符合规范(So,牛掰),该插件已经在 Github 上开源。

https://github.com/alibaba/p3c

以上几款让 Bug 扼杀在摇篮里的武器,感兴趣的老铁,可以亲自体验一下。

武器推荐系列二:线上甩锅的 DeBug。

久入职场,迟早会经历各种奇葩的锅。锅该背的背,不该的背坚决不背,要有自己的态度。但是面对不该你背的大黑锅,如果你却拿不出证据,只能哑巴吃黄连,有苦也说不出。

例如你刚上线了应用,服务器 cpu 或者内存就疯狂报警,此时微信群里直接把锅扣你头上,你该怎么应对?

那肯定是沉着冷静,并按照之前的一篇分享《这部技术葵花宝典真的很硬核》逐步去排查解决。

另外面对线上重要模块却没有任何日志输出,排查无从下手的情形时,不妨在关键位置打印日志,以便尽快定位问题,快速止损。

04. Debug 的态度


有 Bug 不可怕,Debug 是我们前行的催化剂。

面对 Bug 要沉着冷静,不要像生吞蜈蚣一样,百爪挠心。

Debug 要剥丝抽茧,努力缩小范围,找到 Bug 点;通过日常的经验积累,解决 Bug 于无形之中;针对 Fix 的 Bug一定要载入史册,因为它绝对是一笔财富。

再抛几个玄幻的问题 Debug 场景,结束咱们的分享。

  • 为什么你一来我这儿就好了?刚刚怎么调试都不行?!

    哎,Debug 是玄学艺术!

  • 为什么你这么一操作就好了?刚刚我也是这么操作的啊?!

    哎,Debug 是玄学艺术!

  • 线上部署了 4 台服务,配置都一样,项目 war 包也一样,为什么偏偏只有这一台有问题?几经排查无解,而且换一台机器又恢复了平静。

    哎,Debug 是玄学艺术!

好了,今天的分享,到这就结束啦,希望你们能够喜欢,芸芸众生,相遇相识便是缘,如果有一丁点喜欢,就偷偷点个“在看

推荐阅读:

Coding 是门技术

这部技术葵花宝典真的很硬核

<think>首先,用户的问题是:“我想跟踪某个中断的使能情况 请问如何跟踪Linux内核中某个中断的使能状态”。这涉及到Linux内核中断管理。 根据系统级指令: - 所有行内数学表达式使用$...$格式。 - 独立公式使用$$...$$格式并单独成段。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识。 - 回答结构清晰,帮助用户逐步解决问题,保证真实可靠。 参考提供的引用: - 引用[1]:Linux内核中断控制接口,用于禁止或激活中断。 - 引用[2]:Linux内核中断机制,包括软中断和任务队列。 - 引用[3]:request_irq函数用于申请中断,会激活中断。 用户想跟踪某个中断的使能状态。在Linux内核中,中断的使能状态通常与中断控制器相关。每个中断都有一个状态,表示它是否被使能或禁止。 关键点: - 在Linux内核中,中断的使能状态可以通过中断描述符(irq_desc)结构体来查看。 - 具体地,每个中断号对应一个irq_desc结构体,其中包含状态信息。 - 状态信息包括中断是否被使能、是否被屏蔽等。 - 用户可以通过内核函数或工具来访问这些信息。 如何跟踪: 1. **使用内核函数**:在内核代码中,可以使用函数如`irq_is_enabled(unsigned int irq)`来检查特定中断是否使能。这个函数返回布尔值。 2. **使用proc文件系统**:Linux提供了/proc/interrupts文件,显示中断统计信息,但不直接显示使能状态。另一个文件是/proc/irq/<irq_num>/,其中<irq_num>是中断号。在这个目录下,可能有文件如"enable"或状态文件。 3. **使用sysfs**:在/sys/kernel/irq/目录下,每个中断号有一个子目录,包含文件如"enabled"或"state",可以读取来查看使能状态。 4. **内核模块**:如果用户需要编程跟踪,可以编写一个内核模块使用`irq_desc_get()`或类似函数获取irq_desc结构体,然后检查其状态字段。 5. **调试工具**:使用工具如`cat /proc/interrupts`查看中断计数,但不直接显示使能状态。更高级的调试可能需要自定义脚本或工具。 具体步骤: - 确认中断号:首先,需要知道要跟踪的中断号(IRQ number)。 - 检查状态:通过读取/sys/kernel/irq/<irq_num>/enabled文件(如果存在),或使用内核函数。 在引用中: - 引用[1]提到中断控制函数,如禁止和激活中断。 - 引用[3]提到request_irq会激活中断。 所以,回答应该基于这些构建。 回答结构: 1. **介绍问题**:解释什么是中断使能状态。 2. **逐步指导**:提供多种方法来跟踪状态。 3. **代码示例**:如果适用,给出示例代码或命令。 4. **注意事项**:提醒用户权限和安全问题。 5. **生成相关问题**:在末尾添加相关问题。 生成相关问题: - 基于主题,如中断管理、内核调试等。 使用中文回答。 最终回答大纲: - 开头:简述问题。 - 方法1:使用proc或sysfs。 - 方法2:在内核代码中跟踪。 - 注意事项。 - 相关问题。</think>### 如何跟踪Linux内核中某个中断的使能状态 在Linux内核中,中断的使能状态表示某个中断线(IRQ line)是否被激活,允许其触发中断处理程序。跟踪这个状态对于调试中断相关的问题(如中断丢失或异常行为)非常重要。下面我将一步步解释跟踪方法,确保内容真实可靠,基于Linux内核机制(参考内核文档和常见实践)。注意,操作通常需要root权限或内核开发环境。 #### 步骤1: 确定中断号(IRQ number) 在跟踪前,必须先确认目标中断的IRQ number。这可以通过以下方式获取: - **查看/proc/interrupts文件**:这个文件列出了所有注册中断的统计信息。运行命令: ```bash cat /proc/interrupts ``` 输出会显示每个中断的编号、类型和触发次数。例如,找到类似`IRQ 9: eth0`的行,其中`9`是中断号。 - **使用设备信息**:如果知道设备名称(如网卡eth0),可以通过`lspci -v`或`dmesg | grep irq`查找关联的中断号。 #### 步骤2: 跟踪中断使能状态 Linux内核提供了多种方式来检查中断使能状态,分为用户空间工具和内核空间编程方法。以下是常用方法: 1. **使用sysfs接口(推荐用户空间方法)** Linux的sysfs文件系统(挂载在/sys)提供了中断状态的实时视图。每个中断在`/sys/kernel/irq/`目录下有对应的子目录。 - 进入目标中断的目录: ```bash cd /sys/kernel/irq/<irq_number> # 替换<irq_number>为实际中断号,如9 ``` - 查看`enabled`文件:这个文件直接显示使能状态(1表示使能,0表示禁止): ```bash cat enabled ``` 示例输出: ``` 1 # 表示中断已使能 ``` - **动态跟踪**:你可以使用`watch`命令持续监控状态变化: ```bash watch -n 1 cat /sys/kernel/irq/<irq_number>/enabled ``` 这每秒刷新一次状态,便于观察中断使能/禁止的实时变化。 这个方法简单高效,适用于大多数调试场景[^1]。 2. **在内核代码中编程跟踪(适用于开发者)** 如果需要在内核模块或驱动中跟踪状态,可以使用内核API访问中断描述符(`struct irq_desc`)。这个结构体包含状态字段(如`irq_desc->state_use_accessors`),其中`IRQD_IRQ_ENABLED`标志表示使能状态。 - 示例内核模块代码: ```c #include <linux/interrupt.h> #include <linux/module.h> static int __init track_irq_init(void) { struct irq_desc *desc; unsigned int irq = 9; // 替换为目标中断号 bool enabled; desc = irq_to_desc(irq); if (!desc) { printk(KERN_ERR "IRQ %d not found\n", irq); return -EINVAL; } enabled = irqd_is_enabled(&desc->irq_data); // 检查使能状态 printk(KERN_INFO "IRQ %d enabled: %d\n", irq, enabled); return 0; } static void __exit track_irq_exit(void) { // 清理代码 } module_init(track_irq_init); module_exit(track_irq_exit); MODULE_LICENSE("GPL"); ``` - 编译并加载模块后,使用`dmesg`查看输出。状态`1`表示使能,`0`表示禁止。 - **注意事项**:操作中断描述符需要谨慎,错误可能引发系统崩溃。确保在开发环境中测试[^2][^3]。 3. **使用调试工具(高级方法)** - **ftrace**:Linux的内置跟踪工具,可以监控中断事件。例如,启用中断使能/禁止的事件跟踪: ```bash echo 1 > /sys/kernel/debug/tracing/events/irq/enable echo 1 > /sys/kernel/debug/tracing/tracing_on cat /sys/kernel/debug/tracing/trace_pipe | grep "irq_enable\|irq_disable" ``` 这会输出所有中断状态变化的日志。 - **SystemTap或BPF工具**:编写脚本捕获`irq_enable`/`irq_disable`函数调用,适合生产环境动态跟踪。 #### 注意事项 - **权限要求**:访问`/sys`或`/proc`文件、加载内核模块通常需要root权限。避免在生产系统直接操作。 - **中断控制影响**:使能状态可能被内核函数(如`enable_irq()`/`disable_irq()`)动态修改,参考中断控制机制[^1]。跟踪时注意系统负载,以免干扰正常操作。 - **可靠性**:`/sys/kernel/irq/`接口在较新内核(4.x+)中稳定。旧内核可能需依赖`/proc/irq/<irq_number>/`目录,但功能类似。 - **为什么request_irq后状态为已使能**:如引用[3]所述,`request_irq()`函数会自动激活中断,无需手动使能[^3]。 如果以上方法无效,检查内核配置是否启用`CONFIG_GENERIC_IRQ_DEBUGFS`选项(确保sysfs支持)。 #### 相关问题 1. 如何禁止或启用Linux内核中的特定中断? 2. 中断处理程序如何避免并发问题? 3. Linux软中断和任务队列有什么作用?[^2] 4. 如何调试中断处理程序的性能问题? [^1]: linux内核提供了一组接口用于操作机器上的中断状态。这些接口为我们提供了能够禁止当前处理器的中断系统,或者是屏蔽掉整个机器的一条中断线的能力[^1]。 [^2]: Linux内核的中断处理是一复杂但充满智慧的技术艺术。它以灵活的架构、高效的分工和深思熟虑的优化,成功应对了现代操作系统的种种挑战[^2]。 [^3]: request_irq 函数用于申请中断, request_irq 函数可能会导致睡眠,因此不能在中断上下文或者其他禁止睡眠的代码段中使用 request_irq 函数。request_irq 函数会激活(使能)中断,所以不需要我们手动去使能中断[^3]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值