Скрипт проверки целостности файлов (хешами SHA-256)

Приведу пример Python скрипта который считает хеши SHA-256 всех файлов в указанной директории и сообщает на email список файлов которые изменились, создались или удалились, а также записывает в log файл.

Скрипт я запускал на Ubuntu Server, по этому убедимся что установлен python3:

python3 --version
apt install python3 python3-pip

Понадобилось однажды следить за состоянием www файлов, по этому сделал такой скрипт:

#!/usr/bin/env python3
import os
import hashlib
import json
import time
import subprocess

WATCH_DIR = "/var/www"
HASH_DB = "/root/www_hashes.json"
LOG_FILE = "/root/www_changes.log"
EMAIL_TO = "root"
EMAIL_SUBJECT = "FILE MODIFIED"
EXCLUDE_FILES = [
    "/var/www/logs/1.log",
    "/var/www/logs/2.log",
]

def file_hash(path):
    sha = hashlib.sha256()
    try:
        with open(path, "rb") as f:
            for chunk in iter(lambda: f.read(4096), b""):
                sha.update(chunk)
        return sha.hexdigest()
    except Exception:
        return None


def load_db():
    if os.path.exists(HASH_DB):
        with open(HASH_DB, "r") as f:
            return json.load(f)
    return {}


def save_db(db):
    with open(HASH_DB, "w") as f:
        json.dump(db, f, indent=2)


def scan():
    hashes = {}
    for root, dirs, files in os.walk(WATCH_DIR):
        for name in files:
            path = os.path.join(root, name)
            if path in EXCLUDE_FILES:
                continue
            h = file_hash(path)
            if h:
                hashes[path] = h
    return hashes


def log_changes(changes):
    if not changes:
        return
    timestamp = time.strftime("%Y-%m-%d %H:%M:%S")
    with open(LOG_FILE, "a") as f:
        f.write(f"\n[{timestamp}] Changes:\n")
        for line in changes:
            f.write(line + "\n")


def send_email(changes):
    if not changes:
        return
    body = "\n".join(changes)
    try:
        proc = subprocess.Popen(
            ["/usr/sbin/sendmail", EMAIL_TO],
            stdin=subprocess.PIPE
        )
        proc.communicate(input=f"Subject: {EMAIL_SUBJECT}\n\n{body}".encode("utf-8"))
        print("[EMAIL] notification sent")
    except Exception as e:
        print("[EMAIL ERROR]:", e)


def main():
    old_hashes = load_db()
    new_hashes = scan()
    changes = []

    for path, new_h in new_hashes.items():
        old_h = old_hashes.get(path)
        if old_h and old_h != new_h:
            changes.append(f"File modified: {path}")

    for path in old_hashes:
        if path not in new_hashes:
            changes.append(f"File deleted: {path}")

    for path in new_hashes:
        if path not in old_hashes:
            changes.append(f"New file: {path}")

    if changes:
        log_changes(changes)
        send_email(changes)

    save_db(new_hashes)


if __name__ == "__main__":
    main()

Сделаем файл исполняемым и запустим, на NVMe рейдах подсчет делается очень быстро, чем больше размер файла, тем дольше, если файлов десятки тысяч и они маленькие, то это займет секунды:

chmod +x ixnfo.com.py
./ixnfo.com.py

Осталось добавить в cron, например ежедневно в 7 утра:

02 7 * * * root /dir/ixnfo.com.py > /dev/null 2>&1

Смотрите также мои статьи:
Использование и настройка CRON
Скрипт проверки целостности файлов (size+mtime)
Скрипты

Оставьте комментарий

Добавить комментарий