在日常的服务器硬件ref="/tag/193/" style="color:#B2A89E;font-weight:bold;">维护中,经常需要编写一些自动化脚本来监控温度、磁盘状态或电源情况。这些脚本运行时难免遇到意外,比如读取传感器失败、设备文件不存在,或者权限不足。这时候,Ruby 的异常处理机制就派上了用场。
用 begin-rescue 捕获硬件访问错误
假设你写了一个脚本去读取 /sys/class/thermal/thermal_zone0/temp 获取 CPU 温度,但某些服务器可能没有这个路径。直接读取会抛出 Errno::ENOENT 异常。通过 begin 和 rescue 配合,可以让程序更稳健:
begin
temp_data = File.read("/sys/class/thermal/thermal_zone0/temp")
temperature = temp_data.to_i / 1000
puts "当前CPU温度:#{temperature}°C"
rescue Errno::ENOENT
puts "无法读取温度传感器,可能是路径不支持或硬件不同"
rescue StandardError => e
puts "其他错误发生:#{e.message}"
end
这样即使某台机器结构不同,脚本也不会直接崩溃,而是给出提示继续执行后续检测任务。
确保资源释放:使用 ensure
在操作硬件接口时,有时需要打开文件描述符或建立通信连接。不管过程是否出错,都应该关闭资源。ensure 块正好用于这种场景:
file = nil
begin
file = File.open("/dev/gpiochip0", "w")
file.write("1") # 触发某个硬件信号
rescue StandardError => e
puts "GPIO 写入失败:#{e.message}"
ensure
file.close if file && !file.closed?
puts "GPIO 资源已释放"
end
哪怕写入失败,ensure 仍会执行关闭操作,避免句柄泄漏影响系统稳定性。
自定义异常类型应对特定故障
当维护多型号服务器时,可以定义自己的异常类来区分不同硬件平台的问题:
class HardwareNotSupported < StandardError; end
def check_disk_health(device)
raise HardwareNotSupported, "SSD #{device} 不支持 SMART 自检" unless device.start_with?("sda")
# 执行 smartctl 命令
end
begin
check_disk_health("sdb")
rescue HardwareNotSupported => e
puts "跳过检测:#{e.message}"
end
这样的设计让日志更清晰,也方便后续做分类统计和告警过滤。
Ruby 的异常机制不是为了掩盖问题,而是让维护脚本在复杂环境中更可靠地运行。面对千变万化的硬件配置,一个能“容错”的脚本比一个总崩溃的完美脚本实用得多。