-
-
Save goodevilgenius/11375877 to your computer and use it in GitHub Desktop.
[membash] BASH script which may be used to interact with memcache. All main memcache functions are supported. #memcache
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# Gist: 11375877 | |
# Url: https://gist.github.com/goodevilgenius/11375877 | |
# | |
# All memcache functions are supported. | |
# | |
# Can also be sourced from other scripts, e.g. | |
# source membash.sh | |
# MCSERVER="localhost" | |
# MCPORT=11211 | |
# foobar=$(mc_get foobar) | |
# [ -z "$foobar" ] && foobar="default value" | |
# mc_set foobar 0 "$foobar" | |
# original author: wumin, https://gist.github.com/ri0day/1538831 | |
# updated by goodevilgenius to support debian-based systems, support more | |
# functions, and be more user-friendly | |
mc_usage() { | |
format_usage="membash: a memcache library for BASH \n\ | |
https://gist.github.com/goodevilgenius/11375877\n\n\ | |
Usage:\n | |
\t $(basename "$0") [-hp] command [arguments] \n \ | |
\t [-h]\t memcached hostname or ip. \n \ | |
\t [-p]\t memcached port. \n\n\ | |
Commands: \n \ | |
\t usage (print this help) \n \ | |
\t set/add/replace/append/prepend key exptime value \n \ | |
\t touch key exptime \n \ | |
\t incr/decr key value \n \ | |
\t get key \n \ | |
\t delete key [time] \n \ | |
\t stats \n \ | |
\t list_all_keys" | |
echo -e $format_usage | |
} | |
mc_help() { mc_usage;} | |
mc_sendmsg() { echo -e "$*\r" | nc $MCSERVER $MCPORT;} | |
mc_stats() { mc_sendmsg "stats";} | |
mc_get_last_items_id() { | |
LastID=$(mc_sendmsg "stats items"|tail -n 2|head -n 1|awk -F':' '{print $2}') | |
echo $LastID | |
} | |
mc_list_all_keys() { | |
:>/dev/shm/mc_all_keys_${MCSERVER}_${MCPORT}.txt | |
max_item_num=$(mc_get_last_items_id) | |
for i in `seq 1 $max_item_num` | |
do | |
mc_sendmsg "stats cachedump $i 0" | awk '{print $2}' | |
done >>/dev/shm/mc_all_keys_${MCSERVER}_${MCPORT}.txt | |
sed -i '/^$/d' /dev/shm/mc_all_keys_${MCSERVER}_${MCPORT}.txt | |
cat /dev/shm/mc_all_keys_${MCSERVER}_${MCPORT}.txt | |
} | |
mc_get() { mc_sendmsg "get $1" | awk "/^VALUE $1/{a=1;next}/^END/{a=0}a" ;} | |
mc_touch() { | |
key="$1" | |
shift | |
let exptime="$1" | |
shift | |
mc_sendmsg "touch $key $exptime" | |
} | |
mc_doset() { | |
command="$1" | |
shift | |
key="$1" | |
shift | |
let exptime="$1" | |
shift | |
val="$*" | |
let bytes=$(echo -n "$val"|wc -c) | |
mc_sendmsg "$command $key 0 $exptime $bytes\r\n$val" | |
} | |
mc_set() { mc_doset set "$@";} | |
mc_add() { mc_doset add "$@";} | |
mc_replace() { mc_doset replace "$@";} | |
mc_append() { mc_doset append "$@";} | |
mc_prepend() { mc_doset prepend "$@";} | |
mc_delete() { mc_sendmsg delete "$*";} | |
mc_incr() { mc_sendmsg incr "$*";} | |
mc_decr() { mc_sendmsg decr "$*";} | |
mc_superpurge() { | |
mc_list_all_keys > /dev/null | |
if [ ! -z "/dev/shm/mc_all_keys_${MCSERVER}_${MCPORT}.txt" ];then | |
grep "$1" /dev/shm/mc_all_keys_${MCSERVER}_${MCPORT}.txt >/dev/shm/temp.swap.${MCSERVER}_${MCPORT}.txt | |
fi | |
while read keys | |
do | |
mc_sendmsg "delete ${keys}" | |
done </dev/shm/temp.swap.${MCSERVER}_${MCPORT}.txt | |
rm -rf /dev/shm/temp.swap.${MCSERVER}_${MCPORT}.txt | |
} | |
if [ "$(basename "$0" .sh)" = "membash" ] | |
then | |
MCSERVER="localhost" | |
MCPORT=11211 | |
while getopts "h:p:" flag | |
do | |
case $flag in | |
h) | |
MCSERVER=${OPTARG:="localhost"} | |
;; | |
p) | |
MCPORT=${OPTARG:="11211"} | |
;; | |
\?) | |
echo "Invalid option: $OPTARG" >&2 | |
;; | |
esac | |
done | |
command="${@:$OPTIND:1}" | |
[ -z "$command" ] && command="usage" | |
let OPTIND++ | |
mc_$command "${@:$OPTIND}" | |
exit $? | |
fi |
mc_sendmsg() { nc "$MCSERVER" "$MCPORT" << END_OF_MSG
$*
quit
END_OF_MSG
perhaps..
}
Or even allow multiple commands enclosing each one in quotes if they have spaces like "stat" "second cmd" ... "stat"
#!/usr/bin/env bash
#
set -u
#
arr_command=( $@ )
( IFS=$'\n'; echo "${arr_command[]}" )
nc "myservername" 11211 << END_OF_INPUT
$( IFS=$'\n'; echo "${arr_command[]}" )
quit
END_OF_INPUT
Please remove the last ^M / CR / carriage-return character:
echo -e "add __TEMPDATA__ 0 600 8\r\ntempdata\r\nquit" | nc localhost 11211
# "tempdata^M"
GET_TEMPDATA1=$(echo -e "get __TEMPDATA__\r\nquit" | nc localhost 11211| awk "/^VALUE $1/{a=1;next}/^END/{a=0}a")
echo -e "${GET_TEMPDATA1} - length(GET_TEMPDATA1)==${#GET_TEMPDATA1}"
# "tempdata"
GET_TEMPDATA2=$(echo -e "get __TEMPDATA__\r\nquit" | nc localhost 11211| awk "/^VALUE $1/{a=1;next}/^END/{a=0}a" | sed 's/\r$//')
echo -e "${GET_TEMPDATA2} - length(GET_TEMPDATA2)==${#GET_TEMPDATA2}"
Rather than the END_OF_INPUT stuffs, I just added -q 0 for immediate disconnect after payload delivery. Change:
nc $MCSERVER $MCPORT
to
nc -q 0 $MCSERVER $MCPORT
at line 40.
Any reason this would not work?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
When I invoke this script interactively with a single argument like "stats" it produces the result but does not close the connection.
I have to use control-C to exit. Everything else is ignored (including the nc command quit)
Perhaps you want to use a HERE statement where the passed argument is expanded and quit appended.
That way the connection closes after doing the required command.
Example
#!/usr/bin/env bash
set -u
command="stats"
nc "myhostname" 11211 << END_OF_INPUT
$command
quit
END_OF_INPUT