Linux:在磁盘空间不足的情况下触发实时警报

Linux:在磁盘空间不足的情况下触发实时警报

我想订阅一个 inotify 风格的守护进程,当给定文件系统上的可用空间低于一定百分比时接收通知。这可能吗?

答案1

这是一种基于事件的机制。我还没有运行很长时间,所以不能保证它的稳定性。

这使用了一个非常新的系统调用 API,称为 fanotify。可能需要 2.6.37 或更高版本的内核才能运行它(例如,EL5 就不行)。如果您收到它无法编译的投诉,可能是内核太旧了。

它编译为:

gcc -o 通知程序 notifier.c

它的工作方式如下:-

./通知程序/home/文件/dev/shm/monit 10

参数如下:

  1. 您想要监控的文件系统上的文件。
  2. 如果超过阈值,则会创建文件的路径(如果低于阈值,则会被删除)
  3. 应低于阈值的可用空间百分比。

这将设置监视器。文件系统上每个已关闭且具有写入标志的文件句柄都会启动事件检查。

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <limits.h>
#include <linux/fanotify.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
#include <fcntl.h>

int main(const int argc, const char **argv) {
    if (argc < 4) {
        fprintf(stderr, "Supply a path to a file on the mountpoint to listen to, a monitor file and a free %% threshold..\n");
        exit(1);
    }

    if (access(argv[1], R_OK) < 0) {
        fprintf(stderr, "Unable to read file: %s\n", strerror(errno));
        exit(1);
    }

    int len, rc;
    unsigned char donestat = 0,  alerted = 0;
        const char *path = argv[1];
    const char *monpath = argv[2];
    int threshold = atoi(argv[3]);
    char buf[4096];
    struct fanotify_event_metadata *fem = NULL;
    int fan_fd = -1;
    uint64_t mask = FAN_CLOSE_WRITE;
    struct statvfs sfs;
    float bfree;

    memset(&sfs, 0, sizeof(sfs));
    unlink(monpath);

    if (threshold <= 0 || threshold >= 100) {
        fprintf(stderr, "Incorrect threshold provided");
        rc = 1;
        goto end;
    }

    fan_fd = fanotify_init(FAN_CLASS_NOTIF, FAN_CLOEXEC);
    if (fan_fd < 0) {
        perror("fanotify_init");
        rc = 1;
        goto end;
    }

    rc = fanotify_mark(fan_fd, FAN_MARK_ADD|FAN_MARK_MOUNT, mask, AT_FDCWD, path);
    if (rc < 0) {
        perror("fanotify_mark");
        rc = 1;
        goto end;
    }

    while ((len = read(fan_fd, buf, sizeof(buf))) > 0) {
        fem = (void *)buf;
        donestat = 0;

        while (FAN_EVENT_OK(fem, len)) {
            if (fem->vers < 2) {
                fprintf(stderr, "fanotify is too old\n");
                goto end;
            }

            if (!donestat) {
                rc = fstatvfs(fem->fd, &sfs);
                if (rc < 0) {
                    perror("fstatvfs");
                    rc = 1;
                    goto end;
                }
                bfree = 100 - (((float)(sfs.f_blocks - ((sfs.f_blocks - sfs.f_bfree))) / (float)(sfs.f_blocks)) * 100);
                if ((bfree < (float)threshold)) {
                    if (!alerted) {
                        creat(monpath, S_IRUSR|S_IWUSR);
                        alerted = 1;
                    }
                }
                else {
                    if (alerted) {
                        unlink(monpath);
                        alerted = 0;
                    }
                }
            }
            donestat = 1;
            close(fem->fd);
            fem = FAN_EVENT_NEXT(fem, len);
        }
    }
    if (len < 0) {
        perror("Read fan_fd");
        rc = 1;
        goto end;
    }

end:
    close(fan_fd);
    exit(rc);
}

从那里您可以使用 inotify 来监视要创建/删除的文件以了解结果。

要进行测试,请将阈值设置为您知道有时会超出的阈值,然后触摸受影响文件系统上的文件。您应该会创建监控文件。

显然,最好将监视文件放在不在同一文件系统的某个地方(/dev/shm 是个不错的位置)。

答案2

您可以使用监视实用程序为此。您可以设置检查间隔,但 60 秒是轮询的标准。

文件系统监控的配置如下:

check device root with path /
    if SPACE usage > 80% then alert

check device var with path /var
    if SPACE usage > 80% then alert

答案3

由于您要监控的东西会越来越多,您可能需要花一些时间学习 nagios。听起来您遇到了空间不足的情况,并且您不希望再次发生这种特定的故障。但系统可能会以意想不到的方式发生故障,并且所有服务都应该受到监控。

在紧急情况下,你可以使用插件。它们很容易安装,并且能做到它们所说的(check_disk 检查磁盘空间)。它们在失败时返回“非 0”。失败可能是警告、严重或未知的。

apt-get install nagios-plugins

在 crontab 中添加类似这样的内容将在失败时触发 $send_error。如果分区“/”的使用率超过 50%,则会触发该操作。

send_error="command you want to run on failure"
*/5 * * * *  /usr/lib/nagios/plugins/check_disk -w 50% -c 25% -p / || $send_error

相关内容