In my setup, the info
command shows me the following:
[keys] => 1128
[expires] => 1125
I'd like to find those 3 keys without an expiration date. I've already checked the docs to no avail. Any ideas?
In my setup, the info
command shows me the following:
[keys] => 1128
[expires] => 1125
I'd like to find those 3 keys without an expiration date. I've already checked the docs to no avail. Any ideas?
Modified from a site that I can't find now.
redis-cli keys "*" | while read LINE ; do TTL=`redis-cli ttl "$LINE"`; if [ $TTL -eq -1 ]; then echo "$LINE"; fi; done;
edit: Note, this is a blocking call.
@Waynn Lue's answer runs but uses the Redis KEYS command which Redis warns about:
Warning: consider KEYS as a command that should only be used in production environments with extreme care. It may ruin performance when it is executed against large databases.
Redis documentation recommends using SCAN.
redis-cli --scan | while read LINE ; do TTL=`redis-cli ttl "$LINE"`; if [ $TTL -eq -1 ]; then echo "$LINE"; fi; done;
If you want to scan for a specific key pattern, use:
redis-cli --scan --pattern "something*"
In case somebody is getting bad arguments or wrong number of arguments error, put double quotes around $LINE.
So,it would be
redis-cli keys "*" | while read LINE ; do TTL=`redis-cli ttl "$LINE"`; if [ $TTL -eq -1 ]; then echo "$LINE"; fi; done;
This happens when there are spaces in the key.
To me the accepted answer appears unusable for a medium-sized dataset, as it will run a redis-cli
command for each and every key.
Instead I used this lua script to filter the keys inside the redis server:
local show_persistent = ARGV[1] ~= "expiring"
local keys = {}
for i, name in ipairs(redis.call("keys", "*")) do
local persistent = redis.call("pttl", name) < 0
if persistent == show_persistent then
table.insert(keys, name)
end
end
return keys
This can be called as
$ redis-cli --eval show-persistent-keys.lua
to get all keys without an expiration time. It also can be called as
$ redis-cli --eval show-persistent-keys.lua , expiring
to find the opposite key set of all keys with an expiration time set.
On the downside this may block for too long (appears fine for 1 M keys). I'd use scan instead but I happen to have to run this against a legacy Redis at version 2.6, which does not have scan
available.
I needed to extract non-expiring keys from bigger (40GB) dataset, so using keys
command was not suitable for me. So in case someone is looking for offline/non-blocking solution, you can use https://github.com/sripathikrishnan/redis-rdb-tools for extraction of non-expiring keys from redis rdb dump.
You can just install libraries via pip:
pip install rdbtools python-lzf
Then create simple parser which extracts keys and values which has expiration set to None:
from rdbtools import RdbParser, RdbCallback
from rdbtools.encodehelpers import bytes_to_unicode
class ParserCallback(RdbCallback):
def __init__(self):
super(ParserCallback, self).__init__(string_escape=None)
def encode_key(self, key):
return bytes_to_unicode(key, self._escape, skip_printable=True)
def encode_value(self, val):
return bytes_to_unicode(val, self._escape)
def set(self, key, value, expiry, info):
if expiry is None:
print('%s = %s' % (self.encode_key(key), self.encode_value(value)))
callback = ParserCallback()
parser = RdbParser(callback)
parser.parse('/path/to/dump.rdb')
#!/usr/bin/env python
import argparse
import redis
p = argparse.ArgumentParser()
p.add_argument("-i", '--host', type=str, default="127.0.0.1", help="redis host", required=False)
p.add_argument("-p", '--port', type=int, default=6379, help="redis port", required=False)
p.add_argument("-n", '--db', type=int, default=0, help="redis database", required=False)
args = p.parse_args()
r = redis.Redis(host=args.host, port=args.port, db=args.db)
try:
keys = r.keys()
for key in keys:
if r.ttl(key) < 0:
print(key)
except KeyboardInterrupt:
pass