Ruby网络检测脚本出现Rake风格错误,请求协助修复
修复Ruby交换机状态检测脚本的Rake风格错误
嘿,我帮你排查下这个脚本的问题,你遇到的几个错误都是Ruby语法和逻辑上的小问题,咱们一个个来解决:
首先先回顾下你的原始代码和报错:
原始代码
#!/usr/bin/env ruby require 'net/ping' require 'net/smtp' # check if host is up def up?(host) check = Net::Ping::External.new(host) check.ping? end # list of switches to check switch_list = [ ['A ', '192.168.1.1'], ['B ', '192.168.1.2'], ['C ', '192.168.1.3'] ] failed_switches =[] switch_list.each do |switch, ip| puts "#{switch}" + up?(ip).to_s failed_switches << [switch, ip] unless up?(ip) end failed_switches.each do |ip| unless failed_switches.empty? puts "#{failed_switches}" + up?(ip).to_s + "\n" end #email the list of checked and failed swithces message = <<MESSAGE_END From: abc@gmail.com To: xyz@gmail.com Subject: device down! checked devices: #{switch_list.map { |switches, ips| 'Device:' + switch + 'IP:' + ip }.join("\n") } failed devices: #{failed_switches.map { |switches, ips| 'Device:' + switch + 'IP:' + ip }.join("\n") } MESSAGE_END puts "#{message}" next unless failed_switches.empty? Net::SMTP.start('your mail server') do |smtp| smtp.send_message message, 'xyz@gmail.com' end end
报错信息
Inconsistent indentation detected: message = <<MESSAGE_END
Unused block argument - line 36 line 39 |switches, ips|
Inconsistent indentation detected: line 44 next unless failed_switches.empty?
Inconsistent indentation detected: line 45 Net::SMTP.start('your mail server') do |smtp|
具体修复步骤
1. 统一缩进,解决缩进不一致问题
Ruby对缩进要求严格, heredoc(<<MESSAGE_END)的内容和后续代码块必须使用相同的缩进方式(比如全用2个或4个空格,不要混用空格和制表符)。我这里统一用4个空格缩进,还改用了<<~MESSAGE_END(波浪线 heredoc),它能自动去除内容前的缩进,让代码更整洁。
2. 修复未使用的块参数问题
在map方法里,你定义了|switches, ips|但没用到,反而用了外部的switch和ip变量——这会导致所有设备都显示最后一个交换机的信息,完全不对。要把块里的变量改成对应遍历的元素,比如用name和ip_addr来区分循环内的当前元素,避免变量混淆。
3. 修正邮件发送逻辑
- 你原本把邮件发送放在
failed_switches.each循环里,这会给每个故障设备发一封邮件,应该把邮件逻辑移到循环外面,只在有故障设备时发送一次。 next unless failed_switches.empty?逻辑搞反了,应该是当故障列表为空时跳过发送,也就是next if failed_switches.empty?,或者直接用unless failed_switches.empty?包裹邮件逻辑更直观。- SMTP的参数需要修正:
Net::SMTP.start需要服务器地址、端口(比如Gmail是smtp.gmail.com, 587),还要加上认证信息(如果需要的话),另外send_message的参数顺序是消息内容, 发件人, 收件人,你之前的顺序错了。
修复后的完整代码
#!/usr/bin/env ruby require 'net/ping' require 'net/smtp' # Check if host is reachable def up?(host) check = Net::Ping::External.new(host) check.ping? end # List of switches to monitor switch_list = [ ['Switch A', '192.168.1.1'], ['Switch B', '192.168.1.2'], ['Switch C', '192.168.1.3'] ] failed_switches = [] # Check each switch and log status switch_list.each do |name, ip| status = up?(ip) puts "#{name} - #{ip}: #{status ? 'UP' : 'DOWN'}" failed_switches << [name, ip] unless status end # Prepare and send email only if there are failed switches unless failed_switches.empty? # Format email content with clean indentation message = <<~MESSAGE_END From: abc@gmail.com To: xyz@gmail.com Subject: [ALERT] Network Switches Down! Checked Devices: #{switch_list.map { |name, ip| " - #{name} (#{ip}): #{up?(ip) ? 'UP' : 'DOWN'}" }.join("\n")} Failed Devices: #{failed_switches.map { |name, ip| " - #{name} (#{ip})" }.join("\n")} MESSAGE_END puts "\nSending alert email:\n#{message}" # Configure SMTP settings (adjust for your mail server) begin # Example for Gmail: use app-specific password instead of regular password Net::SMTP.start('smtp.gmail.com', 587, 'localhost', 'abc@gmail.com', 'your_app_password', :plain) do |smtp| smtp.send_message message, 'abc@gmail.com', 'xyz@gmail.com' end puts "Email sent successfully!" rescue => e puts "Failed to send email: #{e.message}" end else puts "\nAll switches are up, no alert needed." end
额外说明
- 我把变量名改成了更清晰的
name和ip,避免循环内外的变量混淆 - 添加了异常处理,避免发送邮件时脚本崩溃
- 如果用Gmail的话,需要开启“应用专用密码”,不能用普通账号密码
内容的提问来源于stack exchange,提问作者RashItIs
相关产品推荐
相关产品推荐

