jah 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.document +5 -0
- data/.gitignore +7 -0
- data/LICENSE +20 -0
- data/README.md +115 -0
- data/Rakefile +75 -0
- data/VERSION +1 -0
- data/bin/jah +9 -0
- data/jah.gemspec +89 -0
- data/lib/jah/agent.rb +128 -0
- data/lib/jah/agents/dump.rb +5 -0
- data/lib/jah/agents/post.rb +18 -0
- data/lib/jah/agents/xmpp.rb +194 -0
- data/lib/jah/cli.rb +124 -0
- data/lib/jah/collector.rb +12 -0
- data/lib/jah/collectors/cpu.rb +35 -0
- data/lib/jah/collectors/disk.rb +14 -0
- data/lib/jah/collectors/mem.rb +51 -0
- data/lib/jah/collectors/net.rb +27 -0
- data/lib/jah/collectors/prok.rb +88 -0
- data/lib/jah/collectors/services.rb +13 -0
- data/lib/jah/collectors/who.rb +20 -0
- data/lib/jah/command.rb +23 -0
- data/lib/jah/commands/admin.rb +40 -0
- data/lib/jah/commands/extra.rb +14 -0
- data/lib/jah/commands/pub.rb +34 -0
- data/lib/jah/commands/status.rb +61 -0
- data/lib/jah/god.rb +24 -0
- data/lib/jah/install.rb +336 -0
- data/lib/jah.rb +26 -0
- data/lib/jah.yaml.template +26 -0
- data/lib/locales/en_us.yml +2 -0
- data/lib/locales/pt_br.yml +2 -0
- data/lib/locales/pt_br_gostosa.yml +10 -0
- data/lib/locales/pt_br_mano.yml +10 -0
- data/lib/locales/pt_br_mineiro.yml +10 -0
- data/spec/console +12 -0
- data/spec/jah_spec.rb +7 -0
- data/spec/spec_helper.rb +9 -0
- metadata +123 -0
data/lib/jah/cli.rb
ADDED
@@ -0,0 +1,124 @@
|
|
1
|
+
#
|
2
|
+
# Jah Gem CLI
|
3
|
+
#
|
4
|
+
|
5
|
+
#TODO: def init
|
6
|
+
require 'logger'
|
7
|
+
|
8
|
+
module Jah
|
9
|
+
|
10
|
+
HOME = ENV['HOME'] + "/.jah/"
|
11
|
+
unless File.exists? HOME
|
12
|
+
FileUtils.mkdir_p HOME
|
13
|
+
end
|
14
|
+
|
15
|
+
Log = Logger.new(HOME + "jah.log")
|
16
|
+
def Log.write(d); self.warn(d); end
|
17
|
+
$stderr = Log
|
18
|
+
|
19
|
+
Opt = {}
|
20
|
+
|
21
|
+
def self.hostname
|
22
|
+
`hostname`.chomp.gsub(/\W/, "") rescue "jah#{rand(42000)}"
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.locale
|
26
|
+
`locale | grep LANG`.scan(/LANG=(.*)\./)[0][0].downcase rescue "en_us"
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.method_missing(w)
|
30
|
+
Opt[w.to_s.gsub("?", "").to_sym]
|
31
|
+
end
|
32
|
+
|
33
|
+
class Cli
|
34
|
+
|
35
|
+
def self.parse_options(argv)
|
36
|
+
options = {}
|
37
|
+
|
38
|
+
ARGV.options do |opts|
|
39
|
+
opts.banner = <<BANNER
|
40
|
+
Jah Gem Usage:
|
41
|
+
|
42
|
+
jah [command] [opts] -c [config file]
|
43
|
+
|
44
|
+
Commands:
|
45
|
+
|
46
|
+
start
|
47
|
+
stop
|
48
|
+
restart
|
49
|
+
install
|
50
|
+
|
51
|
+
BANNER
|
52
|
+
opts.separator "Config file:"
|
53
|
+
opts.on("-c", "--config CONFIG", String, "Jah Config file path" ) { |file| options[:config] = file }
|
54
|
+
opts.separator ""
|
55
|
+
opts.separator "Operation mode:"
|
56
|
+
opts.on("-m", "--mode MODE", String, "Jah operation mode") { |val| options[:mode] = val.to_sym }
|
57
|
+
opts.separator ""
|
58
|
+
opts.separator " xmpp - Use xmpp client, requires JID and Password"
|
59
|
+
opts.separator " post - Use post client, requires Jah Web Key"
|
60
|
+
opts.separator " dump - Just dump to disk, Jah Web can login and read"
|
61
|
+
opts.separator ""
|
62
|
+
opts.separator "Server Options:"
|
63
|
+
opts.on("-j", "--jid JID", String, "Client JID (user@domain)") { |val| options[:jid] = val }
|
64
|
+
opts.on("-k", "--key KEY", String, "Client XMPP Password or Jah Web Key") { |val| options[:key] = val }
|
65
|
+
opts.on("-s", "--server SERVER", String, "Jah Server URL" ) { |url| options[:server] = url }
|
66
|
+
opts.on("-p", "--port PORT", Integer, "Jah Server Port") { |val| options[:port] = val.to_i }
|
67
|
+
opts.separator ""
|
68
|
+
|
69
|
+
opts.on("-t", "--talk TALK", String, "Which locale to use" ) { |i18n| options[:i18n] = i18n }
|
70
|
+
opts.on("-f", "--file FILE", String, "Local temp file to track history" ) { |file| options[:history] = file }
|
71
|
+
opts.on("-i", "--interval INTERVAL", Integer, "Poller interval") { |val| options[:interval] = val.to_i }
|
72
|
+
opts.on("-l", "--level LEVEL", Logger::SEV_LABEL.map { |l| l.downcase }, "The level of logging to report" ) { |level| options[:level] = level }
|
73
|
+
opts.on("-g", "--[no-]god", "Don't use god") { |val| options[:god] = false }
|
74
|
+
opts.on("-d", "--daemonize", "Run in background" ) { |d| options[:daemon] = d }
|
75
|
+
opts.on("-r", "--report REPORT", "Report status to others on roster" ) { |r| options[:report] = r }
|
76
|
+
|
77
|
+
opts.separator ""
|
78
|
+
opts.separator "Common Options:"
|
79
|
+
opts.on("-h", "--help", "Show this message" ) { puts opts; exit }
|
80
|
+
opts.on("-v", "--[no-]verbose", "Turn on logging to STDOUT" ) { |bool| options[:verbose] = bool }
|
81
|
+
opts.on("-V", "--version", "Show version") { |version| puts Jah::VERSION; exit }
|
82
|
+
opts.separator ""
|
83
|
+
begin
|
84
|
+
opts.parse!
|
85
|
+
@usage = opts.to_s
|
86
|
+
rescue
|
87
|
+
puts opts
|
88
|
+
exit
|
89
|
+
end
|
90
|
+
end
|
91
|
+
options
|
92
|
+
end
|
93
|
+
private_class_method :parse_options
|
94
|
+
|
95
|
+
def self.dispatch(argv)
|
96
|
+
Jah::Opt.merge! autoload_config(parse_options(argv))
|
97
|
+
if comm = argv.shift
|
98
|
+
Jah::Agent.send(comm) rescue puts "Command not found: #{comm}"
|
99
|
+
else
|
100
|
+
Jah.mode ? Jah::Agent.start : Install.new
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# Load config [., ~/.jah, /etc]
|
105
|
+
def self.autoload_config(options)
|
106
|
+
conf = "jah.yaml"
|
107
|
+
file = options[:config] || [nil, HOME, "/etc/"].select { |c| File.exists? "#{c}#{conf}" }[0]
|
108
|
+
options = YAML.load(File.read(file + conf)).merge!(options) if file
|
109
|
+
|
110
|
+
# Map acl and group arrays
|
111
|
+
[:acl, :groups].each do |g|
|
112
|
+
options[g] = options[g].split(",").map(&:strip)
|
113
|
+
end
|
114
|
+
options[:groups].map! { |g| "#{g}@conference.#{options[:host]}" }
|
115
|
+
|
116
|
+
# find a better place for this
|
117
|
+
I18n.load_path += Dir[File.join(File.dirname(__FILE__), '..', 'locales', "*.{rb,yml}")]
|
118
|
+
I18n.default_locale = options[:i18n] || "en_us"
|
119
|
+
options
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Jah
|
2
|
+
class Cpu < Collector
|
3
|
+
attr_reader :load, :one, :five, :ten, :med
|
4
|
+
EXEC = "uptime"
|
5
|
+
|
6
|
+
def self.get
|
7
|
+
new
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
l = cpu_load
|
12
|
+
@one = l[:one]
|
13
|
+
@five = l[:five]
|
14
|
+
@ten = l[:ten]
|
15
|
+
@load = l.values.join(", ")
|
16
|
+
@med = @ten / cores
|
17
|
+
end
|
18
|
+
|
19
|
+
def cpu_load
|
20
|
+
if `#{EXEC}` =~ /load average(s*): ([\d.]+)(,*) ([\d.]+)(,*) ([\d.]+)\Z/
|
21
|
+
{ :one => $2.to_f,
|
22
|
+
:five => $4.to_f,
|
23
|
+
:ten => $6.to_f }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def cores
|
28
|
+
case RUBY_PLATFORM
|
29
|
+
when /linux/ then `cat /proc/cpuinfo | grep 'model name' | wc -l`.to_i
|
30
|
+
when /darwin/ then `hwprefs cpu_count`.to_i
|
31
|
+
else 1
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Jah
|
2
|
+
|
3
|
+
class Disk < Collector
|
4
|
+
EXEC = "df -h"
|
5
|
+
|
6
|
+
def self.all
|
7
|
+
@disks = `#{EXEC}`.to_a.reject { |dl| dl =~ /Size|none/ }.map do |l|
|
8
|
+
l = l.split(" ")
|
9
|
+
{ :path => l[0], :total => l[1], :used => l[2], :avail => l[3], :percent => l[4]}
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Jah
|
2
|
+
|
3
|
+
class Mem < Collector
|
4
|
+
attr_reader :total, :free, :used, :percent, :cached, :buffered,
|
5
|
+
:swap_total, :swap_free, :swap_used, :swap_percent
|
6
|
+
|
7
|
+
EXEC = "cat /proc/meminfo"
|
8
|
+
|
9
|
+
def self.get
|
10
|
+
new
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
do_something
|
15
|
+
end
|
16
|
+
|
17
|
+
def do_something
|
18
|
+
mem_info = {}
|
19
|
+
`#{EXEC}`.each do |line|
|
20
|
+
_, key, value = *line.match(/^(\w+):\s+(\d+)\s/)
|
21
|
+
mem_info[key] = value.to_i
|
22
|
+
end
|
23
|
+
|
24
|
+
# memory info is empty - operating system may not support it (why doesn't an exception get raised earlier on mac osx?)
|
25
|
+
raise "No such file or directory" if mem_info.empty?
|
26
|
+
|
27
|
+
@total = mem_info['MemTotal'] / 1024
|
28
|
+
@free = (mem_info['MemFree'] + mem_info['Buffers'] + mem_info['Cached']) / 1024
|
29
|
+
@used = @total - @free
|
30
|
+
@percent = (@used / @total.to_f * 100).to_i
|
31
|
+
|
32
|
+
@swap_total = mem_info['SwapTotal'] / 1024
|
33
|
+
@swap_free = mem_info['SwapFree'] / 1024
|
34
|
+
@swap_used = swap_total - swap_free
|
35
|
+
unless @swap_total == 0
|
36
|
+
@swap_percent = (@swap_used / @swap_total.to_f * 100).to_i
|
37
|
+
end
|
38
|
+
rescue Exception => e
|
39
|
+
if e.message =~ /No such file or directory/
|
40
|
+
puts "/proc/meminfo not found.. trying top!"
|
41
|
+
top = `top -l 1`.to_a[5].split.map!{|m| m[0..-2].to_i}.reject(&:zero?)
|
42
|
+
@used, @free = top[3,4]
|
43
|
+
@total = @used + @free
|
44
|
+
@percent = (@used / @total.to_f * 100).to_i
|
45
|
+
else
|
46
|
+
raise e
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Jah
|
2
|
+
class Net < Collector
|
3
|
+
# :net => "netstat -n | grep -i established | wc -l"
|
4
|
+
class << self
|
5
|
+
# attr_reader :count, :ips
|
6
|
+
|
7
|
+
|
8
|
+
def count
|
9
|
+
`netstat -n | grep -i established | wc -l`.to_i
|
10
|
+
end
|
11
|
+
|
12
|
+
def connections
|
13
|
+
`netstat -ntu | grep ESTAB | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -nr`.to_a.map do |l|
|
14
|
+
count, ip = l.split
|
15
|
+
[ip, count]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
|
22
|
+
|
23
|
+
|
24
|
+
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
module Jah
|
2
|
+
|
3
|
+
class Ps < Collector
|
4
|
+
COMM = "ps auxww"
|
5
|
+
|
6
|
+
def self.all
|
7
|
+
`#{COMM}`.to_a[1..-1].map do |l|
|
8
|
+
Prok.new(l.split)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.find(name)
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
class Prok
|
20
|
+
BANLIST = [/^ata/, /^init$/, /^scsi_/, /\/\d$/, /agetty/ ]
|
21
|
+
attr_reader :pid, :comm, :cpu, :mem, :rss, :vsz, :stat
|
22
|
+
|
23
|
+
def initialize(args) # USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
|
24
|
+
return unless args[0]
|
25
|
+
@user = args[0]
|
26
|
+
@pid = args[1].chomp.to_i
|
27
|
+
@cpu = args[2].chomp.to_f
|
28
|
+
@mem = args[3].chomp.to_f
|
29
|
+
@vsz = args[4].chomp.to_i
|
30
|
+
@rss = args[5].chomp.to_i
|
31
|
+
@tty = args[6]
|
32
|
+
@stat = args[7]
|
33
|
+
@start = args[8]
|
34
|
+
@time = args[9]
|
35
|
+
@comm = args[10]
|
36
|
+
#@shr = args[6]
|
37
|
+
end
|
38
|
+
|
39
|
+
def hup!
|
40
|
+
exec "kill -1 #{pid}"
|
41
|
+
end
|
42
|
+
|
43
|
+
def kill!
|
44
|
+
exec "kill #{pid}"
|
45
|
+
end
|
46
|
+
|
47
|
+
def move_to_acre!
|
48
|
+
exec "kill -9 #{pid}"
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.genocide!(ary, f = nil)
|
52
|
+
for prok in ary
|
53
|
+
prok.kill
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def exec(comm)
|
58
|
+
# SSHWorker.new(@host, @host.user, comm)
|
59
|
+
end
|
60
|
+
|
61
|
+
def force(f)
|
62
|
+
{ :hup => "-1", :die => "-9"}[f]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
# COMM = {
|
69
|
+
# :top => "top -n 1",
|
70
|
+
# }
|
71
|
+
|
72
|
+
|
73
|
+
|
74
|
+
# def top
|
75
|
+
# info, tasks, cpus, mem, swap, n, n, *rest = *@res[:top]
|
76
|
+
# n, total, used, free, buffered = *mem.match(/(\d*)k\D*(\d*)k\D*(\d*)k\D*(\d*)k.*/)
|
77
|
+
# cached = swap.match(/(\d*)k cached/)[0]
|
78
|
+
# proks = rest.map do |r|
|
79
|
+
# r.split(" ")
|
80
|
+
# end
|
81
|
+
|
82
|
+
# # fail... top don't show a good stat....
|
83
|
+
# @proks = proks.reject do |p|
|
84
|
+
# p[0] == nil || Prok::BANLIST.select{ |pl| pl =~ p[11] }[0]
|
85
|
+
# end
|
86
|
+
# rescue => e
|
87
|
+
# nil
|
88
|
+
# end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Jah
|
2
|
+
|
3
|
+
class Who < Collector
|
4
|
+
EXEC = "who"
|
5
|
+
|
6
|
+
def self.all
|
7
|
+
@who = `#{EXEC}`.to_a.map do |l|
|
8
|
+
l = l.split(" ")
|
9
|
+
|
10
|
+
hash = {}
|
11
|
+
|
12
|
+
hash[:who] = l[0]
|
13
|
+
hash[:terminal] = l[1]
|
14
|
+
2.times{ l.delete(l[0]) }
|
15
|
+
hash[:date] = l.join(" ")
|
16
|
+
hash
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/jah/command.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
module Jah
|
2
|
+
REG = []
|
3
|
+
|
4
|
+
module Command
|
5
|
+
|
6
|
+
def self.included(base)
|
7
|
+
base.extend ClassMethods
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.find(msg)
|
11
|
+
REG.select { |r| r[1] =~ msg.squeeze(" ").strip }.first
|
12
|
+
end
|
13
|
+
|
14
|
+
module ClassMethods
|
15
|
+
|
16
|
+
def register(handler, regex)
|
17
|
+
REG << [handler, /^#{regex}/, self]
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Jah
|
2
|
+
|
3
|
+
class Admin
|
4
|
+
include Command
|
5
|
+
|
6
|
+
register(:get_roster, "roster$")
|
7
|
+
register(:drop_user, "drop\s")
|
8
|
+
#Jah::Command.register(:create_group, "")
|
9
|
+
|
10
|
+
class << self
|
11
|
+
|
12
|
+
|
13
|
+
def get_roster
|
14
|
+
out = ""
|
15
|
+
client.roster.grouped.each do |group, items|
|
16
|
+
out << "#{'*'*3} #{group || 'Ungrouped'} #{'*'*3}\n"
|
17
|
+
items.each { |item| out << "- #{item.name} (#{item.jid})\n" }
|
18
|
+
out << "\n"
|
19
|
+
end
|
20
|
+
out
|
21
|
+
end
|
22
|
+
|
23
|
+
def drop_user(user)
|
24
|
+
puts "DROP..."
|
25
|
+
end
|
26
|
+
|
27
|
+
def join_group()
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
|
32
|
+
|
33
|
+
def create_group(name)
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require "blather/client/dsl"
|
2
|
+
|
3
|
+
module Jah
|
4
|
+
|
5
|
+
class Pub
|
6
|
+
include Command
|
7
|
+
|
8
|
+
register :create, 'create\spubsub.*'
|
9
|
+
|
10
|
+
|
11
|
+
def self.create(_, node)
|
12
|
+
# pubsub = Blather::DSL::PubSub.new()
|
13
|
+
request(Blather::Stanza::PubSub::Create.new(:set,
|
14
|
+
"Jah.host.com", node)) { |n| yield n if block_given? }
|
15
|
+
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.all
|
20
|
+
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
|
26
|
+
|
27
|
+
|
28
|
+
|
29
|
+
|
30
|
+
|
31
|
+
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module Jah
|
2
|
+
|
3
|
+
class Status
|
4
|
+
include Command
|
5
|
+
register(:ok, 'ok\??$')
|
6
|
+
register(:who, 'who\??$')
|
7
|
+
register(:mem, 'mem\??$')
|
8
|
+
register(:cpu, 'cpu\??$')
|
9
|
+
register(:net, 'net\??$')
|
10
|
+
register(:disk, 'disk\??$')
|
11
|
+
register(:proks, 'prok$|top$')
|
12
|
+
|
13
|
+
|
14
|
+
class << self
|
15
|
+
|
16
|
+
def ok
|
17
|
+
I18n.t("states." + case Jah::Cpu.get.med
|
18
|
+
when 0..0.5 then :green
|
19
|
+
when 0.51..0.7 then :yellow
|
20
|
+
else :red
|
21
|
+
end.to_s)
|
22
|
+
end
|
23
|
+
|
24
|
+
def mem
|
25
|
+
Mem.get.percent.to_s + "%"
|
26
|
+
end
|
27
|
+
|
28
|
+
def cpu
|
29
|
+
Cpu.get.load
|
30
|
+
end
|
31
|
+
|
32
|
+
def net
|
33
|
+
out = ""
|
34
|
+
Net.connections.each do |c|
|
35
|
+
out << "#{c[0]} => #{c[1]} connections\n"
|
36
|
+
end
|
37
|
+
out << "Total: #{Net.count}"
|
38
|
+
end
|
39
|
+
|
40
|
+
def disk
|
41
|
+
Disk.all.map do |d|
|
42
|
+
"\n*#{d[:path]}* => #{d[:percent]}"
|
43
|
+
end.join("\n")
|
44
|
+
end
|
45
|
+
|
46
|
+
def who
|
47
|
+
Who.all.map do |w|
|
48
|
+
"#{w[:who]} Logado via #{w[:terminal]} desde a data: #{w[:date]}"
|
49
|
+
end.join("\n")
|
50
|
+
end
|
51
|
+
|
52
|
+
def proks(find = nil)
|
53
|
+
Ps.all.map do |p|
|
54
|
+
next if find && p.comm !~ /#{find}/i
|
55
|
+
"#{p.comm} => #{p.mem}\n"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
data/lib/jah/god.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# def setup
|
2
|
+
# DRb.start_service
|
3
|
+
# @server = DRbObject.new(nil, God::Socket.socket(@config['god_port'])) || nil
|
4
|
+
# rescue => e
|
5
|
+
# @config[:god] = false
|
6
|
+
# end
|
7
|
+
|
8
|
+
# # ping server to ensure that it is responsive
|
9
|
+
# def ping
|
10
|
+
# if god?
|
11
|
+
# tries = 3
|
12
|
+
# begin
|
13
|
+
# @server.ping
|
14
|
+
# rescue Exception => e
|
15
|
+
# retry if (tries -= 1) > 1
|
16
|
+
# raise e, "The server is not available (or you do not have permissions to access it)"
|
17
|
+
# end
|
18
|
+
# end
|
19
|
+
# end
|
20
|
+
|
21
|
+
|
22
|
+
# def god?
|
23
|
+
# @config[:god]
|
24
|
+
# end
|