1#!/bin/sh
2
3# this script pulls a list of keys from a redis database and stores the
4# values into a save file in redis-cli command format.  the save file can
5# then be restored simply by running it.
6
7# path to save file
8PERSIST_FILE="${2:-/usr/lib/sbsaved/sb.persist.redis}"
9
10# space-delimited list of keys to be saved into PERSIST_FILE
11PERSIST_KEYS="settings:*"
12
13# $1: key
14persist_string() {
15	local key=$1
16	echo "redis-cli SET ${key} $(redis-cli GET ${key})"
17}
18
19# $1: key
20persist_hash() {
21	local hash=$1
22	for key in $(redis-cli hkeys ${hash}); do
23		local value=$(redis-cli HGET ${hash} ${key})
24		echo "redis-cli HSET ${hash} ${key} ${value}"
25	done
26}
27
28# $1: key
29persist_list() {
30	local key=$1
31	for item in $(redis-cli lrange ${key} 0 -1); do
32		echo "redis-cli RPUSH ${key} ${item}"
33	done
34}
35
36# $1: key
37persist_set() {
38	local key=$1
39	for item in $(redis-cli smembers ${key}); do
40		echo "redis-cli SADD ${key} ${item}"
41	done
42}
43
44# $1: key
45persist_zset() {
46	local key=$1
47	for member in $(redis-cli zrange ${key} 0 -1); do
48		local score=$(redis-cli zscore ${key} ${member})
49		echo "redis-cli ZADD ${key} ${score} ${member}"
50	done
51}
52
53persist() {
54	redis-cli info >/dev/null 2>&1
55	if [ "$?" != "0" ]; then
56		echo "refusing to persist: redis is not running"
57		return
58	fi
59
60	# note: this function is implemented this way because the output
61	# of redis-cli DUMP results in error when given to redis-cli RESTORE.
62	# for example, the following command:
63	# $ redis-cli DUMP "mykey" | redis-cli -x RESTORE "mynewkey" 0
64	# results in this error:
65	# (error) ERR DUMP payload version or checksum are wrong
66	tmp=$(mktemp -p /tmp)
67	for key in ${PERSIST_KEYS}; do
68		for subkey in $(redis-cli keys ${key}); do
69			echo "persisting key ${subkey}"
70			local t=$(redis-cli type ${subkey})
71			case $t in
72				hash)
73					persist_hash ${subkey} >> ${tmp}
74					;;
75				string)
76					persist_string ${subkey} >> ${tmp}
77					;;
78				list)
79					persist_list ${subkey} >> ${tmp}
80					;;
81				set)
82					persist_set ${subkey} >> ${tmp}
83					;;
84				zset)
85					persist_zset ${subkey} >> ${tmp}
86					;;
87			esac
88		done
89	done
90	mv ${tmp} ${PERSIST_FILE}
91	rm -f ${tmp}
92}
93
94restore() {
95	sh ${PERSIST_FILE}
96}
97
98case "${1}" in
99	persist)
100		persist
101		;;
102	restore)
103		restore
104		;;
105	*)
106		echo "usage: $(basename $0) <persist|restore> [persistfile]"
107		;;
108esac
109