运维开发网

Shell中打印匹配关键字的前后行 [echo、grep用法]

运维开发网 https://www.qedev.com 2021-04-14 23:45 出处:51CTO 作者:80民工
在日常运维中,经常需要监控某个进程,并打印某个进程的监控结果,通常需要打印匹配某个结果的行以及其前后各N行。这里注意下:echo使用-e参数,对打印的结果中进行\n换行[[email protected] ~]# echo "abcd" abcd [[email protected] ~]# echo "ab\ncd" ab\ncd [[email protected] ~]# echo "ab \n

 

在日常运维中,经常需要监控某个进程,并打印某个进程的监控结果,通常需要打印匹配某个结果的行以及其前后各N行。

这里注意下:echo使用-e参数,对打印的结果中进行\n换行

[[email protected] ~]# echo "abcd"
abcd
[[email protected] ~]# echo "ab\ncd"
ab\ncd
[[email protected] ~]# echo "ab \n cd"
ab \n cd
[[email protected] ~]# echo -e "ab\ncd"
ab
cd
[[email protected] ~]# echo -e "ab \n cd"
ab 
 cd
[[email protected] ~]# echo -e "ab \n cd \n \n df"
ab 
 cd 
 
 df
 [[email protected] ~]# echo -e "ab\ncd \n \ndf"   
ab
cd 
 
df

echo的-n、-e参数:

1)echo -n 表示:不换行输出
[[email protected] ~]# echo "123"   
123
[[email protected] ~]# echo -n "123"
123[[email protected] ~]# 

2)echo -e 表示:处理特殊字符。若字符串中出现以下字符,则特别加以处理,而不会将它当成一般文字输出:
\a 发出警告声;
\b 删除前一个字符;
\c 最后不加上换行符号;
\f 换行但光标仍旧停留在原来的位置;
\n 换行且光标移至行首;
\r 光标移至行首,但不换行;
\t 插入tab;
\v 与\f相同;
\\ 插入\字符;
\nnn 插入nnn(八进制)所代表的ASCII字符;

[[email protected] ~]# echo "123\n456"
123\n456
[[email protected] ~]# echo -e "123\n456"
123
456

[[email protected] ~]# echo -e "wang\bkevin"
wankevin

echo后面跟双引号或单引号问题:

使用echo输出字符串时候,无论单引号还是双引号都是一样的。
如果字符串中有变量,单引号会忽略,而双引号会把变量解析以后带入字符串。
也就是说,echo后面的单引号就是一般输出,对引号里面的变量和特殊操作符号都不识别。 

echo后面跟双引号,双引号里能识别变量和特殊操作符号;
echo后面跟单引号,单引号里不会识别变量和特殊操作符号;

示例:
[[email protected] ~]# aa=123       
[[email protected] ~]# echo "${aa}" 
123
[[email protected] ~]# echo '${aa}'
${aa}

如下,将kill -9 `ps -ef|grep web_server|awk '{print $2}'`这条命令追加到web_script.sh脚本中,正确写法如下:
由于要保留kill命令后面``操作语句中的单引号和$2,所以单引号和$2前面都要加转义符\。
下面示例中echo后面加不加-e参数,效果都一样!
[[email protected] ~]# echo -e "kill -9 \`ps -ef|grep web_server|awk '{print \$2}'\`" >> 123.sh
[[email protected] ~]# cat 123.sh
kill -9 `ps -ef|grep web_server|awk '{print $2}'`

如果不加转移符号,则echo后面的双引号就会直接识别出``执行之后的结果,就将web_server的pid打印出来了
[[email protected] ~]# echo -e "kill -9 `ps -ef|grep web_server|awk '{print $2}'`" >> 123.sh
[[email protected] ~]# cat 123.sh
kill -9 9850

如果echo不使用双引号,使用单引号,则结果中会把$2内容给抹掉。
[[email protected] ~]# echo -e 'kill -9 `ps -ef|grep web_server|awk '{print $2}'`' >> 123.sh  
[[email protected] ~]# cat 123.sh
kill -9 `ps -ef|grep web_server|awk {print }`

如果echo使用单引号,在单引号里面使用双引号,如下,在echo的单引号里将awk后面的内容用双引号,则$2会保留。
但是awk后面必须是单引号才能正确print,awk后面跟单引号就没有意义了!
[[email protected] ~]# echo -e 'kill -9 `ps -ef|grep web_server|awk "{print $2}"`' >> 123.sh
[[email protected] ~]# cat 123.sh
kill -9 `ps -ef|grep web_server|awk "{print $2}"`

示例1

[[email protected] ~]# 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"的行
[[email protected] ~]# cat /opt/test |grep "main is failed"
It's so bad! main is failed!
It's so bad! main is failed!
[[email protected] ~]# 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行
[[email protected] ~]# 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行
[[email protected] ~]# 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行
[[email protected] ~]# 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中,并加上时间
[[email protected] ~]# echo -e "$(date)\n$(cat /opt/test|grep "main is failed" -B1)"> /root/result.log 
[[email protected] ~]# 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!

[[email protected] ~]# echo -e "$(date)\n$(cat /opt/test|grep "main is failed" -B1) \n" > /root/result.log
[[email protected] ~]# echo -e "$(date)\n$(cat /opt/test|grep "main is failed" -B1) \n" >> /root/result.log
[[email protected] ~]# echo -e "$(date)\n$(cat /opt/test|grep "main is failed" -B1) \n" >> /root/result.log
[[email protected] ~]# 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! 

[[email protected] ~]# 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
[[email protected] ~]# echo -e "$(date +%Y年%m月%d日) $(date +%A) $(date +%H时%M分%S秒)\n$(echo "今天是个好日子啊") \n" >> /root/result.log
[[email protected] ~]# echo -e "$(date +%Y年%m月%d日) $(date +%A) $(date +%H时%M分%S秒)\n$(echo "今天是个好日子啊") \n" >> /root/result.log
[[email protected] ~]# 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列表文件
[[email protected] ~]# 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进程状态的检查脚本:
[[email protected] ~]# 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 [email protected]$i "echo $i;sh /usr/bin/main_check"
done
 
[[email protected] ~]# 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
 
 
检查脚本执行结果
[[email protected] ~]# 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!
 
检查脚本执行结果的打印脚本
[[email protected] ~]# 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检查的结果文件内容
[[email protected] ~]# 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)时就清空。

[[email protected] ~]# ls -l /mnt/main_check_result.log
-rw-r--r--. 1 root root 16998 Nov 19  2017 /mnt/main_check_result.log

[[email protected] ~]# ls -l /mnt/main_check_result.log|awk '{print $5}'
16998

[[email protected] ~]# ls -l /mnt/main_check_result.log|awk '{print $9}'
/mnt/main_check_result.log

[[email protected] ~]# 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

[[email protected] ~]# chmod 755 /root/main_check_result.log_del.sh
[[email protected] ~]# crontab -e
0 1 * * 6 /bin/bash -x /root/main_check_result.log_del.sh >/dev/null 2>&1

扫码领视频副本.gif

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号