Skip to the content.

Link to the English language README page

Precizer — проверка контрольных сумм файлов в любом масштабе

Крошечное, высокопроизводительное приложение для проверки целостности файлов

«По-настоящему хорошая программа всегда поместится на дискету. Есть надежда, что кто-то всё ещё помнит, что это такое… Речь идёт не о дискетах, а о качественных программах!»© :-D

Unit Tests Code Coverage
System Tests Code Coverage

Precizer build & testing

КРАТКО

Обзор

precizer — крошечное и быстрое консольное приложение, полностью написанное на чистом Си. Предназначено для проверки целостности и сравнения файлов. Особенно полезно для проверки результатов синхронизации. Программа обходит дерево каталогов и создаёт базу данных файлов и их контрольных сумм с последующим быстрым сравнением.

precizer предназначен как для работы на embedded платформах, так и с файловыми системами гигантского размера на базе кластерных мейнфреймов. С помощью программы можно найти ошибки синхронизации, сравнивая данные с файлами и их контрольными суммами из разных источников. Также precizer можно использовать для исследования исторических изменений путём сравнения баз данных из одних и тех же источников, но за разное время.

Простой пример

Допустим, есть две машины, у которых в /mnt1 и /mnt2 соответственно примонтированы диски большого объёма с идентичным содержимым. Стоит задача побайтно проверить, действительно ли содержимое абсолютно идентично или есть различия.

  1. Запустить программу на первой машине с hostname, например «host1»:
precizer --progress /mnt1

В результате работы программы будут исследованы все директории, начиная с /mnt1, и в текущей директории будет создана база данных host1.db. Параметр --progress визуализирует прогресс и покажет объём пространства и количество исследуемых файлов.

  1. Запустить программу на второй машине с hostname, например «host2»:
precizer --progress /mnt2

В результате будет создана база данных host2.db в текущей директории.

  1. Скопировать файлы с базами данных host1.db и host2.db на одну из машин и запустить программу с соответствующими параметрами для сравнения:
precizer --compare host1.db host2.db

На экран будет выведена следующая информация:

Относительные пути в базе данных для сравнения

Следует обратить внимание, что precizer записывает в базу данных только относительные пути. Файл

/mnt1/abc/def/aaa.txt

из приведённого примера будет записан в базу данных как

abc/def/aaa.txt

без /mnt1. То же самое произойдёт с файлом

/mnt2/abc/def/aaa.txt

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

abc/def/aaa.txt

и с соответствующими контрольными суммами.

ТЕХНИЧЕСКИЕ ПОДРОБНОСТИ

Рассмотрим сценарий, когда имеется основное дисковое хранилище и его копия. Например, это может быть хранилище датацентра и его Disaster Recovery‑копия. Периодически происходит синхронизация с основного хранилища на резервное, но по причине огромных объёмов данных, скорее всего, синхронизация происходит не побайтно, а за счёт вычисления изменений среди метаданных файлов на файловой системе. В таких случаях учитывается размер файла и время модификации, но изменившееся содержимое байт за байтом не исследуется. В этом есть смысл, потому что между основным датацентром и резервным Disaster Recovery‑центром, как правило, хорошие каналы связи, но полная побайтовая синхронизация может занять нецелесообразно много времени. Такие инструменты, как rsync, позволяют производить синхронизацию по обеим методикам: как с учётом изменившихся файлов, так и побайтово, но у них есть один серьёзный недостаток — состояние не сохраняется между сессиями. Что это значит, рассмотрим детально:

ВОПРОСЫ И БАГРЕПОРТЫ

DOWNLOAD

Download https://github.com/precizer/precizer/releases/latest/ executables for:

Пакеты содержат исполняемые бинарные файлы в архиве zip (portable‑версии).

Технические подробности portable сборки

СБОРКА И УСТАНОВКА

Пакетирование для дистрибутивов

Сборка с помощью Docker

Сборка программы уже предусмотрена с использованием Docker. При этом подготовлено несколько тюнингованных платформ, которые могут быть выбраны в качестве дистрибутива для сборки программы. Среди успешно работающих дистрибутивов:

