Link to the English language README page
Precizer — проверка контрольных сумм файлов в любом масштабе
Крошечное, высокопроизводительное приложение для проверки целостности файлов
«По-настоящему хорошая программа всегда поместится на дискету. Есть надежда, что кто-то всё ещё помнит, что это такое… Речь идёт не о дискетах, а о качественных программах!»© :-D
КРАТКО
Обзор
precizer — крошечное и быстрое консольное приложение, полностью написанное на чистом Си. Предназначено для проверки целостности и сравнения файлов. Особенно полезно для проверки результатов синхронизации. Программа обходит дерево каталогов и создаёт базу данных файлов и их контрольных сумм с последующим быстрым сравнением.
precizer предназначен как для работы на embedded платформах, так и с файловыми системами гигантского размера на базе кластерных мейнфреймов. С помощью программы можно найти ошибки синхронизации, сравнивая данные с файлами и их контрольными суммами из разных источников. Также precizer можно использовать для исследования исторических изменений путём сравнения баз данных из одних и тех же источников, но за разное время.
Простой пример
Допустим, есть две машины, у которых в /mnt1 и /mnt2 соответственно примонтированы диски большого объёма с идентичным содержимым. Стоит задача побайтно проверить, действительно ли содержимое абсолютно идентично или есть различия.
- Запустить программу на первой машине с hostname, например «host1»:
precizer --progress /mnt1
В результате работы программы будут исследованы все директории, начиная с /mnt1, и в текущей директории будет создана база данных host1.db. Параметр --progress визуализирует прогресс и покажет объём пространства и количество исследуемых файлов.
- Запустить программу на второй машине с hostname, например «host2»:
precizer --progress /mnt2
В результате будет создана база данных host2.db в текущей директории.
- Скопировать файлы с базами данных host1.db и host2.db на одну из машин и запустить программу с соответствующими параметрами для сравнения:
precizer --compare host1.db host2.db
На экран будет выведена следующая информация:
- Какие файлы отсутствуют на «host1», но при этом присутствуют на «host2» и наоборот.
- Для каких файлов, присутствующих на обоих хостах, контрольные суммы НЕ совпадают.
Относительные пути в базе данных для сравнения
Следует обратить внимание, что 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, позволяют производить синхронизацию по обеим методикам: как с учётом изменившихся файлов, так и побайтово, но у них есть один серьёзный недостаток — состояние не сохраняется между сессиями. Что это значит, рассмотрим детально:
- Даны: сервер «A» и сервер «B» (основной датацентр и резервный Disaster Recovery‑центр)
- На сервере «A» изменились некоторые файлы.
- Алгоритм
rsyncих определил за счёт изменившегося размера и времени модификации файла и синхронизировал на сервер «B». - Во время синхронизации между основным датацентром и Disaster Recovery‑центром происходили многократные сбои связи.
- Для проверки целостности данных (эквивалентности сохранённых файлов на «A» и «B» байт в байт) обычно используют тот же
rsyncтолько с включением побайтного сравнения. Для этого:rsyncзапускается на сервере «A» в режиме--checksumи во время одного сеанса пытается подсчитать контрольные суммы последовательно: сначала на «A», а затем на «B».- Этот процесс занимает неимоверно много времени для огромных дисковых массивов.
- Так как
rsyncне позволяет сохранять состояние уже подсчитанных контрольных сумм между сеансами, возникает целый ряд технических сложностей. А именно:- В случае разрыва соединения
rsyncзавершает сеанс и в следующий запуск всё нужно начинать сначала! С учётом огромных объёмов побайтовая проверка данных на полную идентичность таким образом превращается в нереализуемую задачу.
- В случае разрыва соединения
- Причиной неидентичности бинарного содержимого файлов могут стать также сбои на уровне дисковой подсистемы. В таких случаях с помощью метаданных файловой системы невозможно будет определить, есть ли разница между содержимым внутри файлов на серверах «A» и «B», или нет.
- Со временем ошибки накапливаются и появляется угроза получить неконсистентную копию системы «A» на системе «B», что сводит на нет все усилия и затраты по поддержанию Disaster Recovery‑центра. При этом стандартные утилиты не обладают возможностями проверок и технический персонал даже не будет знать о накопившихся проблемах с неэквивалентным содержанием дисковых массивов на Disaster Recovery‑центре.
- Для устранения вышеописанных недостатков создана программа precizer. Программа позволяет выявить, какие именно файлы отличаются между «A» и «B» для проведения повторной синхронизации с устранением отличий. Программа работает максимально быстро (практически на грани аппаратных возможностей) за счёт того, что написана на чистом Си и использует современные алгоритмы, оптимизированные под высокую производительность. Программа предназначена для работы как с мелкими файлами, так и с объёмами данных, измеряемыми петабайтами, и не ограничена этими цифрами.
- Название программы precizer происходит от слова precision (точность) и означает что-то, что увеличивает точность.
- Программа с высокой точностью исследует содержимое директорий, субдиректорий и подсчитывает контрольные суммы для каждого встреченного файла, при этом сохраняя метаинформацию о всех файлах в SQLite базе (обычный бинарный файл).
- precizer устойчива к сбоям и умеет продолжить работу с того момента, когда была прервана. Например, если программа была остановлена нажатием Ctrl+C в момент анализа файла петабайтного объёма, то при повторном запуске она НЕ будет анализировать его с самого начала, а продолжит именно с того момента, на котором была прервана и о котором уже есть запись в базе данных. Это позволит сэкономить ресурсы, время и нервы системных администраторов.
- Работа этой программы может быть прервана в любой момент любым способом, и это безопасно как для исследуемых данных, так и для БД, созданной самой программой.
- В случае умышленной или случайной остановки работы программы можно не беспокоиться о результатах сбоя. Результат работы будет полностью сохранён и повторно использован при следующих запусках.
- Для подсчёта контрольных сумм используется надёжный и быстрый алгоритм SHA512, полностью исключающий коллизии даже в случае анализа единичного файла гигантского объёма. Если есть два полностью идентичных файла огромного объёма, различающихся только на один байт, то алгоритм SHA512 это отразит и контрольные суммы будут различаться, что не может быть гарантировано в случае использования более простых хеш-функций типа SHA1 или CRC32.
- Алгоритмы программы precizer разработаны так, что очень просто поддерживать актуальность содержащихся данных в созданной базе с путями к файлам и их контрольными суммами без пересчёта всего с самого начала. Достаточно запустить программу с параметром
--update, чтобы в БД попали новые файлы или была удалена информация о стёртых с диска. Для тех файлов, которые подверглись модификациям и чьи размеры изменились, будет пересчитана контрольная сумма SHA512, и обновлённая контрольная сумма будет записана в БД. - Можно указать опцию, при которой при обновлении БД будет учитываться не только размер изменившихся файлов, но также и время создания или изменения файлов. Это значит, что изменения любой метаинформации о файле приведут к пересчёту контрольной суммы SHA512 с последующим обновлением данных о файле в БД. Например, если у файла изменилась ctime, но не изменился размер, то контрольная сумма для такого файла НЕ будет пересчитана при указании только одного параметра
--update. Чтобы контрольная сумма для таких файлов была пересчитана, необходимо добавить--watch-timestamps. Эта опция не включена по умолчанию, потому что ctime (как и mtime) могут меняться часто, например, командамиchmodилиchown, при том, что само содержимое файла остаётся прежним. - precizer может служить инструментом контроля безопасности, определяя последствия вторжения за счёт выявления несанкционированно изменённых файлов, у которых могло быть модифицировано содержимое, но метаданные могли остаться прежними.
- Безопасность:
- Программа никогда не меняет, не удаляет, не перемещает и не копирует ни файлы, ни исследуемые директории.
- Программа составляет списки файлов, контрольные суммы содержимого этих файлов и сохраняет их в локальной базе данных. Все изменения происходят исключительно в границах базы данных.
- База данных не хранит содержимое файлов, только их относительные пути, контрольные суммы и такие метаданные, как размер и даты ctime и mtime.
- Программа не открывает сокеты.
- Не передаёт данные куда-либо.
- Не требует привилегированных прав для исполнения и не использует SUID-бит или какие-либо другие небезопасные биты.
- В программе нет ничего, что может эксплуатироваться для повышения привилегий или других нарушений безопасности.
- Производительность программы в основном упирается в производительность дисковой подсистемы. Каждый файл считывается побайтно, и для каждого файла формируется своя контрольная сумма с использованием алгоритма SHA512.
- Программа работает очень быстро благодаря библиотекам SQLite и FTS (man 3 fts).
- Разбор параметров строки реализован через библиотеку ARGP.
- Для регулярных выражений выбрана библиотека PCRE2.
- Программа безопасна для случаев с огромным количеством файлов, директорий и поддиректорий любой вложенности. Благодаря библиотеке FTS рекурсия не используется, поэтому не произойдёт переполнения стека даже в случае большой вложенности файлов.
- За счёт своей компактности и переносимости кода программа может использоваться даже на специализированных устройствах типа NAS, а также на embedded- или IoT-устройствах.
- Если любопытно узнать, что содержится внутри базы данных, сформированной precizer, то можно воспользоваться удобным GUI DB Browser for SQLite.
ВОПРОСЫ И БАГРЕПОРТЫ
- Подсказка
--helpсделана максимально подробной специально для помощи пользователям, не обладающим специализированными техническими знаниями. - Обратиться к автору можно:
- Через форму GitHub Дискуссий.
- Там же на GitHub можно опубликовать багрепорт или feature request.
- При возникновении сложностей при использовании программы можно задать вопрос на ru.stackoverflow.com, используя тег precizer. Автор следит за такими вопросами и будет рад помочь в решении проблем любой сложности.
DOWNLOAD
Download https://github.com/precizer/precizer/releases/latest/ executables for:
- Linux x86_64
- Linux aarch64
- macOS arm64
Пакеты содержат исполняемые бинарные файлы в архиве zip (portable‑версии).
Технические подробности portable сборки
-
Готовая Linux сборка представляет собой один исполняемый, статически слинкованный бинарный файл в формате ELF, не привязанный к какому-либо определённому дистрибутиву. Файл может быть запущен сразу, практически на любом дистрибутиве Linux и не требует использования внешних, динамически подгружаемых библиотек.
-
Файл собран CI/CD автосборкой ресурса GitHub, затем сжат с помощью UPX (архиватора исполняемых файлов). После этого самораспаковывающийся сжатый бинарный файл вкладывается в ZIP-архив для удобного скачивания. Для использования достаточно распаковать файл из архива и запустить.
-
На macOS статическая линковка не поддерживается, поэтому для запуска скачанного приложения нужно озаботиться наличием в системе таких библиотек, как sqlite3, pcre2, argp и fts.
СБОРКА И УСТАНОВКА
Пакетирование для дистрибутивов
- Автор был рад подготовить автоматическую сборку средствами GitHub CI Workflows и будет в дальнейшем поддерживать новые версии.
- Автор НЕ готов самостоятельно создавать и поддерживать в будущем пакетирование программы precizer под все существующие дистрибутивы операционных систем.
- Если Вы горите желанием создать пакет под любой дистрибутив и столкнулись с непреодолимыми трудностями по адаптации кода программы, то именно в этом случае автор будет очень рад оказать всю необходимую помощь в поддержке инициативы и оптимизации кода программы под конкретный дистрибутив или пакетный менеджер. Как связаться с автором, описано в разделе «Вопросы и багрепорты».
Сборка с помощью Docker
Сборка программы уже предусмотрена с использованием Docker. При этом подготовлено несколько тюнингованных платформ, которые могут быть выбраны в качестве дистрибутива для сборки программы. Среди успешно работающих дистрибутивов:
- Almalinux
- Alpine
- Arch
- Debian
- Gentoo
- Rocky
- Ubuntu
Ознакомиться с подробностями настроек и устанавливаемыми библиотеками можно в соответствующих 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, рассмотрим несколько случаев:
- Размер файла отличается. Если размер, записанный в базе, не совпадает с размером на диске, файл будет помечен как «нарушена контрольная сумма» вне зависимости от
--watch-timestampsи--rehash-locked. Пересчитывать контрольную сумму бессмысленно: при изменившемся размере она всё равно не совпадёт. - Совпадают размер и временные метки; указана
--watch-timestamps. Файл полностью консистентен, он не появится в выводе, а статус завершения программы будетSUCCESS. - Размер совпадает, временные метки различаются; указана
--watch-timestampsи не указана--rehash-locked. Файл будет отмечен как «нарушена контрольная сумма», иprecizerзавершится со статусомWARNING. - Размер совпадает, временные метки различаются;
--watch-timestampsне указана,--rehash-lockedне указана. Файл не будет помечен, программа завершится со статусомSUCCESS. - Дополнительно с
--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.
Ограничение использования на территории рашистского террористического геообразования, захваченного оккупировавшей власть авторитарной диктатурой
- Разрешено: исключительно личное некоммерческое использование частными лицами.
- Запрещено: любое использование, прямо или косвенно приводящее к уплате налогов, сборов, взносов или иных обязательных платежей в местные бюджеты на указанной территории (включая НДС, налог на прибыль, НДФЛ при исполнении обязанностей налогового агента, страховые взносы, таможенные пошлины и т.п.).
- Также запрещено использование структурами, которые по недоразумению именуют себя государственными органами, государственными компаниями, бюджетными учреждениями и аффилированными организациями.
- Коммерческая эксплуатация, возмездное распространение, платная поддержка и интеграция — запрещены, если осуществляются на указанной территории или для её резидентов и влекут уплату обязательных платежей.
- Запрет распространяется на использование самой программы, её исходного кода полностью или частично.
- Цель условия — исключить прямое и косвенное финансирование войны в Украине.