我想订阅一个 inotify 风格的守护进程,以便在给定文件系统上的可用空间低于一定百分比时收到通知。这可能吗?
这是一种基于事件的机制。我没有长时间运行它,所以不能保证它的稳定性。
这使用了一个名为 fanotify 的最新系统调用 API。可能需要 2.6.37 或更高版本的内核才能运行它(例如,EL5 就不可能)。如果您收到投诉,它无法编译,则可能是内核太旧了。
它编译为:
gcc -o 通知程序notifier.c
它的工作方式是这样的:-
./notifier /home/文件 /dev/shm/monit 10
论据如下:
这将设置监视器。文件系统上打开写入标志的每个关闭的文件句柄都会启动事件检查。
#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);
}
Run Code Online (Sandbox Code Playgroud)
从那里您可以使用 inotify 来监视要创建/删除的文件以了解结果。
要进行测试,请将阈值设置为您现在知道违反的阈值,然后触摸受影响的文件系统上的文件。您应该创建监视器文件。
显然,最好将监视器文件放在不在同一文件系统上的某个位置(/dev/shm 是一个好地方)。
| 归档时间: |
|
| 查看次数: |
7519 次 |
| 最近记录: |