Shell中打印匹配关键字的前后行 [echo、grep用法]
在日常运维中,经常需要监控某个进程,并打印某个进程的监控结果,通常需要打印匹配某个结果的行以及其前后各N行。
这里注意下:echo使用-e参数,对打印的结果中进行\n换行
[root@mq-master02 ~]# echo "abcd" abcd [root@mq-master02 ~]# echo "ab\ncd" ab\ncd [root@mq-master02 ~]# echo "ab \n cd" ab \n cd [root@mq-master02 ~]# echo -e "ab\ncd" ab cd [root@mq-master02 ~]# echo -e "ab \n cd" ab cd [root@mq-master02 ~]# echo -e "ab \n cd \n \n df" ab cd df [root@mq-master02 ~]# echo -e "ab\ncd \n \ndf" ab cd df
echo的-n、-e参数:
1)echo -n 表示:不换行输出 [root@mq-master02 ~]# echo "123" 123 [root@mq-master02 ~]# echo -n "123" 123[root@mq-master02 ~]# 2)echo -e 表示:处理特殊字符。若字符串中出现以下字符,则特别加以处理,而不会将它当成一般文字输出: \a 发出警告声; \b 删除前一个字符; \c 最后不加上换行符号; \f 换行但光标仍旧停留在原来的位置; \n 换行且光标移至行首; \r 光标移至行首,但不换行; \t 插入tab; \v 与\f相同; \\ 插入\字符; \nnn 插入nnn(八进制)所代表的ASCII字符; [root@mq-master02 ~]# echo "123\n456" 123\n456 [root@mq-master02 ~]# echo -e "123\n456" 123 456 [root@mq-master02 ~]# echo -e "wang\bkevin" wankevin
echo后面跟双引号或单引号问题:
使用echo输出字符串时候,无论单引号还是双引号都是一样的。 如果字符串中有变量,单引号会忽略,而双引号会把变量解析以后带入字符串。 也就是说,echo后面的单引号就是一般输出,对引号里面的变量和特殊操作符号都不识别。 echo后面跟双引号,双引号里能识别变量和特殊操作符号; echo后面跟单引号,单引号里不会识别变量和特殊操作符号; 示例: [root@localhost ~]# aa=123 [root@localhost ~]# echo "${aa}" 123 [root@localhost ~]# echo '${aa}' ${aa} 如下,将kill -9 `ps -ef|grep web_server|awk '{print $2}'`这条命令追加到web_script.sh脚本中,正确写法如下: 由于要保留kill命令后面``操作语句中的单引号和$2,所以单引号和$2前面都要加转义符\。 下面示例中echo后面加不加-e参数,效果都一样! [root@localhost ~]# echo -e "kill -9 \`ps -ef|grep web_server|awk '{print \$2}'\`" >> 123.sh [root@localhost ~]# cat 123.sh kill -9 `ps -ef|grep web_server|awk '{print $2}'` 如果不加转移符号,则echo后面的双引号就会直接识别出``执行之后的结果,就将web_server的pid打印出来了 [root@localhost ~]# echo -e "kill -9 `ps -ef|grep web_server|awk '{print $2}'`" >> 123.sh [root@localhost ~]# cat 123.sh kill -9 9850 如果echo不使用双引号,使用单引号,则结果中会把$2内容给抹掉。 [root@localhost ~]# echo -e 'kill -9 `ps -ef|grep web_server|awk '{print $2}'`' >> 123.sh [root@localhost ~]# cat 123.sh kill -9 `ps -ef|grep web_server|awk {print }` 如果echo使用单引号,在单引号里面使用双引号,如下,在echo的单引号里将awk后面的内容用双引号,则$2会保留。 但是awk后面必须是单引号才能正确print,awk后面跟单引号就没有意义了! [root@localhost ~]# echo -e 'kill -9 `ps -ef|grep web_server|awk "{print $2}"`' >> 123.sh [root@localhost ~]# cat 123.sh kill -9 `ps -ef|grep web_server|awk "{print $2}"`
示例1
[root@mq-master02 ~]# cat /opt/test 192.168.10.11 Don't worry! main is running! 192.168.10.12 Don't worry! main is running! 192.168.10.13 It's so bad! main is failed! 192.168.10.14 Don't worry! main is running! 192.168.10.15 Don't worry! main is running! 192.168.10.16 It's so bad! main is failed! 192.168.10.17 Don't worry! main is running! 192.168.10.18 Don't worry! main is running! 192.168.10.19 Don't worry! main is running! 192.168.10.20 Don't worry! main is running! 192.168.10.21 Don't worry! main is running! 192.168.10.12 Don't worry! main is running! 1)打印/opt/test中所有匹配"main is failed"的行 [root@mq-master02 ~]# cat /opt/test |grep "main is failed" It's so bad! main is failed! It's so bad! main is failed! [root@mq-master02 ~]# sed -n '/main is failed/p' /opt/test It's so bad! main is failed! It's so bad! main is failed! 2)打印/opt/test中所有匹配"main is failed"的行及其前1行 [root@mq-master02 ~]# cat /opt/test |grep "main is failed" -B1 192.168.10.13 It's so bad! main is failed! -- 192.168.10.16 It's so bad! main is failed! 3)打印/opt/test中所有匹配"main is failed"的行及其后1行 [root@mq-master02 ~]# cat /opt/test |grep "main is failed" -A1 It's so bad! main is failed! 192.168.10.14 -- It's so bad! main is failed! 192.168.10.17 4)打印/opt/test中所有匹配"main is failed"的行及其前后各1行 [root@mq-master02 ~]# cat /opt/test |grep "main is failed" -C1 192.168.10.13 It's so bad! main is failed! 192.168.10.14 -- 192.168.10.16 It's so bad! main is failed! 192.168.10.17 5)把/opt/test中所有匹配"main is failed"的行及其前1行的结果打印到/root/result.log中,并加上时间 [root@mq-master02 ~]# echo -e "$(date)\n$(cat /opt/test|grep "main is failed" -B1)"> /root/result.log [root@mq-master02 ~]# cat /root/result.log Wed Oct 10 20:34:15 CST 2018 192.168.10.13 It's so bad! main is failed! -- 192.168.10.16 It's so bad! main is failed! [root@mq-master02 ~]# echo -e "$(date)\n$(cat /opt/test|grep "main is failed" -B1) \n" > /root/result.log [root@mq-master02 ~]# echo -e "$(date)\n$(cat /opt/test|grep "main is failed" -B1) \n" >> /root/result.log [root@mq-master02 ~]# echo -e "$(date)\n$(cat /opt/test|grep "main is failed" -B1) \n" >> /root/result.log [root@mq-master02 ~]# cat /root/result.log Wed Oct 10 20:35:27 CST 2018 192.168.10.13 It's so bad! main is failed! -- 192.168.10.16 It's so bad! main is failed! Wed Oct 10 20:35:29 CST 2018 192.168.10.13 It's so bad! main is failed! -- 192.168.10.16 It's so bad! main is failed! Wed Oct 10 20:35:29 CST 2018 192.168.10.13 It's so bad! main is failed! -- 192.168.10.16 It's so bad! main is failed! [root@mq-master02 ~]# echo -e "$(date +%Y年%m月%d日) $(date +%A) $(date +%H时%M分%S秒)\n$(echo "今天是个好日子啊") \n" > /root/result.log You have new mail in /var/spool/mail/root [root@mq-master02 ~]# echo -e "$(date +%Y年%m月%d日) $(date +%A) $(date +%H时%M分%S秒)\n$(echo "今天是个好日子啊") \n" >> /root/result.log [root@mq-master02 ~]# echo -e "$(date +%Y年%m月%d日) $(date +%A) $(date +%H时%M分%S秒)\n$(echo "今天是个好日子啊") \n" >> /root/result.log [root@mq-master02 ~]# cat /root/result.log 2018年10月10日 Wednesday 20时36分49秒 今天是个好日子啊 2018年10月10日 Wednesday 20时36分52秒 今天是个好日子啊 2018年10月10日 Wednesday 20时36分54秒 今天是个好日子啊
示例2
ip列表文件 [root@kevin ~]# cat /opt/ip.list 192.168.10.11 192.168.10.12 192.168.10.13 192.168.10.14 192.168.10.15 192.168.10.16 192.168.10.17 main进程状态的检查脚本: [root@kevin ~]# cat /opt/script/6_main_check.sh #!/bin/bash for i in $(cat /opt/ip.list) do /usr/bin/rsync -e "ssh -p22" -avpgolr /usr/bin/main_check $i:/usr/bin/ > /dev/null 2>&1 ssh -p22 root@$i "echo $i;sh /usr/bin/main_check" done [root@kevin ~]# cat /usr/bin/main_check #!/bin/bash NUM=$(ps -ef|grep -w main|grep -v grep|wc -l) if [ $NUM -eq 0 ];then echo "Oh!My God! It's broken! main is stoped!" else echo "Don't worry! main is running!" fi 检查脚本执行结果 [root@kevin ~]# sh /opt/script/6_main_check.sh 192.168.10.11 Don't worry! main is running! 192.168.10.12 Don't worry! main is running! 192.168.10.13 Don't worry! main is running! 192.168.10.14 Don't worry! main is running! 192.168.10.15 Don't worry! main is running! 192.168.10.16 Don't worry! main is running! 192.168.10.17 Don't worry! main is running! 检查脚本执行结果的打印脚本 [root@kevin ~]# cat /mnt/main_check_result.sh #!/bin/bash NUM=$(/bin/bash /opt/script/6_main_check.sh |grep -w "main is stoped"|wc -l) CONTENT=$(/bin/bash /opt/script/6_main_check.sh |grep -w "main is stoped") if [ $NUM -ne 0 ];then echo -e "$(date +%Y年%m月%d日) $(date +%A) $(date +%H时%M分%S秒)\n$(/bin/bash /opt/script/6_main_check.sh |grep "main is stoped" -B1)\n">> /mnt/main_check_result.log else echo -e "$(date +%Y年%m月%d日) $(date +%A) $(date +%H时%M分%S秒)\n$(echo "当前时段所有机器的main进程运行正常,无需担心哈!")\n">> /mnt/main_check_result.log fi main检查的结果文件内容 [root@kevin ~]# cat /mnt/main_check_result.log 2018年10月10日 星期三 20时30分41秒 当前时段所有机器的main进程运行正常,无需担心哈! 2018年10月10日 Wednesday 20时30分46秒 当前时段所有机器的main进程运行正常,无需担心哈! 2018年10月10日 Wednesday 20时35分45秒 当前时段所有机器的main进程运行正常,无需担心哈! 2018年10月10日 Wednesday 20时40分45秒 当前时段所有机器的main进程运行正常,无需担心哈! 以上的脚本:不管main进程状态检查结果是否正常,都打印一个结果到/mnt/main_check_result.log文件中, 其实检查结果正常的时候,可以不必打印结果(即echo "****" > /dev/null 2 >&1); 只有检查结果不正常的时候才打印结果,这样比较好点。 对/mnt/main_check_result.log文件大小做判断,当该文件大于60M(即61865984)时就清空。 [root@kevin ~]# ls -l /mnt/main_check_result.log -rw-r--r--. 1 root root 16998 Nov 19 2017 /mnt/main_check_result.log [root@kevin ~]# ls -l /mnt/main_check_result.log|awk '{print $5}' 16998 [root@kevin ~]# ls -l /mnt/main_check_result.log|awk '{print $9}' /mnt/main_check_result.log [root@kevin ~]# vim /root/main_check_result.log_del.sh #!/bin/bash size=$(ls -l /mnt/main_check_result.log|awk '{print $5}') file=$(ls -l /mnt/main_check_result.log|awk '{print $9}') if [ $size -gt 61865984 ] ; then echo $file; echo $size echo >$file fi [root@kevin ~]# chmod 755 /root/main_check_result.log_del.sh [root@kevin ~]# crontab -e 0 1 * * 6 /bin/bash -x /root/main_check_result.log_del.sh >/dev/null 2>&1
*************** 当你发现自己的才华撑不起野心时,就请安静下来学习吧!***************