Ознакомиться с подробностями настроек и устанавливаемыми библиотеками можно в соответствующих Docker‑файлах в поддиректории проекта .docker/

Для сборки достаточно указать команду make, ключевое слово docker, дистрибутив debian (например), а затем цель dynamic-production или другую.

Пример сборки в контейнере:

make docker-gentoo-production

Команда соберёт программу в режиме production, используя Docker‑контейнер с дистрибутивом Gentoo.

make docker-ubuntu-production

Команда соберёт программу в том же режиме production, но уже используя дистрибутив Ubuntu.

В результате запуска в директории проекта появится исполняемый файл precizer, который был собран внутри контейнера. При этом явным преимуществом использования Docker является то, что нет необходимости в систему устанавливать много инструментов для сборки и тестирования, библиотек и их зависимостей. Достаточно запустить Docker и получить результат — исполняемый файл. Дальше нужно определиться с типом этого исполняемого файла. В случае сомнений лучше остановить выбор на make portable как на наиболее универсальном варианте. Описания всех доступных вариантов сборки представлены ниже.

Самостоятельная сборка

Подготовка

git clone --depth=1 https://github.com/precizer/precizer.git
cd precizer

Портируемый бинарный файл

make portable

Результатом сборки будет один статически слинкованный, самораспаковывающийся сжатый UPX файл в формате ELF, без каких-либо динамических зависимостей. Этот файл представляет собой всю программу целиком и может быть запущен практически на любом современном дистрибутиве Linux. Достаточно этот файл скопировать на любую платформу в рамках архитектуры x64/arm/etc.

Программа оптимизирована под максимальную переносимость.

Особенности компиляции и линковки: -static -O2 -mtune=generic

Альтернатива с использованием докера:

make docker-ubuntu-portable

или замените -ubuntu- на любой из вышеперечисленных дистрибутивов

Единый бинарный файл с оптимизацией под локальный CPU

make production

Результатом сборки будет заточенный под локальный CPU, статически слинкованный, самораспаковывающийся, сжатый UPX файл в формате ELF, не нуждающийся в отдельных библиотеках. Этот файл представляет собой всю программу целиком, может быть запущен на локальном компьютере и будет использовать все возможности CPU по-максимуму.

Программа оптимизирована под предельно возможную производительность на локальном железе.

Особенности компиляции и линковки: -static -O3 -march=native

Альтернатива с использованием докера:

make docker-ubuntu-production

или замените -ubuntu- на любой из вышеперечисленных дистрибутивов

Исполняемый файл с динамически подгружаемыми библиотеками и оптимизацией под локальный CPU

make dynamic-production

Результатом сборки будет исполняемый файл размером около 50 килобайт в формате ELF. Он будет заточен под локальный CPU, динамически слинкован с установленными в системе библиотеками, самораспаковывающийся, сжатый UPX. Этот файл может быть успешно собран и запущен на локальном компьютере, если в системе были предварительно установлены такие библиотеки, как sqlite3, pcre2, argp и fts.

Файл оптимизирован под максимальную производительность и минимальный размер.

Особенности компиляции: -O3 -march=native

Альтернатива с использованием докера:

make docker-ubuntu-dynamic-production

или замените -ubuntu- на любой из вышеперечисленных дистрибутивов

Установка

Просто скопируйте получившийся исполняемый файл precizer в любое место, прописанное в системной переменной $PATH для быстрого вызова.

Зависимости для сборки на определённых OS

Install build and compile tools on Linux

Arch Linux

sudo pacman -S --noconfirm base-devel gcc-libs sqlite pcre2 upx

Ubuntu/Debian Linux

sudo apt -y install gcc make libpcre2-dev libsqlite3-dev upx-ucl

Alpine Linux

sudo apk add --update build-base pcre2-dev pcre2-static fts-dev argp-standalone sqlite-dev upx

Almalinux/Rocky Linux

sudo dnf -y install gcc make sqlite sqlite-devel glibc-devel pcre2 pcre2-devel upx pcre2-static glibc-static

Gentoo Linux

