Redis: who is eating my field when piping llen results through awk?
awk, bash, pipe, redis, shell
Solution
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 }'
Problem
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.