我写的shell都是依照自己很浅薄的现学的知识去写的,好多时候写完了博客,去查找答案,会发现很多更效率更好的答案。写博客是激励我自己能坚持下去,让我的头脑不去懈怠,望共勉。
题目:
创建一个send_mail.sh脚本,检测某项目log文件,检测当日是否有error信息,如果有,检测该error的行号是否存储在send_mail目录下的当日的log文件中,如果没有存储,则使用邮箱发送error信息到指定邮箱,并追加记录下已发送的错误行号到err_line。
知识点:
- 邮件发送系统
我本身使用的是deepin系统,安装的mutt + msmtp,配置起来相对简单一些。
# 傻瓜式安装
apt-get install mutt msmtp
# 创建root用户配置文件
# muttrc配置
vim /root/.muttrc
set sendmail="/usr/bin/msmtp"
set use_from=yes
set realname="name"
set [email protected]
set envelope_from=yes
# 创建日志文件
touch /root/.msmtp.log
# msmtp配置
vim /root/.msmtprc
# Set default values for all following accounts.
defaults
account 163
host smtp.163.com
from [email protected]
auth login
user [email protected]
password password # 注意,这里要写邮箱设置里的客户端授权密码
logfile /root/.msmtp.log
# Set a default account
account default : 163
# 都保存后,测试是否正常
msmtp -S
# 测试邮件是否可以发送,没收到不要急,可以去自己邮箱查看是否因内容原因被当垃圾邮件退回了,正常内容是可以发送的。
echo "test" | mutt -s 'test' [email protected]
- 检测文件中的error信息,并获取行号和信息
# 检测日志中带字符串error的行号
# grep 的 -n参数可以获取到带行号的错误信息 cut用:分割,获取第一行的,就是所有行号
line_num=grep -n 'error' $filename | cut -d':' -f 1
把行号变成数组形式,这块真的不太会,所以用的最笨的遍历
arr=() # ${#arr[@]} 获取数组元素个数
for i in $line_num
do
arr[${#arr[@]}]=$i
done
- 获取今天的已经发送过的错误行号
# 先判断有没有该文件,没有则创建
# 并判断昨天有没有文件,有的话删除
if [ -e $filename ]
then
# 处理
fi
# 获取内容
data=$(cat $filename)
4.对比已发送过的错误行号 (搞完感觉这样不太对,双重遍历太费劲,之后我修改成,遍历用逗号连接已经发送的行号,在第二步查找错误信息的时候,用sed 'd’去过滤已经发送过的,能省事很多很多)
# 双重遍历两组数据
# 相同的,就把该元素删除。 然后我数组里的元素就不知道为啥丢了。。。
unset arr[$j]
# 改成
arr[$j]=''
- 判断数组为空,则直接exit。否则查找错误,拼接成内容发送邮件
str=''
for i in arr
do
error=`sed -n "${arr[k]}p` $filename | grep 'error'`
# 错误行号存入已发送文件里
echo -e ${error_line}'\n' >> $send_mail_log
str=${str}${error}'\n'
done
# 判断str是否为空,为空则直接echo无错误,exit退出
# 发送邮件
echo -e $str | mutt -s "xxx项目"`date +"%Y-%m-%d最新错误信息` ‘[email protected]’
改进:
# ==========================
第二部可以改成,先获取已发送的行号,逗号拼接,然后检索
str=''
for i in sended_lines
do
str=${str}${i}','
done
# 删除最后个逗号
str=${str%,*}
error_message = nl $filename | sed "$strd" | grep 'error' # 这个就是所有错误信息
nl $filename | sed "$strd" | grep 'error' | awk '{print $1}' >> sended_lines.log # 这里直接就导入了行号
# ===============