echo "dev-libs/libpcre2 static-libs" >> /etc/portage/package.use/libpcre2;
emerge dev-libs/libpcre2 app-arch/upx

Clean up

Remove all build artifacts
make purge

ПРИМЕРЫ ИСПОЛЬЗОВАНИЯ

Тесты

Для проверки возможностей программы можно использовать наборы тестов из директории tests/examples/ в исходном коде программы

Запуск тестов:

git clone https://github.com/precizer/precizer.git
cd precizer
make tests

Пример 1

Добавить файлы в две базы данных и сравнить их между собой:

precizer --progress --database=database1.db tests/examples/diffs/diff1

precizer --progress --database=database2.db tests/examples/diffs/diff2

precizer --compare database1.db database2.db

The comparison of database1.db and database2.db databases is starting…
Starting database file database1.db integrity check…
Database database1.db has been verified and is in good condition
Starting database file database2.db integrity check…
Database database2.db has been verified and is in good condition
These files are no longer in the database1.db but still exist in the database2.db
path1/AAA/BCB/CCC/b.txt
These files are no longer in the database2.db but still exist in the database1.db
path2/AAA/ZAW/D/e/f/b_file.txt
The SHA512 checksums of these files do not match between database1.db and database2.db
2/AAA/BBB/CZC/a.txt
3/AAA/BBB/CCC/a.txt
4/AAA/BBB/CCC/a.txt
path1/AAA/ZAW/D/e/f/b_file.txt
path2/AAA/BCB/CCC/a.txt
Comparison of database1.db and database2.db databases is complete
The precizer completed its execution without any issues

Пример 2

Актуализация базы данных

Попробуем использовать предыдущий пример ещё раз. Первая попытка. Сообщение с предупреждением.

precizer --progress --database=database1.db tests/examples/diffs/diff1

The database database1.db was previously created and already contains data with files and their checksums. Use the --update option only when you are certain that the database needs to be updated and when file information (including changes, deletions, and additions) should be synchronized with the database.
ERROR: The precizer process terminated unexpectedly due to an error

Должен быть добавлен параметр –update. Этот параметр необходим для защиты базы данных от потери информации из-за случайного запуска.

precizer --update --progress --database=database1.db tests/examples/diffs/diff1

Primary database file name: database1.db
Starting database file database1.db integrity check…
Database database1.db has been verified and is in good condition
File system traversal initiated to calculate file count and storage usage
Total size: 45B, total items: 58, dirs: 46, files: 12, symlnks: 0
The database file database1.db has NOT been modified since the program was launched
The precizer completed its execution without any issues

Внесём некоторые изменения:

# Modify a file
echo -n "  " >> tests/examples/diffs/diff1/1/AAA/BCB/CCC/a.txt

# Add a new file
touch tests/examples/diffs/diff1/1/AAA/BCB/CCC/c.txt

# Remove a file
rm tests/examples/diffs/diff1/path2/AAA/ZAW/D/e/f/b_file.txt

и запустим precizer ещё раз, но уже с параметром --update:

precizer --update --progress --database=database1.db tests/examples/diffs/diff1

Primary database file name: database1.db
Starting database file database1.db integrity check…
Database database1.db has been verified and is in good condition
File system traversal initiated to calculate file count and storage usage
Total size: 43B, total items: 58, dirs: 46, files: 12, symlnks: 0
The –update option has been used, so the information about files will be updated against the database database1.db
File traversal started
These files have been added or changed and those changes will be reflected against the DB database1.db:
1/AAA/BCB/CCC/a.txt changed size & ctime & mtime rehashed
1/AAA/BCB/CCC/c.txt added
File traversal complete
Total size: 43B, total items: 58, dirs: 46, files: 12, symlnks: 0
These files are no longer exist or ignored and will be deleted against the DB database1.db:
path2/AAA/ZAW/D/e/f/b_file.txt
Start vacuuming the primary database…
The primary database has been vacuumed
The database file database1.db has been modified since the program was launched
The precizer completed its execution without any issues

