shell使用管道,配合awk,一句代码清空大于设定大小的日志文件

服务器上,多多少少都会有一些日志文件,nginx python等等诸如此类,运行时间一长,难免会遇到磁盘塞满的状况,由于缺乏适当的日志清空机制(nginx也许要写个脚本跑),这时候就需要手动去删除一部分日志腾出空间,但是对于我这种懒人,要管理这么多服务器,时不时就需要去清空下日志,简直受不了,于是了解了下管道和awk,自己尝试着写了个简单的shell脚本

不想看过程请直接跳到最后的解决方案

首先,我们需要列出这次需要考虑的几个问题

1.在sheel中如何声明变量并使用
2.管道是什么
3.AWK又是个什么
4.怎么在一句代码中进行判断和后续处理

在sheel中如何声明变量并使用

其实这个是一个很入门的东西了,不过这里也简单的提一下,shell中声明变量和大部分语言一样使用loli='yes'的方式进行声明,不过需要注意,等号前后不能有空格,还有一些常识,都列(fu)举(zhi)一下

命名只能使用英文字母,数字和下划线,首个字符不能以数字开头。
中间不能有空格,可以使用下划线(_)。
不能使用标点符号。
不能使用bash里的关键字(可用help命令查看保留关键字)。

如何使用呢?其实也很简单,echo $loli或者echo ${loli}都是可以的。

管道是什么

复制大神的话,管道命令操作符是:”|”,它仅能处理经由前面一个指令传出的正确输出信息,也就是 standard output 的信息,对于 stdandard error 信息没有直接处理能力。然后,传递给下一个命令,作为标准的输入 standard input.

是不是有点懵逼,简单地讲,管道就是将前一个命令的内容,传递给下一个命令,比如ps aux | grep python3,是不是很熟悉?ps aux可以输出当前所有正在运行的进程信息,这里通过管道的操作符|,将ps aux的标准输出,传递给了grep,grep是一个用于处理文本查找常用指令,这里就是使用grep筛选出来了包含python3字符串的列,只有符合这个列的数据才会打印出来。

比如ps aux输出如下内容:

root       868  0.0  0.1 301712 29452 ?        Sl   Oct16  21:25 python3 /home/main.py --port=12024
root       874  0.0  0.1 301712 29472 ?        Sl   Oct16  21:36 python3 /home/main.py --port=12025
xiaoc     1934  1.7  0.4 166536 79144 ?        S    Dec13 131:21 nginx: worker process                    
xiaoc     1935  1.7  0.5 170632 83944 ?        S    Dec13 130:57 nginx: worker process                    
xiaoc     1936  1.7  0.4 169608 81512 ?        S    Dec13 131:58 nginx: worker process                    
xiaoc     1937  1.8  0.4 170632 82336 ?        S    Dec13 132:37 nginx: worker process                    
xiaoc     1938  1.8  0.4 168584 81112 ?        S    Dec13 136:01 nginx: worker process                    
xiaoc     1939  1.7  0.4 168456 80736 ?        S    Dec13 131:41 nginx: worker process                    
xiaoc     1940  1.7  0.4 167560 80528 ?        S    Dec13 131:40 nginx: worker process                    
xiaoc     1941  1.7  0.4 167560 79752 ?        S    Dec13 131:07 nginx: worker process                    
xiaoc     1942  0.0  0.0 121992 15232 ?        S    Dec13   1:22 nginx: cache manager process             
root      3467  0.0  0.0      0     0 ?        S    12:28   0:00 [kworker/u8:1]
root      4884  0.0  0.0  46784  2852 tty1     S    Dec09   0:00 su root
root      4922  0.0  0.0  13740  3392 tty1     S+   Dec09   0:00 bash
root      5249  0.0  0.0  42240  2756 ?        S    12:30   0:00 /usr/sbin/CRON -f
root      5250  0.0  0.0  42240  2808 ?        S    12:30   0:00 /usr/sbin/CRON -f
root      5251  0.0  0.0  42240  2808 ?        S    12:30   0:00 /usr/sbin/CRON -f
root      5252  0.0  0.0  42240  2772 ?        S    12:30   0:00 /usr/sbin/CRON -f

