Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Redis: who is eating my field when piping llen results through awk?

Redis: 2.0.4, 2.4.1, ...

I'm going to write a Nagios plugin to check the length of a list. Here's my script:

#!/bin/sh

help()
{
    echo "Usage: $0 <host> <port> <key> -w <warning> -c <critical>"
}

case "$1" in
    --help)
        help 
        exit
        ;;
esac

if [ $# -eq 0 ]; then
    help
    exit 3
fi
if [ $# -ne "7" ]; then
    help
    exit 4
fi
if [ $4 !="-w" -o $6 !="-c" ]; then
    help
    exit 5
fi

REDIS_CLI="/usr/local/redis/bin/redis-cli"
LLEN=`$REDIS_CLI -h $1 -p $2 llen $3 | awk '{ print $2 }'`
if [ $LLEN -lt $5 ]; then
    echo "$3.llen:$2 OK - $LLEN | $3.llen:$2=$LLEN;$5;$7"
    exit 0
elif [ $LLEN -ge $5 -a $LLEN -lt $7 ]; then
    echo "$3.llen:$2 WARNING - $LLEN | $3.llen:$2=$LLEN;$5;$7"
    exit 1
elif [ $LLEN -ge "$7" ]; then   
    echo "$3.llen:$2 CRITICAL - $LLEN | $3.llen:$2=$LLEN;$5;$7"
    exit 2
fi

but I got the following error when running /usr/lib64/nagios/plugins/redis_llen.sh 192.168.5.201 2468 -w 90000 -c 100000:

/usr/lib64/nagios/plugins/redis_llen.sh: line 31: [: -lt: unary operator expected
/usr/lib64/nagios/plugins/redis_llen.sh: line 34: [: too many arguments
/usr/lib64/nagios/plugins/redis_llen.sh: line 37: [: -ge: unary operator expected

Running it in debug mode, I found that the LLEN's value is... blank. Since the llen queue_1 returns the right result:

# /usr/local/redis/bin/redis-cli -h 192.168.5.201 -p 2468 llen queue_1
(integer) 965

why does the pipeline swallow my fields? (not only to awk but also echo, tee, ...):

# /usr/local/redis/bin/redis-cli -h 192.168.5.201 -p 2468 llen queue_1 | \
awk '{ print $0 }'
961

I can check the number of fields and print the corresponding as a workaround:

| awk '{ if (NF == 2) print $2; else print $1 }'`

but I really want to know why does it happen? Is there any null or special character between (interger) and the number?

PS: it seems that some other Redis version (for e.x: 1.3.7) doesn't get this issue.

like image 475
quanta Avatar asked Jun 19 '12 10:06

quanta


1 Answers

What you're experiencing is redis-cli selecting different outputs depending on what STDOUT is. If STDOUT is a TTY, redis-cli will output using it's "standard" formatting. Otherwise, the "raw" formatting is the default:

--raw            Use raw formatting for replies (default when STDOUT is not a tty)

As you see from the help, or the above, you can specify --raw to always have it output the "raw" format (without type qualifiers, etc). What I found out digging through the source for this, is that there is also a CSV mode, using redis-cli --csv.

Edit: To force the "standard" output, even when STDOUT is not a TTY, you can set the environment variable FAKETTY:

FAKETTY=1 redis-cli llen some_list | awk '{ print $2 }'

Or

redis-cli --raw llen some_list | awk '{ print $1 }'
like image 118
Linus Thiel Avatar answered Sep 28 '22 14:09

Linus Thiel