При каждом запуске precizer обходит файловую систему, после этого проверяя, есть ли запись об определённом файле в базе данных или нет. Другими словами, приоритет для программы имеет состояние файловой системы на диске.

Обход каталогов precizer работает очень похоже на работу rsync, поскольку использует похожий алгоритм.

Стоит обратить внимание, что precizer не будет пересчитывать контрольные суммы SHA512 для файлов, которые уже были записаны в базу данных и для которых метаданные файла остаются прежними (такие, как размер и время последнего доступа — atime). Если указан аргумент --watch-timestamps, то помимо размера будут учитываться время создания и время модификации (mtime и ctime).

Любые новые файлы, удалённые файлы или те файлы, которые изменились между запусками приложения, будут обработаны и, соответственно, все изменения будут отражены в базе данных, если указан параметр --update.

Пример 3

Использование режима --silent. При включении этого режима программа ничего не выводит на экран. Это имеет смысл при использовании precizer в скриптах.

Добавим параметр –silent к предыдущему примеру:

precizer --silent --update --progress --database=database1.db tests/examples/diffs/diff1

В результате на экране ничего не отобразится.

Пример 4

Дополнительная информация в режиме --verbose может быть полезна для отладки.

Добавим параметр –verbose к предыдущему примеру:

precizer --verbose --update --progress --database=database1.db tests/examples/diffs/diff1

2025-01-25 09:55:59:820 src/parse_arguments.c:442:parse_arguments:Configuration: rational_logger_mode=VERBOSE
paths=tests/examples/diffs/diff1; database=database1.db; db_file_name=database1.db; verbose=yes; maxdepth=-1; silent=no; force=no; update=yes; watch-timestamps=no; progress=yes; compare=no, db-clean-ignored=no, dry-run=no, check-level=FULL, rational_logger_mode=VERBOSE
2025-01-25 09:55:59:820 src/parse_arguments.c:558:parse_arguments:Arguments parsed
2025-01-25 09:55:59:820 src/detect_paths.c:025:detect_paths:Checking directory paths provided as arguments
2025-01-25 09:55:59:820 src/file_availability.c:034:file_availability:Verify that the path tests/examples/diffs/diff1 exists
2025-01-25 09:55:59:820 src/file_availability.c:053:file_availability:The path tests/examples/diffs/diff1 is exists and it is a directory
2025-01-25 09:55:59:821 src/detect_paths.c:036:detect_paths:Paths detected
2025-01-25 09:55:59:821 src/init_signals.c:034:init_signals:Set signal SIGUSR2 OK:pid:604770
2025-01-25 09:55:59:821 src/init_signals.c:043:init_signals:Set signal SIGINT OK:pid:604770
2025-01-25 09:55:59:821 src/init_signals.c:052:init_signals:Set signal SIGTERM OK:pid:604770
2025-01-25 09:55:59:821 src/init_signals.c:055:init_signals:Signals initialized
2025-01-25 09:55:59:821 src/determine_running_dir.c:018:determine_running_dir:Current directory: /tmp
2025-01-25 09:55:59:821 src/db_determine_name.c:099:db_determine_name:Primary database file name: database1.db
2025-01-25 09:55:59:821 src/db_determine_name.c:105:db_determine_name:Primary database file path: database1.db
2025-01-25 09:55:59:821 src/db_determine_name.c:109:db_determine_name:DB name determined
2025-01-25 09:55:59:821 src/file_availability.c:034:file_availability:Verify that the path . exists
2025-01-25 09:55:59:821 src/file_availability.c:053:file_availability:The path . is exists and it is a directory
2025-01-25 09:55:59:821 src/file_availability.c:034:file_availability:Verify that the path database1.db exists
2025-01-25 09:55:59:821 src/file_availability.c:044:file_availability:The path database1.db is exists and it is a file
2025-01-25 09:55:59:821 src/db_determine_mode.c:128:db_determine_mode:Final value for config->sqlite_open_flag: SQLITE_OPEN_READWRITE
2025-01-25 09:55:59:821 src/db_determine_mode.c:129:db_determine_mode:Final value for config->db_initialize_tables: false
2025-01-25 09:55:59:821 src/db_determine_mode.c:131:db_determine_mode:DB mode determined
2025-01-25 09:55:59:821 src/db_test.c:061:db_test:Starting database file database1.db integrity check…
2025-01-25 09:55:59:821 src/db_test.c:082:db_test:The database verification level has been set to FULL
2025-01-25 09:55:59:821 src/db_test.c:126:db_test:Database database1.db has been verified and is in good condition
2025-01-25 09:55:59:822 src/db_get_version.c:087:db_get_version:Version number 1 found in database
2025-01-25 09:55:59:822 src/db_check_version.c:032:db_check_version:The database1.db database file is version 1
2025-01-25 09:55:59:822 src/db_check_version.c:061:db_check_version:The database database1.db is on version 1 and does not require any upgrades
2025-01-25 09:55:59:822 src/db_init.c:030:db_init:Successfully opened database database1.db
2025-01-25 09:55:59:822 src/db_init.c:118:db_init:The primary database and tables have NOT been initialized
2025-01-25 09:55:59:822 src/db_init.c:150:db_init:The primary database named database1.db is ready for operations
2025-01-25 09:55:59:822 src/db_init.c:167:db_init:The in-memory runtime_paths_id database successfully attached to the primary database database1.db
2025-01-25 09:55:59:822 src/db_init.c:174:db_init:Database initialization process completed
2025-01-25 09:55:59:822 src/db_compare.c:136:db_compare:Database comparison mode is not enabled. Skipping comparison
2025-01-25 09:55:59:822 src/db_contains_data.c:086:db_contains_data:The database database1.db has already been created previously
2025-01-25 09:55:59:822 src/db_validate_paths.c:192:db_validate_paths:The paths written against the database and the paths passed as arguments are completely identical
2025-01-25 09:55:59:822 src/file_list.c:143:file_list:File system traversal initiated to calculate file count and storage usage
2025-01-25 09:55:59:823 src/file_list.c:038:show_status:Total size: 43B, total items: 58, dirs: 46, files: 12, symlnks: 0
2025-01-25 09:55:59:825 src/db_get_version.c:087:db_get_version:Version number 1 found in database
2025-01-25 09:55:59:825 src/db_consider_vacuum_primary.c:025:db_consider_vacuum_primary:No changes were made. The primary database doesn’t require vacuuming
2025-01-25 09:55:59:825 src/status_of_changes.c:049:status_of_changes:The database file database1.db has NOT been modified since the program was launched
2025-01-25 09:55:59:825 src/exit_status.c:027:exit_status:The precizer completed its execution without any issues

