-
Notifications
You must be signed in to change notification settings - Fork 24
/
memcached_client.rb
123 lines (98 loc) · 2.3 KB
/
memcached_client.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#!/usr/bin/env ruby
# gem install dalli -> https://github.com/mperham/dalli
require 'dalli'
require 'net/telnet'
@server = 'remote_server_ip'
@port = '11211'
@serverport = "#{@server}:#{@port}"
begin
@dc = Dalli::Client.new(@serverport, compress: true, socket_timeout: 5)
rescue Dalli::NetworkError
puts "[!] Couldn't connect to remote host #{serverport}"
exit
end
#
# Extract the slabs from the items stats.
# Returns a unique array of slabs.
#
def slabs
slabs = []
@dc.stats(:items)[@serverport].each_pair do |key, value|
slabs << key.match(/^items:(\d*):/)[1]
end
slabs = slabs.uniq - [""]
puts
puts "[*] Identified #{slabs.size} slabs..."
slabs
end
#
# Extract the keys using stats cachedump:
# http://www.darkcoding.net/software/memcached-list-all-keys/
# https://gist.github.com/bkimble/1365005
# Returns an array of keys.
#
def keys(slabs)
keys = []
telnet = Net::Telnet::new('Host' => @server,
'Port' => @port,
'Timeout' => 15,
'Telnetmode' => false,
'Waittime' => 5)
slabs.each do |slab|
sleep 0.5 # don't want to flood the server
begin
telnet.cmd('String' => "stats cachedump #{slab} 100", 'Match' => /^END/) { |output| keys << output.scan(/^ITEM\s([\w-]*)\s/) }
rescue => e
puts "[!] Something is wrong when getting slabs #{e}"
next
end
end
telnet.close
keys = keys.flatten.uniq
puts "[*] Identified #{keys.size} keys..."
keys
end
#
# Use the key name to grab the key value
#
def values(found_slabs)
keys(found_slabs).each do |key|
begin
puts "[*] Getting value for #{key} key..."
value = @dc.get(key)
puts value if value
rescue => e
# puts "[!] Something went wrong #{e}"
next
end
end
end
#
# Dumps the memcached stats
#
def stats
@dc.stats[@serverport].each_pair do |key, value|
puts "[*] #{key}: #{value}"
end
end
#
# Main
#
if @dc.alive!
puts "[+] Connected to #{@serverport}"
puts
puts '[+] Remote memcached stats:'
puts
stats
found_slabs = slabs
unless found_slabs.empty?
puts
puts '[+] Remote memcached key values:'
puts
values(found_slabs)
else
puts
puts '[!] No slabs found.'
end
@dc.close
end