需求简介:

由于服务器被挂马,经常被写入涉敏感的html网页,领导时常被网监请去喝茶,呵呵你懂的。所以有两个需求,一是找出服务器的木马后门和修复代码漏洞,二是监控服务器涉及增删改查的文件。

第一个不在此次探讨行列,故只说第二个需求。

  inotify简介:

Inotify 是一个 Linux特性,它监控文件系统操作,比如读取、写入和创建。Inotify 反应灵敏,用法非常简单,并且比 cron 任务的繁忙轮询高效得多。学习如何将 inotify 集成到您的应用程序中,并发现一组可用来进一步自动化系统治理的命令行工具。(来自百度百科inotify

  inotify-tools是简化使用inotify服务的一种工具。

以下,我们开始安装inotify-tools。

  服务器系统:centos 6.5
  文件目录:/data/rise
  实现目的:当/data/rise目录下任何文件发生变化时,记录日志并保存。
 
  具体操作:
 

一、安装inotify-tools工具
 
1、查看服务器内核是否支持inotify服务
 
  命令:ll /proc/sys/fs/inotify   #列出文件目录,出现下面内容,说明服务器支持
 
 
备注:Linux下支持inotify的内核最小为2.6.13,可以输入命令 [ uname -a ] 查看,centOS 5.x 内核为2.6.32,默认已经支持inotify
 
 
2、安装inotify-tools工具
 
  1. yum install make gcc gcc-c++ #安装编译工具
 
  inotify-tools下载地址:点我下载
 
  上传inotify-tools-3.14.tar.gz到/usr/local/src目录下。

  1. cd /usr/local/src
  2.  
  3. tar -zxvf inotify-tools-3.14.tar.gz #解压
  4.  
  5. cd inotify-tools-3.14 #进入解压目录
  6.  
  7. ./configure --prefix=/usr/local/inotify #配置
  8.  
  9. make #编译
  10.  
  11. make install #安装
 
3、设置环境变量
 
  1. echo "PATH=/usr/local/inotify/bin:$PATH" >>/etc/profile.d/inotify.sh
  2.  
  3. source /etc/profile.d/inotify.sh #使设置立即生效
  4.  
  5. echo "/usr/local/inotify/lib" >/etc/ld.so.conf.d/inotify.conf
  6.  
  7. ln -s /usr/local/inotify/include /usr/include/inotify
 
4、修改inotify默认参数(inotify默认内核参数太小)
  1. 执行以下命令查看结果:
  2.  
  3. sysctl -a | grep max_queued_events #结果是:fs.inotify.max_queued_events =
  4.  
  5. sysctl -a | grep max_user_watches #结果是:fs.inotify.max_user_watches =
  6.  
  7. sysctl -a | grep max_user_instances #结果是:fs.inotify.max_user_instances =
  8.  
  9. #修改上述参数为下列值
  10.  
  11. sysctl -w fs.inotify.max_queued_events=""
  12.  
  13. sysctl -w fs.inotify.max_user_watches=""
  14.  
  15. sysctl -w fs.inotify.max_user_instances=""
  16.  
  17. #修改方法
  18.  
  19. vi /etc/sysctl.conf #添加以下代码
  20.  
  21. fs.inotify.max_queued_events=
  22.  
  23. fs.inotify.max_user_watches=
  24.  
  25. fs.inotify.max_user_instances=
  26.  
  27. wq! #保存退出
参数说明:
 
max_queued_events:

inotify队列最大长度,如果值太小,会出现"** Event Queue Overflow **"错误,导致监控文件不准确
 
 
 
 
 
 
max_user_watches:
  要同步的文件包含多少目录,可以用:find /data/rise -type d | wc -l 统计,必须保证max_user_watches值大于统计结果(这里/data/rise为同步文件目录)
 
max_user_instances:
  每个用户创建inotify实例最大值
 
二、创建实时脚本(可跳过走第三步)
 
  1. mkdir -p /home/inotify #创建目录
  2.  
  3. vim /home/inotify/inotif.sh #编辑并添加以下内容
  4.  
  5. #!/bin/sh
  6. /usr/local/inotify/bin/inotifywait -mrq -e modify,create,move,delete --fromfile '/home/inotify/excludedir' --timefmt '%y-%m-%d %H:%M' --format '%T %f %e'
  7. /data/rise/ >> /tmp/rsync.txt
  8.  
  9. wq! #保存退出
  10.  
  11. vim /home/inotify/excludedir #编辑并添加以下内容
  12.  
  13. /data/rise/ #要监控的目录
  14. @/data/rise/cache/ #要排除监控的目录
  15.  
  16. wq! #保存退出
  17.  
  18. chmod +x /home/inotify/inotif.sh #添加执行权限
  19.  
  20. vim /etc/rc.d/rc.local #编辑并在最后一行添加以下内容,开机自动启动
  21.  
  22. sh /home/inotify/inotif.sh
  23.  
  24. wq! #保存退出
  25.  
  26. reboot重启生效
三、直接使用手动执行命令(不想创建脚本可以走这一步)
 
切换到有inotifywait的目录下或直接在命令中添加文件路径。
 
命令如下:
  1. /usr/local/inotify/bin/inotifywait -m -r -d -o /tmp/file_change.log --timefmt '%F %T' --format '%T %w%f %e' -e close_write -e create /data/riseweb/ @/data/riseweb/data/ @/data/riseweb/riseimg/

命令解析:

  1. /tmp/file_change.log 是日志路径,生成的日志写在这里面。
  1. /data/riseweb/ 是监控的文件目录,后面两个@是要排除监控的目录。

四、使用PHP脚本监测并发送邮件

实现思路:

在/tmp文件夹下新建一个row_mark.txt的文件,用来保存上一次的file_change.log的最后行数,在crontab中定时执行php脚本,获取file_change.log的最后行数,与row_mark文件最后保存的行数做对比,数字一致,说明没有新增操作日志。不一致,说明有新增操作日志,读取新行数与旧行数之间的日志内容,排版发送邮件,并把新行数写入row_mark.txt文件。

实现的php脚本代码:

  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: jimmyRen
  5. * Date: 16/10/24
  6. * Time: 下午1:56
  7. * 主要作用:检查服务器项目目录下是否有新建文件或文件夹,如果有,发送邮件通知
  8. * 实现思路:服务器如有新建文件,inotify会写在/tmp/file_change.log里,打开文件,获取最后一行的行数,如果大于0或大于上一次保存的行数,则追加写进行数文件中,并发送邮件通知
  9. */
  10.  
  11. require_once(dirname(__FILE__)."/include/common.inc.php");
  12. date_default_timezone_set("PRC");
  13. $url = '/tmp/';
  14. //打开日志文件
  15. $change_log = file_get_contents($url.'file_change.log');
  16. //打开记录行数的文件
  17. $row_log = file_get_contents($url.'row_mark.log');
  18. //将文件以每行转换成数组
  19. $change_array = explode("\n",$change_log);
  20. $row_array = explode("\n",$row_log);
  21. //获取数组的总长度
  22. $change_count = count($change_array);
  23. $row_count = count($row_array);
  24. //获取日志文件最后一行的key[行数]
  25. $change_row = $change_count - 2;
  26. //获取行数文件最后一行的值
  27. $row_value = substr($row_array[$row_count-1],0,strpos($row_array[$row_count-1],"["));
  28.  
  29. $row_date = date("Y-m-d H:i:s",time());
  30. if($change_row > 0 && $row_log== ""){//第一次写行数日志
  31. $file_write = file_put_contents($url.'row_mark.log',$change_row."[".$row_date."]",FILE_APPEND);
  32. echo "首次写入记录成功";exit;
  33. }elseif($change_row > 0 && $change_row > $row_value){
  34. $file_write2 = file_put_contents($url.'row_mark.log',"\n".$change_row."[".$row_date."]",FILE_APPEND);
  35. }else{
  36. echo "当前时间".date("Y-m-d H:i:s", time())." 没有新写入的文件";
  37. exit;
  38. }
  39.  
  40. //有新写入的行数,把日志新写入的内容循环取出来,生成文件,然后发送email
  41. if($file_write2){
  42. ini_set("memory_limit","512M");
  43. $new_array = array();
  44. for($i = $row_value;$i<$change_row;$i++){
  45. $new_array[] = "\n\r\n".$change_array[$i];
  46. }
  47. //把拿到的数组转换成行数格式的字符串
  48. $text = implode("\n\r\n",$new_array);
  49. $file_time = date("Y-m-d_H:i");
  50. //把内容生成文件
  51. $file = fopen($url."checkChangeLog".$file_time.".txt","w+");
  52. if($file){
  53. iconv("UTF-8","GB2312//IGNORE",$text);
  54. $write = fwrite($file,$text);
  55. }
  56. fclose($file);
  57.  
  58. //发送邮件
  59. function sendmail($email, $mailtitle, $mailbody)
  60. {
  61. global $cfg_sendmail_bysmtp, $cfg_smtp_server, $cfg_smtp_port, $cfg_smtp_usermail, $cfg_smtp_user, $cfg_smtp_password, $cfg_adminemail,$cfg_webname;
  62. if($cfg_sendmail_bysmtp == 'Y' && !empty($cfg_smtp_server))
  63. {
  64. $mailtype = 'TXT';
  65. require_once(DEDEINC.'/mail.class.php');
  66. $smtp = new smtp($cfg_smtp_server,$cfg_smtp_port,true,$cfg_smtp_usermail,$cfg_smtp_password);
  67. $smtp->debug = false;
  68. if(!$smtp->smtp_sockopen($cfg_smtp_server)){
  69. ShowMsg('邮件发送失败,请联系管理员','-1');
  70. exit();
  71. }
  72. $smtp->sendmail($email,$cfg_webname,$cfg_smtp_usermail, $mailtitle, $mailbody, $mailtype);
  73. }else{
  74. @mail($email, $mailtitle, $mailbody, $headers);
  75. }
  76. }
  77.  
  78. $email = "906691xxx.qq.com"; //这里填写要发送到的邮箱
  79. $mailtitle = date("Y-m-d H:i", time())." rise文件写入情况";
  80. $mailbody = $text;
  81. sendmail($email, $mailtitle, $mailbody);
  82. echo "脚本执行成功!";exit;
  83.  
  84. }

tip:记得加载发送邮件的class。

五、crontab定时任务

  要求是每天的0 - 7点,每5个小时执行一次,7 - 21点,每1个小时执行一次,21 - 23点,每2个小时执行一次,故crontab脚本命令如下。

  1. #定时检查服务器文件写入情况并发送邮件通知
  2. -/,-/,-/ * * * php /data/rise/checkfile.php

六、总结

需求肯定是实现了,由于不是专业的运维,本次只是实现了需求,大神们有更好的方法可交流探讨。

  1.  

inotify-tools + php脚本实现Linux服务器文件监控并邮件提醒的更多相关文章

  1. nmon脚本——对Linux服务器的监控

    继服务器被挖之后,我又开拓了另一个监控工具----nmon! Nmon可以很轻松的监控系统的CPU.内存.网络.硬盘.文件系统.NFS.高耗进程.资源和IBM Power系统的微分区的信息,还有专属的 ...

  2. Python 脚本实现对 Linux 服务器的监控

    本文来自我的github pages博客http://galengao.github.io/ 即www.gaohuirong.cn 摘要: 原文地址 由于原文来自微信公众号,并且脚本都是图片,所以这里 ...

  3. 用 Python 脚本实现对 Linux 服务器的监控

    目前 Linux 下有一些使用 Python 语言编写的 Linux 系统监控工具 比如 inotify-sync(文件系统安全监控软件).glances(资源监控工具)在实际工作中,Linux 系统 ...

  4. Linux 服务器系统监控脚本 Shell【转】

    转自: Linux 服务器系统监控脚本 Shell - 今日头条(www.toutiao.com)http://www.toutiao.com/i6373134402163048961/ 本程序在Ce ...

  5. Linux入门(五)linux服务器文件远程管理

     1 使用filezila远程管理linux服务器文件 filezila下载地址:https://filezilla-project.org/ filezila默认只能登录普通用户,如果想要root用 ...

  6. Shell脚本对Linux进行文件校验

    Shell脚本对Linux进行文件校验 一.需求 有客户等保需求对文件一致性进行校验,想到利用md5sum工具,因此写脚本来对文件进行自定义扫描,后期可以利用其进行校验,快速校验文件发现变更的文件,一 ...

  7. Inotify: 高效、实时的Linux文件系统事件监控框架

      Inotify: 高效.实时的Linux文件系统事件监控框架   概要 - 为什么需要监控文件系统? 在日常工作中,人们往往需要知道在某些文件(夹)上都有那些变化,比如:   通知配置文件的改变 ...

  8. Linux服务器上监控网络带宽的18个常用命令 zz

    Linux服务器上监控网络带宽的18个常用命令 本文介绍了一些可以用来监控网络使用情况的Linux命令行工具.这些工具可以监控通过网络接口传输的数据,并测量目前哪些数据所传输的速度.入站流量和出站流量 ...

  9. Linux服务器上监控网络带宽的18个常用命令和工具

    一.如何查看CentOS的网络带宽出口 检查维护系统的时候,经常会要查看服务器的网络端口是多大的,所以需要用到Linux的一个命令. 如何查看CentOS的网络带宽出口多大?可以用下面的命令来查看. ...

随机推荐

  1. 201521123088《java程序设计》第三周学习总结

    1. 本周学习总结 本周学习了关于Java的封装,所谓封装就是将属性私有化,提供公有的方法访问私有属性 2. 书面作业 代码阅读 public class Test1 { private int i ...

  2. [转载]请教各位高手光盘版或者U盘版的BT保存配置的问题

    这样安装的bt4默认是不能保存配置的,每次你更改了设置,下次重启又没有了.在网上下载一个叫做"saveFile.rar"的压缩包,大小40K左右,这个是bt4能够保存配置关键,当然 ...

  3. 201521123032 《Java程序设计》第10周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常与多线程相关内容. 2. 书面作业 本次PTA作业题集异常.多线程 1.finally 题目4-2 1.1 截图你的提交结果(出 ...

  4. Java:实现对象的比较 comparable接口和comparator接口

    在实际应用中,我们往往有需要比较两个自定义对象大小的地方.而这些自定义对象的比较,就不像简单的整型数据那么简单,它们往往包含有许多的属性,我们一般都是根据这些属性对自定义对象进行比较的.所以Java中 ...

  5. html css 前端基础 学习方法及经验分享

    前言: 入园第一天,想分享一点儿前端基础html css 的学习方法和一些经验给热爱前端,但是不知道从哪儿开始,依旧有些迷茫的新手朋友们.当然,适合每个人的学习方式不同,以下所讲的仅供参考. 一.关于 ...

  6. 如何使用IntelliJ IDEA的Favorites来管理项目中的常用代码

    http://www.cnblogs.com/deng-cc/p/6530279.html

  7. [06] Session实现机制以及和Cookie的区别

    1.为什么有Session和Cookie 根据早期的HTTP协议,每次request-reponse时,都要重新建立TCP连接.TCP连接每次都重新建立,所以服务器无法知道上次请求和本次请求是否来自于 ...

  8. Struts2配置文件复用代码【web.xml、struts.xml、常量配置】

    web.xml的分发器代码: <!-- 引入struts核心过滤器 --> <filter> <filter-name>struts2</filter-nam ...

  9. SQL知识点大纲图

    这是我整理出来的SQL大纲图.

  10. ToStringBuilder学习总结

    一.简介与引入   1.ToStringBuilder.HashCodeBuilder.EqualsBuilder.ToStringStyle.ReflectionToStringBuilder.Co ...