Skip to content

Instantly share code, notes, and snippets.

@bkimble
Last active August 22, 2024 14:21
Show Gist options
  • Save bkimble/1365005 to your computer and use it in GitHub Desktop.
Save bkimble/1365005 to your computer and use it in GitHub Desktop.
List local memcached keys using Ruby
#!/usr/bin/env ruby
# List all keys stored in memcache.
# Credit to Graham King at http://www.darkcoding.net/software/memcached-list-all-keys/ for the original article on how to get the data from memcache in the first place.
require 'net/telnet'
headings = %w(id expires bytes cache_key)
rows = []
localhost = Net::Telnet::new("Host" => "localhost", "Port" => 11211, "Timeout" => 3)
matches = localhost.cmd("String" => "stats items", "Match" => /^END/).scan(/STAT items:(\d+):number (\d+)/)
slabs = matches.inject([]) { |items, item| items << Hash[*['id','items'].zip(item).flatten]; items }
longest_key_len = 0
slabs.each do |slab|
localhost.cmd("String" => "stats cachedump #{slab['id']} #{slab['items']}", "Match" => /^END/) do |c|
matches = c.scan(/^ITEM (.+?) \[(\d+) b; (\d+) s\]$/).each do |key_data|
cache_key, bytes, expires_time = key_data
rows << [slab['id'], Time.at(expires_time.to_i), bytes, cache_key]
longest_key_len = [longest_key_len,cache_key.length].max
end
end
end
row_format = %Q(|%8s | %28s | %12s | %-#{longest_key_len}s |)
puts row_format%headings
rows.each{|row| puts row_format%row}
localhost.close
@gfa
Copy link

gfa commented May 27, 2014

does it list all the keys or most of them?

@saxxi
Copy link

saxxi commented Jan 5, 2015

As I didn't know about this snippet I created a similar one based on the same source. Please have a look if you find it useful.

require 'net/telnet'
memcached = Net::Telnet::new("Host" => "localhost", "Port" => 11211)
memcached.puts 'stats items'
slab_ids = memcached.waitfor(/./).split("\n").map { |line| x = line[/([^\:]+)\d+/, 0].to_i ; x > 0 ? x : nil }.uniq.compact
slab_ids.inject([]) do |items, slab_id|
  memcached.puts "stats cachedump #{slab_id} 100"
  items << memcached.waitfor(/./).split("\n")[0].split(' ', 3)[1]
  items
end

@saxxi
Copy link

saxxi commented Jan 5, 2015

@gfa from the first couple of lines of the source in http://www.darkcoding.net/software/memcached-list-all-keys/:
"In the general case, there is no way to list all the keys that a memcached instance is storing. You can, however, list something like the first 1Meg of keys, which is usually enough during development."

@ginjo
Copy link

ginjo commented Jan 30, 2015

@bkimble thanks for this!

Here's yet another fork of your original gist:
https://gist.github.com/ginjo/aaa4a4395fcdbbad3d29

This revision adds a couple of features for working with cache item rows as ruby objects.

  • Isolates the cache item query and enumeration into a method that yields to an optional block (passing all elements of cache item. You can do anything with the block - print rows, return rows as an array of hashes, return a single 'matching' row, etc..
  • Accepts a list of servers and runs the above enumerator for all items found on every server.

I've included a method that mimics your original formatted printing, plus a method that returns all found cache items as an array of hashes.

@VARGA-Peter
Copy link

Unfortunately it does not work when the server has several 100 thousand keys...

@rafanasiev
Copy link

excellent, thanks a lot!

@rbalman
Copy link

rbalman commented Aug 18, 2017

Nice 😮 . I have customized this script for dump and restore using dalli gem.
https://gist.github.com/javanux/dbd005ef50ae4b8cea213af058abf771

@jsqu99
Copy link

jsqu99 commented Sep 5, 2017

I'm fairly certain this does not work on memcachier.

I successfully telneted in to our production servers and tried issues the stats cachedump command and got:

CLIENT_ERROR unsupported stats command

@vkdimitrov
Copy link

bingo! 👍

@ralphjay24
Copy link

ralphjay24 commented Apr 13, 2018

Thank you! This help me to solve problem of infinite caching(no expiration).

@archan937
Copy link

archan937 commented Oct 16, 2019

Hello, @bkimble. I have adjusted your Gist a bit, see: https://gist.github.com/archan937/f441146e1aeaa9da138e337514ee4000

The logic is in a method called keys and you can pass your memcached host (or a list of hosts) and an optional pattern to filter on keys.
Also, prints the slab IDs with all of its keys.

@ankhaa-g
Copy link

Unfortunately it does not work when the server has several 100 thousand keys...

Same here. Does not work with 60k keys.

@HeroProtagonist
Copy link

The require statement at the top needs to be updated because telnet was removed from the standard library at some point and made a separate gem. Otherwise script works as expected. Thanks @bkimble 👍

- require 'net/telnet'
+ gem 'net-telnet'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment