1. 程式人生 > >Ubuntu: inotify遞迴監控檔案系統狀態

Ubuntu: inotify遞迴監控檔案系統狀態

參考:

inotify只能監控單層目錄變化,不能監控子目錄中的變化情況。所以只能遍歷目錄,將所有子目錄新增入監控列表

當所監控目錄超過8192時,導致too many open files, 兩種解決方案:
1:
  需要更改下列檔案數值大小:
      /proc/sys/fs/inotify/max_user_watches
                This specifies an upper limit on the number of watches that
              can be created per real user ID.
 但是這種方式在系統重啟後會被重置為8192

2: [推薦]
     vim /etc/sysctl.conf

           新增 fs.inotify.max_user_watches=[max_watch_number]

開機自啟:
    cp monitor_file_system.sh /etc/init.d
    cd /etc/init.d
    新增:
        update-rc.d monitor_file_system.sh defaults'
    刪除: 
        update-rc.d -f monitor_file_system.sh remove
使用:
    service monitor_file_system { start | stop | restart | status }
    /etc/init.d/monitor_file_system { start | stop | restart | stauts }



#!/bin/bash
### BEGIN INIT INFO
#
# Provides:	 
[email protected]
# Required-Start: $local_fs $remote_fs # Required-Stop: $local_fs $remote_fs # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: initscript # Description: 刪除監控資料夾中檔案所帶\r # ### END INIT INFO #Author: lzgabel PATH=/sbin:/usr/sbin:/bin:/usr/bin DAEMON=/usr/sbin/monitor_file_system/monitor_file_systemd . /lib/lsb/init-functions start() { status if [[ $? -ne 0 ]]; then return 1 else echo "Starting monitor_file_systemd..." $DAEMON fi return $? } stop() { status if [[ $? -eq 0 ]]; then return 1 else echo "Stopping monitor_file_systemd..." `ps -ef | grep "$DAEMON" | grep -v "grep" | awk '{print $2}' | xargs kill -9` if [[ $? -eq 0 ]]; then echo "Done." return 0 else return 1 fi fi } restart() { status if [[ $? -eq 0 ]]; then return 1 else echo "Stopping monitor_file_systemd..." stop echo "Restart monitor_file_systemd..." start return 0 fi } status() { ProCount=`ps -ef | grep "$DAEMON" | grep -v "grep" | awk '{print $2}' |wc -l` if [[ $ProCount -le 0 ]]; then echo "* : monitor_file_systemd is not running." return 0 else echo "* : monitor_file_systemd is running."; return 1 fi } case "$1" in 'start') start ;; 'stop') stop ;; 'restart') restart ;; 'status') status ;; *) echo "Usage: "$DAEMON" {start|stop|restart|status}" exit 1 ;; esac exit 0
/*************************************************************************
	> File Name: daemon.c
	> Author: lzgabel
	> Mail: [email protected]
	> Created Time: 2017年08月05日 星期六 20時19分55秒
    > 守護程序實時監聽檔案狀態,刪除檔案中所有\r

 ************************************************************************/

#include <stdio.h>
#include <sys/resource.h>
#include <signal.h>
#include <errno.h>
#include <fcntl.h>
#include <dirent.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/inotify.h>
#include <string.h>
#include <sys/epoll.h>
#include <unistd.h>
#include "ini.h"

#define EVENT_SIZE (sizeof(struct inotify_event))

static int WD_SIZE; //監聽事件個數
static char watch_directory[BUFSIZ]; //目錄

typedef struct wd_dir
{
    int     wd; //inotify_add_watch返回:Watch descriptor
    char    dirname[BUFSIZ]; //監控目錄絕對路徑
}*WD_DIR;

WD_DIR wd_array;
int wd_count = 0;  //事件發生個數

void 
init_daemon()
{
    pid_t               pid;
    struct rlimit       rl;
    struct sigaction    sa;
    unsigned int        i;
    umask(0);

    //建立子程序
    if((pid = fork()) < 0) {
         perror("fork error");
         exit(EXIT_FAILURE);
    } else if(pid > 0) {
        exit(EXIT_SUCCESS); //使父程序退出
    } 

    setsid();  //建立會話

    sa.sa_handler = SIG_IGN;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;
    sigaction(SIGHUP|SIGCHLD,&sa,NULL);

    //建立子程序避免獲取控制終端
    if((pid = fork()) < 0) {
         perror("fork error");
         exit(EXIT_FAILURE);
    } else if(pid > 0) {
        exit(EXIT_SUCCESS);
    }

    //修改目錄
    if (chdir("/") == -1) {
        perror("Can't change directory");
        exit(EXIT_FAILURE);
    }
    //獲取檔案描述符最大值
    getrlimit(RLIMIT_NOFILE,&rl);
    //關閉不需要的檔案描述符
    if(rl.rlim_max == RLIM_INFINITY)
        rl.rlim_max = 1024;
    for(i = 0; i < rl.rlim_max; ++i)
        close(i);
}

/**
 *   將當前目錄新增監聽列表,遍歷整個目錄,將當前目錄下子目錄入監控列表 
 */

void
add_watch(int watch_fd, char *dir, int mask)
{
    DIR             *odir;
    int             wd;
    struct dirent   *dirent;
    if ( (odir = opendir(dir)) == NULL ) {
        perror("opendir error");
        exit(EXIT_FAILURE);
    }

    wd = wd_array[wd_count].wd =  inotify_add_watch(watch_fd, dir, mask);
    strcpy(wd_array[wd_count++].dirname, dir);

    if (wd == -1) {
        perror("Couldn't add watch list");
        return;
    }

    while ((dirent = readdir(odir)) != NULL) {
        if (strcmp(dirent->d_name, "..") == 0 
            || strcmp(dirent->d_name, ".") == 0) {
                continue;
            }
        if (dirent->d_type == DT_DIR) {
            char *subdir = (char *)malloc(BUFSIZ*sizeof(char));
            sprintf(subdir, "%s/%s", dir, dirent->d_name);
            add_watch(watch_fd, subdir, mask);
            free(subdir);
        } 
        /*處理已存在檔案
       if (dirent->d_type == DT_REG )
        { 
            FILE *fp;
            char     *file_name = (char *)malloc(BUFSIZ*sizeof(char));
            char     *cmd_string = (char *)malloc(BUFSIZ*sizeof(char));
            sprintf(file_name, "%s/%s", dir, dirent->d_name);
            sprintf(cmd_string, "sed -i \"s/\\r//g\" %s", file_name);
	    fp = popen(cmd_string, "r");
            pclose(fp);
        }
        */
    }
    closedir(odir);
    return;
}

/**
 *  獲取檔案/目錄的父目錄絕對路徑 
 */

char *
get_absolute_path(struct inotify_event *event)
{
    int     i;
    char    *dir = (char *)malloc(BUFSIZ*sizeof(char));

    for(i = 0; i < wd_count; i++) {
        if (wd_array[i].wd == event->wd) {
            strcpy(dir ,wd_array[i].dirname);
            break;
        }
    }
    return dir;
}

/**
 * 將子目錄新增進入監聽列表
 */

void 
append_subdir(int watch_fd, struct inotify_event *event, int mask)
{
    char    *dir = (char *)malloc(BUFSIZ*sizeof(char));
    char    *subdir = (char *)malloc(BUFSIZ*sizeof(char));

    dir = get_absolute_path(event);
    sprintf(subdir, "%s/%s", dir, event->name);
    add_watch(watch_fd, subdir, mask);
    free(dir);
    free(subdir);
    return;
}

/**
 *  將刪除資料夾移除監聽列表
 */

void 
remove_dir(int watch_fd, char *dir)
{
    int         i;
    for (i = 0; i < wd_count; i++) {
        if (strcmp(dir, wd_array[i].dirname) == 0) {
            inotify_rm_watch(watch_fd, wd_array[i].wd);
            return;
        }
            
    }
    return;
}

/**
 *  監聽目錄等待事件觸發
 */

