#!/bin/bash export LANG=C export LC_ALL=C rdbver=1.1 keyname=$2 test -d $3 || mkdir -p $3 log_file=$3/${0##*/}.log ## redis opts redis_cli_opts='--raw' redis_bgsave_timeout=300 redis_bgsave_one_try_timeout=15 redis_data_dir='/var/lib/redis' redis_rdp_location="$redis_data_dir/dump.rdb" test -f $redis_rdp_location || { redis_data_dir='/var/spool/redis' redis_rdp_location="$redis_data_dir/dump.rdb" } redis_backup_dir=$redis_data_dir current_date=`date '+%Y%m%d-%H%M%S'` ## choosing compress bzip=`which bzip2 2>/dev/null`; pbzip=`which pbzip2 2>/dev/null`; gzip=`which gzip 2>/dev/null`; bzcompress=${pbzip:-${bzip}}; compress_prog=${bzcompress:-${gzip}} test -x "$compress_prog" || { echo "[ERROR `date '+%Y/%m/%d-%H:%M:%S'`] No compress util or $compress_prog has no execute flag. Fix it first."; exit 1; } case "${compress_prog##*/}" in 'pbzip2' ) compress_ext='bz2'; tar --version | grep -oE '1.2[0-6]' > /dev/null || compress_prog+=' -l' ;; 'bzip2' ) compress_ext='bz2' ;; 'gzip' ) compress_ext='gz' ;; esac function show_error() { local message="$1"; local funcname="$2"; local log_date=`date '+%Y/%m/%d:%H:%M:%S'` echo -e "[ERROR.$funcname $log_date] $message" >> $log_file 2>&1 } function show_notice() { local message="$1"; local funcname="$2"; local log_date=`date '+%Y/%m/%d:%H:%M:%S'` echo -e "[NOTICE.$funcname $log_date] $message" >> $log_file 2>&1 } function show_usage() { echo "Usage: ${0##*/} --(get|remove) " echo -e "\t Example: ${0##*/} --get example.ru /var/log" echo -e "\t Example: ${0##*/} --remove example.ru /var/log" } function backup_redis() { local err=0; local dir=$1; local seconds=0; which redis-cli > /dev/null || { show_error "Not found redis-cli." "$FUNCNAME"; return 1;} test $# -eq 1 || { show_error "Function wrong usage! Args=$@" "$FUNCNAME"; return 1; } test -d $dir || mkdir -p $dir local lastsave_before=`echo lastsave | redis-cli $redis_cli_opts` echo bgsave | redis-cli $redis_cli_opts while [ $seconds -lt $redis_bgsave_timeout ]; do sleep $redis_bgsave_one_try_timeout let seconds=seconds+$redis_bgsave_one_try_timeout local lastsave_after=`echo lastsave | redis-cli $redis_cli_opts` show_notice "Curent seconds: $seconds. Lastsave before: $lastsave_before, lastsave after: $lastsave_after." "$FUNCNAME" test "x$lastsave_before" != "x$lastsave_after" && { show_notice "Saving $redis_rdp_location to $dir/${current_date}-redis.rdb, and compress" "$FUNCNAME" cp $redis_rdp_location $dir/${current_date}-redis.rdb && \ nice -n 19 ionice -c 3 $compress_prog -f $dir/${current_date}-redis.rdb || \ { show_error "Error on copy and compress $redis_rdp_location" "$FUNCNAME"; local err=1; } return $err; } done show_error "Attempt to backup redis rdb has ended by timeout: $redis_bgsave_timeout seconds!" "$FUNCNAME"; return 1; } function remove_redis_db() { redis-cli $redis_cli_opts -n $dbnumber flushdb redis-cli $redis_cli_opts DEL $keyname show_notice "Database $keyname with dbnumber=$dbnumber removed." "get_redis_db_number" } function get_redis_db_number() { which redis-cli > /dev/null || { show_error "Not found redis-cli." "$FUNCNAME"; return 1;} dbnumber=`redis-cli $redis_cli_opts GET $keyname` show_notice "Curent dbnumber for key $keyname=$dbnumber" "$FUNCNAME" } function get_redis_db_list() { which redis-cli > /dev/null || { show_error "Not found redis-cli." "$FUNCNAME"; return 1;} dblist=`redis-cli $redis_cli_opts INFO keyspace |grep db |grep -v db0 |awk -F':' '{print $1}' | sed 's/db//' | sort | uniq |tr '\n' ' '` show_notice "Redis dblist: $dblist" "$FUNCNAME" } function get_redis_db_not_used_number() { local i=1; while true do echo $dblist | tr ' ' '\n' | grep -qE "^${i}$" || break i=$((i + 1)); done dbnumber=$i show_notice "Uniq dbnumber: $dbnumber" "$FUNCNAME" } function create_redis_key_with_db_number() { redis-cli $redis_cli_opts SET $keyname "$dbnumber" show_notice "Created key: $keyname with value=$dbnumber" "$FUNCNAME" } test x"$1" = "x" -o x"$2" = "x" -o x"$3" = "x" && { echo "One or more arguments is missing!"; show_usage; exit 1; } test x"$1" == x"" && show_usage test x"$1" = x"--get" && { get_redis_db_number check=`echo $dbnumber | grep -E ^\-?[0-9]+$` test "$check" = '' && { show_notice "Database $keyname not exist, script generate new database number." "get_redis_db_number" backup_redis $redis_backup_dir && \ get_redis_db_list && \ get_redis_db_not_used_number && \ create_redis_key_with_db_number } >> $log_file 2>&1 echo $dbnumber exit 0 } test x"$1" = x"--remove" && { get_redis_db_number check=`echo $dbnumber | grep -E ^\-?[0-9]+$` test "$check" = '' && { show_notice "Can't remove database $keyname, not exist." "get_redis_db_number" exit 1; } >> $log_file 2>&1 backup_redis $redis_backup_dir && \ remove_redis_db exit 0 }