昨天经阮哥指点后,写一个检查redis-server的内存消耗的脚本。脚本本身不复杂,因为redis-cli已经提供了查询接口。

# redis-cli -p yourt_port info | grep 'used_memory'

# resuts:
# used_memory:122088016
# used_memory_human:116.43M
# used_memory_rss:128057344
# used_memory_peak:122079336
# used_memory_peak_human:116.42M

一般会选择提取出used_memory_human的结果,但是考虑到万一内存消耗上G了呢?那么这里也要进行一个单位转换,干脆就提取used_memory这个值,以字节为单位的,然后在这个值基础上除以1024*1024换算成MB。

#!/bin/bash
redis_ret=$(redis-cli -p your_port info |  grep '\<used_memory \>' | awk -F":" '{ print $2 }')
redis_ret=$(echo "scale=2; $redis_ret/1024/1024" | bc)

echo "$redis_ret"
</used_memory>

执行脚本你会发现出错,错误提示为:

(standard_in) 1: illegal character: ^M

这说明redis_ret这个包含了非法字符^M,相信使用Vim打开Windows下的文本的童鞋肯定知道这个字符是什么——回车。

我当时在执行这个脚本的时候没注意到这个错误,而是在今天回头再思考的时候才前后联系起来。当时没发现,所以我当时不知道问题的原因。因为脚本执行出错,我又在脚本中加了一些调试语句,目的是看这个redis_ret是否是我需要的结果:

#!/bin/bash
redis_ret=$(redis-cli -p your_port info |  grep '\<used_memory \>' | awk -F":" '{ print $2 }')
redis_ret=$(echo "scale=2; $redis_ret/1024/1024" | bc)

echo "a${redis_ret}+|--|+${redis_ret}b"

# results
129774752
b|--|+12977475
</used_memory>

昨天看到这个结果的时候,我快抓狂了(10点多了),怎么也想不通为什么会是这样的一个结果。今天到公司上班,脑子清醒点,又开始琢磨这个结果。发现echo后面的字符跑到前面去了,为什么会跑到前面去?什么情况下,打印的时候,光标会跑到前面去了?一个是退格符(\b),另外一个就是回车符了(\r)。平时我们编程的时候,不大会注意回车和换行的区别,因为语言帮我们统一了,但是实际上在不同的系统下还是有区别的,具体可以看这一篇文章,讲得非常清楚。

退格符是不可能的了,唯一的可能是redis_ret变量中多了一个回车符,在前面的脚本基础上再删除换行符:

#!/bin/bash
redis_ret=$(redis-cli -p your_port info |  grep '\<used_memory \>' | awk -F":" '{ print $2 }' | tr -d "\r")
echo "a${redis_ret}+|--|+${redis_ret}b"

#results:
129774752+|--|+129774752
</used_memory>

现在结果就正常了,所以原因是在redis_ret返回值中多了一个回车符,其实这点也是可以验证的,cat命令有选项可以显示这些不能打印的控制字符:

# redis-cli -p your_port info |  grep '\<used_memory \>' | cat -et -
used_memory:137850816^M$
</used_memory>

在回到之前bc命令执行的错误提示,一切都可以解释得通了。

不过是该怪redis-cli这个命令没有处理好结果输出呢,还是怪自己不小心呢?