void
watch_dir(int watch_fd, int mask)
{
    int     length, i;
    char    buffer[BUFSIZ];
   /*
    * read從inotify的檔案描述符中讀取事件,從而判定發生了那些事件。若讀取之時還沒有發生任何事件,則read會阻塞指導事件發生
    */
    length = read(watch_fd, buffer, BUFSIZ);
    if (length == -1) {
        perror("read error !");
        exit(EXIT_FAILURE);
    }

    for (i = 0; i < length; ){
        struct inotify_event *event = (struct inotify_event *) &buffer[i];  //event->name是引發事件的檔名, 並不是完整路徑
        if (event->len) {
            if (event->mask & IN_CREATE) {
                FILE * FP = fopen("/tmp/file.log" , "a+");
                if (event->mask & IN_ISDIR) {
                    char     *dir = (char *)malloc(BUFSIZ*sizeof(char));
                    dir = get_absolute_path(event);
                    fprintf(FP, "Directory [%s] was created in directory [%s]\n", event->name, dir);
                    append_subdir(watch_fd, event, mask);
                } else {
                    pid_t    cpid;
                    if ((cpid = fork()) < 0) {
                        perror("fork error");
                        exit(EXIT_FAILURE);
                    } else if (cpid == 0) {
                        FILE     *fp;
                        char     *file_name = (char *)malloc(BUFSIZ*sizeof(char));
                        char     *cmd_string = (char *)malloc(BUFSIZ*sizeof(char));
                        char     *dir = (char *)malloc(BUFSIZ*sizeof(char));
                        dir = get_absolute_path(event);
                        if (strncmp(event->name, "sed", 3) == 0)
                            exit(EXIT_SUCCESS);
                        sprintf(file_name, "%s/%s", dir, event->name);
                        sprintf(cmd_string, "sed -i \"s/\\r//g\" %s", file_name);
                        fp = popen(cmd_string, "r");
                        fprintf(FP, "File [%s] was created in directory [%s]\n", event->name, dir);
                        pclose(fp);
                        free(dir);
                        free(file_name);
                        free(cmd_string);
                        exit(EXIT_SUCCESS);
                    }

                }
                fclose(FP);
            } else if (event->mask & IN_DELETE) {
                FILE * FP = fopen("/tmp/file.log" , "a+");
                if (event->mask & IN_ISDIR) {
                    char    *dir = (char *)malloc(BUFSIZ*sizeof(char));
                    char    *subdir = (char *)malloc(BUFSIZ*sizeof(char));
                    dir = get_absolute_path(event);
                    sprintf(subdir, "%s/%s", dir, event->name);
                    remove_dir(watch_fd, subdir);
                    fprintf(FP, "\033[41;37mDirectory [ %s ] was deleted from directory [ %s ] \033[0m\n", event->name, dir);
                    free(dir);
                } else {
                    char    *dir = (char *)malloc(BUFSIZ*sizeof(char));
                    dir = get_absolute_path(event);
                    fprintf(FP, "\033[41;37mFile [ %s ] was deleted from directory [ %s ] \033[0m\n", event->name, dir);
                    free(dir);
                }
                fclose(FP);
            }
        }
        i += EVENT_SIZE + event->len;
    }
    return;
}

/**
 *   監聽初始化
 */

int 
watch_init(char *root, int mask) 
{
    int     fd;
    if ((fd = inotify_init()) < 0) {
        perror("inotify_init error");
        exit(EXIT_FAILURE);
    } 
    add_watch(fd, root, mask);
    return fd;
}

static int handler(void* user, const char* section, const char* name,
                  const char* value)
{
    if(strncmp(name, "watch_directory", 15) == 0)
        strcpy(watch_directory, value);
    if(strncmp(name, "WD_SIZE", 7) == 0) {
        WD_SIZE = atoi(value);
        wd_array = (WD_DIR)malloc(sizeof(WD_DIR)*WD_SIZE);
    }
    return 1;
}

int
main(int argc,char *argv[])
{
    int                watch_fd;
    int                error;
    int                mask=IN_CREATE|IN_DELETE;
    init_daemon();
    error = ini_parse("/usr/sbin/monitor_file_system/monitor_file_systemd.conf", handler, NULL);
    if (error < 0) {
        perror("Can't read config file");
        exit(EXIT_FAILURE);
    }
    else if (error) {
        perror("Bad config file !");
        exit(EXIT_FAILURE);
    }
    // daemone(0,0); 系統呼叫
    watch_fd = watch_init(watch_directory, mask);
    for (;;) {
            watch_dir(watch_fd, mask);
    }
    exit(EXIT_SUCCESS);
}


相關推薦

Ubuntu: inotify監控檔案系統狀態

參考: inotify只能監控單層目錄變化,不能監控子目錄中的變化情況。所以只能遍歷目錄,將所有子目錄新增入監控列表 當所監控目錄超過8192時,導致too many open files, 兩種解決方案: 1:   需要更改下列檔案數值大小:      /p

記錄一個讀取linux系統檔案路徑的方法

