You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 11:57:27