Пример 5

Исследование без рекурсии с помощью параметра --maxdepth

tree tests/examples/4

tests/examples/4
├── AAA
│   ├── BBB
│   │   ├── CCC
│   │   │   └── a.txt
│   │   └── uuu.txt
│   └── tttt.txt
└── sss.txt

3 directories, 4 files

Параметр --maxdepth со значением =0 полностью отключает рекурсию.

precizer --maxdepth=0 tests/examples/4

Primary database file name: myhost.db
The path myhost.db doesn’t exist or it is not a file
The primary DB file not yet exists. Brand new database will be created
Recursion depth limited to: 0
File traversal started
These files will be added against the myhost.db database:
sss.txt
File traversal complete
Total size: 2B, total items: 5, dirs: 4, files: 1, symlnks: 0
Start vacuuming the primary database…
The primary database has been vacuumed
The database myhost.db has been modified since the last check (files were added, removed, or updated)
The precizer completed its execution without any issues

Пример 6

Пример пути, который следует игнорировать. Для указания шаблона игнорирования файлов или каталогов можно использовать регулярные выражения PCRE2. Внимание! Все пути в регулярном выражении должны быть указаны как относительные.

Чтобы проверить и протестировать регулярные выражения PCRE2, можно использовать ресурс https://regex101.com/

Для понимания, как выглядит относительный путь, достаточно запустить сканирование директорий без опции --ignore и посмотреть, как терминал будет отображать относительные пути, записываемые в базу данных:

% tree -L 3 tests/examples/diffs

