注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

永福的技术博客

Linux运维

 
 
 

日志

 
 

在shell判断数字时出现 integer expression expected 错误  

2012-08-08 17:28:40|  分类: 软件编程 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
今天要写一个监控redis内存使用的脚本

[root]# cat watch_redis.sh
#!/bin/sh

#set -xv    #调试命令,在第二步中将其取消注释,即可进行调试
contents='/tmp/watch_redis_info.log'
d=$(date +%Y%m%d)
Num_limit=10737418240   #表示10G内存

/opt/app/redis/redis-cli  -h 10.0.110.72  info > $contents
#dos2unix $contents
Num_test=$(grep 'used_memory:' $contents |awk -F':' '{print $2}')
echo $Num_test

echo $Num_limit
# judge if > 10737418240 (10G)
if [ $Num_test -gt $Num_limit ]; then
    Subject="【警告】redis的内存使用超过了10G"
    echo $Subject    #在超过10G的情况下,邮件警告,这里用echo代替
fi

运行过程中,出现如下错误:

[root]# ./watch_redis.sh   
166634912
10737418240
: integer expression expected line 15: [: 166634912

问题分析:
1. 从报错结果看,说的是15行的if判断,需要的是一个整数
2. 但是从结果的显示和推测上来看,确实是整数呀。echo $Num_test 和echo $Num_limit 都有输出,是整数呀。
3. 百思不得其解,开启调试命令:set -xv  (将脚本中的set -xv行的#注释去掉)
运行脚本,得到如下结果:
[root]# ./watch_redis.sh    
contents='/tmp/watch_redis_info.log'
+ contents=/tmp/watch_redis_info.log
d=$(date +%Y%m%d)
date +%Y%m%d
++ date +%Y%m%d
+ d=20120808
Num_limit=10737418240
+ Num_limit=10737418240

/opt/app/redis/redis-cli  -h 10.0.110.72  info > $contents
+ /opt/app/redis/redis-cli -h 10.0.110.72 info
#dos2unix $contents
Num_test=`grep 'used_memory:' $contents |awk -F':' '{print $2}'`
grep 'used_memory:' $contents |awk -F':' '{print $2}'
++ grep used_memory: /tmp/watch_redis_info.log
++ awk -F: '{print $2}'
+ Num_test=$'167105984\r'    #注意这一句,怎么结果是$'167105984\r' 而不是167105984的整数,问题就出在这里
echo $Num_test
+ echo $'167105984\r'
167105984

echo $Num_limit
+ echo 10737418240
10737418240
# judge if > 10737418240 (10G)
if [ $Num_test -gt $Num_limit ]; then
    Subject="【警告】redis的内存使用超过了10G"
    echo $Subject
fi
+ '[' $'167105984\r' -gt 10737418240 ']'
: integer expression expected line 15: [: 167105984

+ Num_test=$'167105984\r'    #注意这一句,怎么结果是$'167105984\r' 而不是167105984的整数,问题就出在这里
怎么会多出一个$和\r来?
1. 难道是经过grep和awk操作将这些不可见字符引入的。经多次实验,排除了这个原因。
2. 那就是/tmp/watch_redis_info.log文件中本身含有这些特殊的不可见字符

使用命令cat -A  /tmp/watch_redis_info.log ,果然发现原来这个文件生成的为dos格式的
[root]# cat -A /tmp/watch_redis_info.log 
redis_version:2.4.15^M$
.....     #此处省略若干行
blocked_clients:0^M$
used_memory:167473280^M$
used_memory_human:159.71M^M$
used_memory_rss:384790528^M$
used_memory_peak:167503912^M$
used_memory_peak_human:159.74M^M$    # 在linux字符界面中 ^M表示dos下的行结束符\r\n
.....      #此处省略若干行 

好了,问题找到,是由于不同的行结束符导致的问题。
将 /tmp/watch_redis_info.log 进行dos2unix转码,即:将#dos2unix $contents 行的“#”注释符去掉
最终的脚本为:
#!/bin/sh

set -xv   #调试结束后,将该行注释
contents='/tmp/watch_redis_info.log'
d=$(date +%Y%m%d)
Num_limit=10737418240

/opt/app/redis/redis-cli  -h 10.0.110.72  info > $contents
dos2unix $contents >/dev/null 2>&1    #对文件进行处理,转换为linux的行结束符
Num_test=`grep 'used_memory:' $contents |awk -F':' '{print $2}'`

# judge if > 10737418240 (10G)
if [ $Num_test -gt $Num_limit ]; then
    Subject="【警告】redis的内存使用超过了10G"
    echo $Subject
fi

运行脚本得到的结果:
[root]# /data/crontab/watch_redis.sh    
contents='/tmp/watch_redis_info.log'
+ contents=/tmp/watch_redis_info.log
d=$(date +%Y%m%d)
date +%Y%m%d
++ date +%Y%m%d
+ d=20120808
Num_limit=10737418240
+ Num_limit=10737418240

/opt/app/redis/redis-cli  -h 10.0.110.72  info > $contents
+ /opt/app/redis/redis-cli -h 10.0.110.72 info
dos2unix $contents >/dev/null 2>&1
+ dos2unix /tmp/watch_redis_info.log
Num_test=`grep 'used_memory:' $contents |awk -F':' '{print $2}'`
grep 'used_memory:' $contents |awk -F':' '{print $2}'
++ grep used_memory: /tmp/watch_redis_info.log
++ awk -F: '{print $2}'
+ Num_test=167577808    #注意到这里没有了$和\r的结尾字符了

# judge if > 10737418240 (10G)
if [ $Num_test -gt $Num_limit ]; then
    Subject="【警告】redis的内存使用超过了10G"
    echo $Subject
fi
+ '[' 167577808 -gt 10737418240 ']'

好了,问题解决,记得将set -xv 行删除或注释。
[永福原创]转载请注明:来自http://rickie622.blog.163.com

下面还有两个问题待解释和解决:
1. 为什么redis-cli命令生成的文件要是\r\n结尾的?在linux下,应该要自动以\n结尾吧,这个需要写redis的人去改进了。
2. 怎么在shell下,去掉这些不可见的特殊字符,将字符串直接转换成数字(不包含其他任何字符,仅数字)?

附注:
换行符在Linux和Windows下的区别以及将Linux和windows下的文件的互转的Linux命令:unix2dos, dos2unix
一、区别
换行符:
1.windows中的换行符是\r\n,
2. linux/unix下的换行符是\n。
其中:
回车符:\r=0x0d  (13)          return; #回车(carriage return)  
换行符:\n=0x0a (10)           newline。#换行(newline)
二、文件格式互转命令
1.unix2dos:将具有unix风格的格式文件转化为具有window下的格式文件。
2.dos2unix:将具有windows风格的格式文件转化为unix下的格式文件。
详见:http://blog.csdn.net/wzb56/article/details/6860358





  评论这张
 
阅读(6185)| 评论(2)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018