入參為要查詢的路徑,返回所有檔案的路徑列表:    public static List<File> getAllFile(String path) throws Exception {     

linux inotify 監控檔案系統事件(incron,基於事件驅動的cron- )

原文地址: http://www.51know.info/system_security/inotify.html 1. Inotify 機制概述 1.1. Inotify 介紹 在日常的運維過程中,經常需要備份某些檔案,或者對系統的某些檔案進行監控,比如重要的

在macos系統刪除檔案或目錄…

今天想刪除.svn用git做版本管理,因為只有自己一個人,用.svn太麻煩,發現git還好用,特別是對個人而然。但是要刪除.svn真的很麻煩,特別是在macos下,檔案都是隱藏的,要開啟隱藏比較麻煩。 注意:需要開啟終端,輸入sudo -s,並輸入密碼,才能看到隱藏檔案。 如果用svn管理程式碼時,會

C# 將圖片匯出Excel(包括 建立Excel 、檔案壓縮、刪除檔案及資料夾)

新增引用 using ICSharpCode.SharpZipLib.Zip;   public void CreateDirectory(string DirectoryPath) { if (!Directory.Exist

查詢檔案及其子檔案(需傳入一棵樹和id)

首先明確大致的思路: 1.已知的資料有整棵樹 和 要刪除資料的id 2.根據id能夠查到其在 樹中對應的List(需遍歷) 3.找到List後確定要刪除List的children(treeNode.getId()==id) 4.判斷找到的treeNode是否有chil

Java讀取檔案路徑下所有檔名稱並儲存為Txt文件

本文用遞迴的方法實現讀取一個路徑下面的所有檔案並將檔名稱儲存到Txt檔案中,親測可用。 遞迴讀取檔案路徑下的所有檔案: /** * 遞迴讀取檔案路徑下的所有檔案 * * @param path * @param fileNameList

php掃描檔案刪除檔案

掃描檔案: <?php function scanMyDir($path){ // 開啟目錄 $dh = opendir($path); echo $path; echo '<ul>'; // 迴圈讀取目錄 while(($file = readdir($dh)

node建立檔案

node 遞迴建立檔案 function mkdir(fileString,cb){ let f_ary = fileString.split('/'); let index =0; fun

python watchdog:監控檔案系統事件的Python庫

watchdog.events.FileSystemEventHandler() 事件處理器的基類,用於處理事件,使用者需繼承該類,並在子類中重寫對應方法。 類例項方法如下: self.dispatch(event) 接收到一個事件後,通過該方法來決定該event由下面哪個方法

統計檔案個數--python

#coding=utf-8 ''' Created on 2015-06-17 @author: xhw ''' import os class CountFile: """統計檔案個數""

node js 刪除 檔案, 目錄

var fs = require(‘fs’); var rootFile = ‘e:/luo/dist’; //要刪除的資料夾 url //刪除所有的檔案(將所有資料夾置空) var emptyDir = function(fileUrl) {

Ubuntu 16.04 64位 檔案系統system.img生成命令make_ext4fs報錯

報錯提示: make_ext4fs: error while loading shared libraries: libstdc++.so.6: cannot open shared object f

Python查詢檔案(os.path, fnmatch,glob)

#!/usr/bin/env python #coding=utf8 import os.path import fnmatch import glob def recursiveSearchFiles(dirPath, partFileInfo): file

Ubuntu無法掛載Windows(ntfs)檔案系統

原文地址: 原因: 由於新版Windows自帶快速啟動, 所以它在預設的關機下並不會真的關機, 而是進入休眠模式,並且佔用著它的檔案系統。 而Ubuntu開啟ntfs系統的 ntfs-3g

shell刪除檔案或者目錄

shell遞迴刪除指定字串檔案或者目錄: 1、檔案: find . -name "*.rej" | xargs rm -rf 2、目錄: find . -type d -name "*.rej" | xargs rm -rf

Java之展示檔案目錄結構

通過遞迴函式,展示某個檔案下目錄結構public class DirectorList { private static Scanner sc; public static void main(String[] args) { String route = getR

java刪除檔案

/** * @author yzh * @date 2018年4月26日 14:52:12 * @description 遞迴刪除資料夾下所有目錄和檔案 */public static void delDir(File f) {      if(f.isDirectory()

刪除檔案和刪除資料夾

<?php $path = "F:/software/phpStudy/WWW/ico_web/node_modules/"; /* 自定義的刪除函式,可以刪除檔案和遞迴刪除資料夾 scandir() 返回指定目錄中的檔案和目錄的陣列。 */ function m

Ubuntu硬碟分割槽/格式化/掛載檔案系統各種應用

Ubuntu更新了很多版本更新,我本人認為Ubuntu硬碟很好使的檔案系統,在此向大家推薦。如今技術不斷更新,各種使用檔案都已經淘汰。我認為還是有很不錯的如Ubuntu硬碟值得大家來運用。Ubuntu 硬碟操作參考. 一、檢視Ubuntu硬碟上的狀態 硬碟上有些什麼、檔案們都有多大,在有些時候我們是