tests/examples/diffs
├── diff1
│   ├── 1
│   │   └── AAA
│   ├── 2
│   │   └── AAA
│   ├── 3
│   │   └── AAA
│   ├── 4
│   │   └── AAA
│   ├── path1
│   │   └── AAA
│   └── path2
│       └── AAA
└── diff2
    ├── 1
    │   └── AAA
    ├── 2
    │   └── AAA
    ├── 3
    │   └── AAA
    ├── 4
    │   └── AAA
    ├── path1
    │   └── AAA
    └── path2
        └── AAA

26 directories, 0 files
precizer --ignore="^diff1/1/.*" tests/examples/diffs

В этом примере начальный путь сканирования — ./tests/examples/diffs, а сформированный путь для игнорирования — ./tests/examples/diffs/diff1/1/ со всеми подкаталогами (/*).

Primary database file name: myhost.db
The path myhost.db doesn’t exist or it is not a file
The primary DB file not yet exists. Brand new database will be created
File traversal started
These files will be added against the myhost.db database:
diff1/1/AAA/BCB/CCC/a.txt ignored & not added
diff1/1/AAA/ZAW/A/b/c/a_file.txt ignored & not added
diff1/1/AAA/ZAW/D/e/f/b_file.txt ignored & not added
diff1/2/AAA/BBB/CZC/a.txt
diff1/3/AAA/BBB/CCC/a.txt
diff1/4/AAA/BBB/CCC/a.txt
diff1/path1/AAA/BCB/CCC/a.txt
diff1/path1/AAA/ZAW/A/b/c/a_file.txt
diff1/path1/AAA/ZAW/D/e/f/b_file.txt
diff1/path2/AAA/BCB/CCC/a.txt
diff1/path2/AAA/ZAW/A/b/c/a_file.txt
diff1/path2/AAA/ZAW/D/e/f/b_file.txt
diff2/1/AAA/BCB/CCC/a.txt
diff2/1/AAA/ZAW/A/b/c/a_file.txt
diff2/1/AAA/ZAW/D/e/f/b_file.txt
diff2/2/AAA/BBB/CZC/a.txt
diff2/3/AAA/BBB/CCC/a.txt
diff2/4/AAA/BBB/CCC/a.txt
diff2/path1/AAA/BCB/CCC/a.txt
diff2/path1/AAA/BCB/CCC/b.txt
diff2/path1/AAA/ZAW/A/b/c/a_file.txt
diff2/path1/AAA/ZAW/D/e/f/b_file.txt
diff2/path2/AAA/BCB/CCC/a.txt
diff2/path2/AAA/ZAW/A/b/c/a_file.txt
File traversal complete
Total size: 97B, total items: 114, dirs: 90, files: 24, symlnks: 0
Start vacuuming the primary database…
The primary database has been vacuumed
The database myhost.db has been modified since the last check (files were added, removed, or updated)
The precizer completed its execution without any issues
Enjoy your life!

Повторим тот же пример, но без опции --ignore, чтобы добавить три ранее проигнорированных файла:

precizer --update tests/examples/diffs

Primary database file name: myhost.db
Starting database file myhost.db integrity check…
Database myhost.db has been verified and is in good condition
The –update option has been used, so the information about files will be updated against the database myhost.db
File traversal started
These files have been added or changed and those changes will be reflected against the DB myhost.db:
diff1/1/AAA/BCB/CCC/a.txt add
diff1/1/AAA/ZAW/A/b/c/a_file.txt add
diff1/1/AAA/ZAW/D/e/f/b_file.txt add
File traversal complete
Total size: 97B, total items: 114, dirs: 90, files: 24, symlnks: 0
Start vacuuming the primary database…
The primary database has been vacuumed
The database file myhost.db has been modified since the program was launched
The precizer completed its execution without any issues

Пример 7

Продолжение предыдущего примера Пример 6.

Несколько регулярных выражений для игнорирования можно указать одновременно, повторив опцию --ignore несколько раз.

База данных будет очищена от упоминаний файлов, соответствующих регулярным выражениям из аргументов --ignore: “diff1/1/.*” и “diff2/1/.*”

Параметр --db-clean-ignored должен быть указан дополнительно, чтобы удалить из базы данных упоминание файлов, соответствующих регулярным выражениям, переданным через опции --ignore.

На файловой системе не было изменений, но игнорируемые файлы будут удалены из БД.

# Обновить базу данных, удалив информацию о тех файлах, которые были указаны как игнорируемые:

precizer \
    --update \
    --db-clean-ignored \
    --ignore="^diff1/1/.*" \
    --ignore="^diff2/1/.*" \
    tests/examples/diffs

Primary database file name: myhost.db
Starting database file myhost.db integrity check…
Database myhost.db has been verified and is in good condition
The –update option has been used, so the information about files will be deleted against the database myhost.db
These files are no longer exist or ignored and will be deleted against the DB myhost.db:
diff1/1/AAA/BCB/CCC/a.txt clean ignored
diff1/1/AAA/ZAW/A/b/c/a_file.txt clean ignored
diff1/1/AAA/ZAW/D/e/f/b_file.txt clean ignored
diff2/1/AAA/BCB/CCC/a.txt clean ignored
diff2/1/AAA/ZAW/A/b/c/a_file.txt clean ignored
diff2/1/AAA/ZAW/D/e/f/b_file.txt clean ignored
Start vacuuming the primary database…
The primary database has been vacuumed
The database file myhost.db has been modified since the program was launched
The precizer completed its execution without any issues

Пример 8

Использование параметров --ignore вместе с --include


# Удалим старую базу данных и создадим новую, наполним её данными:

rm -i "${HOST}.db"

precizer tests/examples/diffs

Усложним задачу с использованием регулярных выражений.

Регулярные выражения PCRE2 для относительных путей, которые необходимо включить. Включаем указанные относительные пути, даже если они были исключены с помощью одного или нескольких параметров --ignore. Несколько регулярных выражений могут быть указаны с помощью --include

Чтобы проверить и протестировать регулярные выражения PCRE2, можно использовать ресурс https://regex101.com/

DB будет очищена от упоминаний файлов, соответствующих регулярным выражениям из аргументов --ignore: “^.*/path2/.*” и “diff2/.*”, но опция --include оставит в базе данных пути, соответствующие заданным шаблонам.

Параметр --db-clean-ignored должен быть указан дополнительно, чтобы удалить из базы данных упоминание файлов, соответствующих регулярным выражениям, переданным через опции --ignore.


# Обновить базу данных, удалив информацию о тех файлах, которые были указаны как игнорируемые за исключением шаблонов путей из --include

precizer --update --db-clean-ignored \
	--ignore="^.*/path2/.*" \
	--ignore="^diff2/.*" \
	--include="^diff2/1/AAA/ZAW/A/b/c/.*" \
	--include="^diff2/path1/AAA/ZAW/.*" \
	tests/examples/diffs

Primary database file name: myhost.db
Starting database file myhost.db integrity check…
Database myhost.db has been verified and is in good condition
The –update option has been used, so the information about files will be deleted against the database myhost.db
These files are no longer exist or ignored and will be deleted against the DB myhost.db:
diff1/path2/AAA/BCB/CCC/a.txt clean ignored
diff1/path2/AAA/ZAW/A/b/c/a_file.txt clean ignored
diff1/path2/AAA/ZAW/D/e/f/b_file.txt clean ignored
diff2/1/AAA/BCB/CCC/a.txt clean ignored
diff2/1/AAA/ZAW/D/e/f/b_file.txt clean ignored
diff2/2/AAA/BBB/CZC/a.txt clean ignored
diff2/3/AAA/BBB/CCC/a.txt clean ignored
diff2/4/AAA/BBB/CCC/a.txt clean ignored
diff2/path1/AAA/BCB/CCC/a.txt clean ignored
diff2/path1/AAA/BCB/CCC/b.txt clean ignored
diff2/path2/AAA/BCB/CCC/a.txt clean ignored
diff2/path2/AAA/ZAW/A/b/c/a_file.txt clean ignored
Start vacuuming the primary database…
The primary database has been vacuumed
The database file myhost.db has been modified since the program was launched
The precizer completed its execution without any issues

Пример 9

Защита неизменяемых архивов с помощью --lock-checksum

Опция --lock-checksum нужна для архивных каталогов или файлов, содержимое которых не должно переписываться. Она принимает регулярные выражения PCRE2 для относительных путей (тот же формат, что и у --ignore). Пути, совпавшие с любым шаблоном, записываются в БД один раз. После этого их контрольные суммы не пересчитываются даже при --update. Любое дальнейшее изменение размера или временных меток (при использовании режима --watch-timestamps) считается порчей данных и выводится как сообщение об ошибке вместо обновления записи. Несколько шаблонов могут быть указаны повторением добавления опции.

precizer \
  --lock-checksum="^archive/2024/.*" \
  --lock-checksum="^snapshots/monthly/.*" \
  /mnt/storage

В последующих запусках необходимо сохранять те же шаблоны блокировки при актуализации базы:

precizer --update --lock-checksum="^archive/2024/.*" /mnt/storage

Файлы вне шаблонов обновляются в обычном порядке. Для заблокированных через --lock-checksum записей любое расхождение сразу становится заметным и код возврата при завершении precizer будет больше нуля.

Пример 10

Глубокая проверка заблокированных данных с помощью --rehash-locked

Опция --rehash-locked используется только вместе с --lock-checksum. При её включении каждый файл, попавший под шаблон блокировки и уже присутствующий в базе данных, перечитывается побайтно, для него заново вычисляется контрольная сумма SHA512 и выполняется сравнение с сохранённым значением. Это позволяет выполнить дополнительный аудит неизменяемых архивов ценой увеличенного дискового ввода-вывода. Наличие или отсутствие параметра --watch-timestamps не влияет на работу --rehash-locked. Если пересчитанная сумма и размер совпадают с записью в БД, файл считается консистентным; если при этом на диске отличаются ctime/mtime, новые значения сохраняются в базе данных.

precizer --update \
  --lock-checksum="^archive/2024/.*" \
  --rehash-locked \
  /mnt/storage

Чтобы увидеть взаимодействие --watch-timestamps и --rehash-locked, рассмотрим несколько случаев:

  1. Размер файла отличается. Если размер, записанный в базе, не совпадает с размером на диске, файл будет помечен как «нарушена контрольная сумма» вне зависимости от --watch-timestamps и --rehash-locked. Пересчитывать контрольную сумму бессмысленно: при изменившемся размере она всё равно не совпадёт.
  2. Совпадают размер и временные метки; указана --watch-timestamps. Файл полностью консистентен, он не появится в выводе, а статус завершения программы будет SUCCESS.
  3. Размер совпадает, временные метки различаются; указана --watch-timestamps и не указана --rehash-locked. Файл будет отмечен как «нарушена контрольная сумма», и precizer завершится со статусом WARNING.
  4. Размер совпадает, временные метки различаются; --watch-timestamps не указана, --rehash-locked не указана. Файл не будет помечен, программа завершится со статусом SUCCESS.
  5. Дополнительно с --watch-timestamps используется --rehash-locked. Для проверки учитываются только контрольная сумма и размер, записанные в базе данных. Если они совпадают, файл остаётся консистентным, предупреждений не будет. Если на диске изменилась только временная метка, новые значения ctime/mtime будут сохранены в базе данных.

Практический сценарий: выполнять ежедневное быстрое сканирование без --rehash-locked (и при необходимости без --watch-timestamps), чтобы поддерживать БД в актуальном состоянии, а реже запускать углублённый аудит с --rehash-locked, который гарантированно сверяет контрольные суммы «замороженных» данных.

АВТОР

Автор приложения Денис Владимирович Разумовский

LICENSE

This program is distributed under the CC0 (Creative Commons Zero) Public Domain Dedication. The author is not responsible for any use of the source code or the entire program. Anyone who uses the code or the program uses it at their own risk and responsibility.

Ограничение использования на территории рашистского террористического геообразования, захваченного оккупировавшей власть авторитарной диктатурой