那么ps aux | grep python3将会输出

root       868  0.0  0.1 301712 29452 ?        Sl   Oct16  21:25 python3 /home/main.py --port=12024
root       874  0.0  0.1 301712 29472 ?        Sl   Oct16  21:36 python3 /home/main.py --port=12025

AWK又是个什么

你只需要知道,AWK是一个超级强大的文本分析工具

awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大。简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理。

awk有3个不同版本: awk、nawk和gawk,未作特别说明,一般指gawk,gawk 是 AWK 的 GNU 版本。

awk其名称得自于它的创始人 Alfred Aho 、Peter Weinberger 和 Brian Kernighan 姓氏的首个字母。实际上 AWK 的确拥有自己的语言: AWK 程序设计语言 , 三位创建者已将它正式定义为“样式扫描和处理语言”。它允许您创建简短的程序,这些程序读取输入文件、为数据排序、处理数据、对输入执行计算以及生成报表,还有无数其他的功能。

怎么在一句代码中进行判断和后续处理

这就要借助强大的awk了,比如我们需要将当前目录下,超过102400字节的文件打印出来,那么就可以这样写

ls -la | awk '{if($5 > 102400) print $0}'

别急,这里简单的说一下awk干了什么,以及那个$5和$0又是个什么东西。

我们先是用了ls -la输出了当前所有文件和文件夹,然后使用管道(|)将输出的数据传递给了awk,由于awk是逐行处理,以空格为默认分隔符将每行切片,所以这里的$5就代表一行的第5个切片,$1就是第1个切片,可能会觉得疑问,索引不都是从0开始的吗?在awk里面比较特殊,$0是代表当前这一行的所有数据

也可以写成这样

max_length=1024000
ls -la | awk '{if($5 > '"$max_length"')  print $0}'

是不是看着有点懵逼,这个单引号双引号$max_length双引号单引号又是个什么鬼?

会产生这样的问题,是因为这里和平时用到的语言有点不太一样

比如平时需要将2个字符串相加,一般情况下是print "a" + "b",这样输出ab,然而在awk中,却是这样的

ls -la | awk '{print "a""b"}'
ls -la | awk '{print "a"+"b"}' //输出并不是ab

没错,在awk中,字符串之间不需要用+号连接起来,就像c#的$语法糖和python3.6的f语法糖一样,直接在字符串中写变量就好了,只是将{}变成了双引号。(感觉好像并没有讲懂,反正要在awk中用外部变量,这么用就对了)

现在判断做好了,然后需要怎么处理呢

现在就需要用到wak的system函数去调用shell命令

ls -la | awk '{if($5 > 102400)system("echo del file:" $9)}'

这样符合条件的文件,就会被打印出来,显示del file: xxxxx

同样的,我们使用

ls -la | awk '{if($5 > 102400)system("echo del file:" $9 "; echo \"\">"$9)}'

就可以直接将这个文件清空了!

最后我们再完善一下这句代码

cat dir_list.txt | awk '{system("ls -la " $1)}' | awk '{if($5 > '"$max_length"')system("echo file del:  " $9 "; echo \"\">"$9 )}'

这样就会直接读取当前目录下的dir_list.txt里面配置好的路径,然后判断并删除!
dir_list.txt文件示例如下

/tmp/xxx/xx/*.log.*
/var/log/mongodb/*.log
/var/log/xxx/*.log.*

最后的最后,再完善一下

max_length=1073741824
echo ''
df -h | awk '{if($1~/^\/dev/)print "dev:" $1 ", use:" $2"/"$3"("$5")"}'
echo ''
echo 'clear start'
echo '-----------------------------------------------------------------------'
cat dir_list.txt | awk '{system("ls -la " $1)}' | awk '{if($5 > '"$max_length"')system("echo file del:  " $9 "; echo \"\">"$9 )}'
echo '-----------------------------------------------------------------------'
echo 'clear end'
echo ''
df -h | awk '{if($1~/^\/dev/)print "dev:" $1 ", use:" $2"/"$3"("$5")"}'
echo ''

效果图

发表评论

电子邮件地址不会被公开。