Link to the English language README page
Precizer — проверка целостности данных для файловых систем любого масштаба
Крошечное, высокопроизводительное приложение для проверки целостности файлов
«По-настоящему хорошая программа всегда поместится на дискету. Есть надежда, что кто-то всё ещё помнит, что это такое… Речь идёт не о дискетах, а о качественных программах!»© :-D
Содержание
- Непрерывная интеграция и автоматизация
- Кратко о программе
- Скачивание
- История изменений
- Технические подробности алгоритмов работы
- Вопросы и багрепорты
- Участие в проекте
- Сборка и установка
- Конфигурационный файл
- Примеры использования
- Основные параметры командной строки
- Устранение неполадок
- Альтернативы
- Автор
- Лицензия
Continuous integration and automation
Гибридный интеграционно-системный набор тестов
- In-process integration tests
- Out-of-process CLI system tests
- Unit tests
Test coverage:
Automated builds:
Security:
Bages
КРАТКО О ПРОГРАММЕ
Обзор
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
и с соответствующими контрольными суммами.
Скачивание/Download
Подходящий пакет определяется по операционной системе и архитектуре процессора.
Linux
64-разрядный процессор Intel или AMD (x86_64)
Скачать precizer для Linux x86_64
Переносимая статически слинкованная сборка для большинства настольных и серверных дистрибутивов Linux. Дополнительные динамические библиотеки не требуются
64-разрядный процессор ARM (ARM64 / AArch64)
Скачать precizer для Linux ARM64
Переносимая статически слинкованная сборка для 64-разрядных ARM-систем. Дополнительные динамические библиотеки не требуются
Windows
Поддержка Windows экспериментальная.
64-разрядный процессор Intel или AMD (x64)
Рекомендуемый пакет для Windows. После распаковки архива файлы precizer.exe и msys-2.0.dll должны находиться в одном каталоге
Скачать отдельный EXE-файл для Windows
Самораспаковывающийся исполняемый файл, не требующий отдельных файлов библиотек среды выполнения. Поддержка Windows экспериментальная и исполняемый файл не имеет цифровой подписи, поэтому Defender может показать предупреждение
macOS
Сборки для macOS используют динамические библиотеки. Необходимые для запуска пакеты перечислены в разделе «Системные библиотеки для запуска приложения».
Процессор Apple Silicon (M1 или новее, ARM64)
Скачать precizer для macOS Apple Silicon ARM64
Процессор Intel (x86_64)
Скачать precizer для macOS Intel x86_64
Автоматическое скачивание, распаковка и запуск в Linux и macOS
Этот сценарий определяет операционную систему и архитектуру процессора, скачивает подходящую сборку последнего релиза, распаковывает её и проверяет запуск precizer
# Automation for downloading and unarchiving new versions
# Download
wget -O precizer.zip -q "https://github.com/precizer/precizer/releases/latest/download/precizer_$(uname -s | tr '[:upper:]' '[:lower:]' | sed 's/darwin/macos/')_$(uname -m | sed 's/amd64/x86_64/')$( [ "$(uname -s)" = "Linux" ] && echo '_portable' ).zip"
# Extract the archive
unzip -jqo precizer.zip '*/precizer' -d ./
# Run
./precizer --version
Технические детали portable сборки
-
Готовая Linux сборка представляет собой один исполняемый, статически слинкованный бинарный файл в формате ELF, не привязанный к какому-либо определённому дистрибутиву. Файл может быть запущен сразу, практически на любом дистрибутиве Linux и не требует использования внешних, динамически подгружаемых библиотек.
-
Файл собирается CI/CD автосборкой actions GitHub, затем сжимается с помощью UPX (архиватора исполняемых файлов). После этого самораспаковывающийся сжатый бинарный файл вкладывается в ZIP-архив для удобного скачивания. Для использования достаточно распаковать файл из архива и запустить.
-
ZIP-пакет для Windows x64: программа собирается в среде MSYS2 (MSYS) и основные компоненты линкуются статически. Архив содержит
precizer.exeи библиотеку среды выполненияmsys-2.0.dll; после распаковки они должны оставаться в одном каталоге. Устанавливать MSYS2 для запуска не нужно -
Отдельный EXE для Windows x64: самораспаковывающийся загрузчик содержит внутри те же
precizer.exeиmsys-2.0.dll. При запуске он извлекает их в пользовательский кэш и запускает программу, а при следующих запусках повторно использует сохранённые файлы. Загрузчик собирается средствами MinGW-w64/UCRT. Исполняемый файл сжат с помощью UPX для уменьшения размера. Отдельно устанавливать MSYS2 или размещать DLL рядом со скачанным EXE не требуется -
На macOS статическая линковка не поддерживается на уровне операционной системы. Необходимые для запуска приложения системные библиотеки перечислены в разделе «Системные библиотеки для запуска приложения».
ИСТОРИЯ ИЗМЕНЕНИЙ
Список изменений по версиям можно найти в отдельном файле CHANGELOG
ТЕХНИЧЕСКИЕ ПОДРОБНОСТИ АЛГОРИТМОВ РАБОТЫ
Рассмотрим сценарий, когда имеется основное дисковое хранилище и его копия.
Например, это может быть хранилище датацентра и его 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 можно остановить и затем продолжить без риска для проверяемых данных. Программа не меняет исследуемые файлы и каталоги, а сохраняет только собственный прогресс и результаты в SQLite-базу.
- Если пользователь нажал Ctrl+C или процесс завершился во время обработки большого файла, precizer использует уже сохранённый прогресс в БД. При следующем запуске с
--updateпрограмма продолжит хеширование с ближайшей сохранённой точки, а не обязательно с самого начала файла. - Во время долгого подсчёта SHA512 precizer регулярно сохраняет прогресс. Сейчас программа старается делать это примерно раз в 14 930 016 475 наносекунд, поэтому после аварийного завершения обычно теряется не вся работа по большому файлу, а только небольшой участок после последнего сохранения.
- Если файл изменился после сохранения промежуточного прогресса, старому прогрессу доверять нельзя. В таком случае precizer начнёт считать SHA512 для этого файла заново, чтобы итоговая контрольная сумма относилась к текущему содержимому файла.
- Для промежуточного прогресса проверка специально строгая: precizer продолжает с сохранённого места только если текущий файл выглядит точно так же, как в момент сохранения прогресса. Должны совпасть размер файла, количество занятых блоков на диске, если оно доступно на этой файловой системе, а также
mtimeиctime. Если отличается хотя бы один из этих признаков, программа считает, что файл мог измениться, и начинает расчёт SHA512 с начала. - В режимах
--dry-runи--dry-run=with-checksumsпрогресс в БД не сохраняется, потому что эти режимы не должны изменять базу данных. - Для обычного файла в БД может временно храниться состояние для продолжения хеширования, а не полная SHA512. То же возможно для файла, который уже попал под
--lock-checksum, но ещё не был дочитан до конца: при повторном запуске precizer продолжит расчёт с сохранённого места. После успешного завершения чтения временное состояние заменяется полной SHA512. С этого момента защищённый файл считается запечатанным: уже сохранённая полная SHA512 становится эталоном, и временная запись о ходе последующей проверки больше не затирает эту эталонную контрольную сумму. - Для подсчёта контрольных сумм используется криптографически стойкий, надёжный и быстрый алгоритм SHA512 с очень высокой практической устойчивостью к коллизиям. Если два больших файла различаются хотя бы на один байт, SHA512 с подавляющей вероятностью отразит это в разных контрольных суммах; в отличие от CRC32 и устаревшего SHA1, этот алгоритм предназначен именно для надёжной проверки целостности данных
- precizer поддерживает актуальность базы с путями к файлам и их контрольными суммами без полного пересчёта. При запуске с
--updateв БД добавляются новые файлы и удаляются записи об исчезнувших файлах. Для файлов с уже сохранённой полной SHA512 контрольная сумма пересчитывается при изменении размера файла или времени модификации (mtime), и результат обновляетя в БД - При
--updateзаписи об отсутствующих файлах удаляются, но записи о недоступных файлах (например, из-за прав доступа) по умолчанию сохраняются. Такая защита нужна потому, что права могут временно меняться (владелец, ACL, проблемы монтирования), и при удалении записей в этот момент можно незаметно потерять корректную историю в БД. Использование--db-drop-inaccessibleвместе с--updateоправдано только если нужно действительно удалить эти записи из БД. - При включённом
--progressпредупреждения и ошибки, накопленные в течение сессии, выводятся единым блоком перед завершением программы, чтобы важные сообщения (например, об отсутствии доступа к файлам) не терялись на фоне второстепенных логов. - Опция
--quiet-ignoredотключает вывод строк о файлах, отфильтрованных через--ignoreи--include. Это помогает не засорять логи программы лишними сообщенями, когда регулярные выражения для игнорирования уже отлажены и стабильны в работе; остальные предупреждения и ошибки продолжают выводиться. - Можно указать опцию, при которой при обновлении БД будет учитываться не только размер изменившихся файлов, но также и время изменения метаданных (
ctime) или содержимого файлов (mtime). Это значит, что изменения любой метаинформации о файле приведут к пересчёту контрольной суммы SHA512 с последующим обновлением данных о файле в БД. Например, если у файла изменилсяctime, но размер иmtimeостались прежними, контрольная сумма не будет пересчитана при использовании только--update. Для пересчёта необходимо добавить--watch-timestamps. Эта опция не включена по умолчанию, потому что ctime могут меняться часто, например, командамиchmodилиchown, при том, что само содержимое файла остаётся прежним. - precizer может служить инструментом контроля безопасности, определяя последствия вторжения за счёт выявления несанкционированно изменённых файлов, у которых могло быть модифицировано содержимое, но метаданные могли остаться прежними.
- Безопасность:
- Программа никогда не меняет, не удаляет, не перемещает и не копирует ни файлы, ни исследуемые директории.
- Программа не открывает сокеты, не делает запросов в сеть или на внешние адреса в интернете, не передаёт данные куда-либо и работает исключительно локально.
- Программа составляет списки файлов, контрольные суммы содержимого этих файлов и сохраняет их в локальной базе данных. Все изменения происходят исключительно в границах базы данных.
- База данных не хранит содержимое файлов, только их относительные пути, контрольные суммы и такие метаданные, как размер и даты ctime и mtime.
- Не требует привилегированных прав для исполнения и не использует SUID-бит или какие-либо другие небезопасные биты.
- В программе нет ничего, что может эксплуатироваться для повышения привилегий или других нарушений безопасности.
- Производительность программы в основном упирается в производительность дисковой подсистемы. Каждый файл считывается побайтно, и для каждого файла формируется своя контрольная сумма с использованием алгоритма SHA512.
- Программа работает очень быстро благодаря библиотекам SQLite и FTS (man 3 fts).
- Разбор параметров строки реализован через библиотеку ARGP, а конфигурационного файла через inih.
- Для регулярных выражений выбрана библиотека PCRE2.
- Программа безопасна для случаев с огромным количеством файлов, директорий и поддиректорий любой вложенности. Благодаря библиотеке FTS рекурсия не используется, поэтому не произойдёт переполнения стека даже в случае большой вложенности файлов.
- За счёт своей компактности и переносимости кода программа может использоваться даже на специализированных устройствах типа NAS, а также на embedded- или IoT-устройствах.
- Если любопытно узнать, что содержится внутри базы данных, сформированной precizer, то можно воспользоваться удобным GUI DB Browser for SQLite.
ВОПРОСЫ И БАГРЕПОРТЫ
- Подсказка
--helpсделана максимально подробной специально для помощи пользователям, не обладающим специализированными техническими знаниями. - Обратиться к автору можно:
- По электронной почте: jpy95dg6@anonaddy.com
- Через форму GitHub Дискуссий
- Приватно сообщить о проблеме безопасности можно через GitHub Security Advisories
- Там же на GitHub можно опубликовать багрепорт или feature request.
УЧАСТИЕ В ПРОЕКТЕ
Участие в развитии проекта приветствуется. Начните с CONTRIBUTING: там описаны рабочий процесс, зависимости, шаги проверки и требования к pull request. Актуальные запросы на усовершенствования можно выбрать в списке Issues по уровню и интересу.
СБОРКА И УСТАНОВКА
Пакетирование для дистрибутивов
- Автор был рад подготовить автоматическую сборку средствами GitHub CI Workflows и будет в дальнейшем поддерживать новые версии.
- Автор НЕ готов самостоятельно создавать и поддерживать в будущем пакетирование программы precizer под все существующие дистрибутивы операционных систем.
- Если Вы горите желанием создать пакет под любой дистрибутив и столкнулись с непреодолимыми трудностями по адаптации кода программы, то именно в этом случае автор будет очень рад оказать всю необходимую помощь в поддержке инициативы и оптимизации кода программы под конкретный дистрибутив или пакетный менеджер. Как связаться с автором, описано в разделе «Вопросы и багрепорты».
Сборка с помощью Docker
Сборка программы уже предусмотрена с использованием Docker. При этом подготовлено несколько тюнингованных платформ, которые могут быть выбраны в качестве дистрибутива для сборки программы. Среди успешно работающих дистрибутивов:
- Almalinux
- Alpine
- Arch
- Debian
- Fedora
- Gentoo
- Rocky
- Ubuntu
Ознакомиться с подробностями настроек и устанавливаемыми библиотеками можно в соответствующих Docker‑файлах в поддиректории проекта .docker/
Для сборки достаточно указать команду make, ключевое слово docker, дистрибутив debian (например), а затем цель dynamic-production или другой вариант сборки.
Пример сборки в контейнере:
make docker-gentoo-production
Команда соберёт программу в режиме production в контейнере Gentoo и сохранит готовый архив precizer_linux_<архитектура>_production.zip в корне проекта.
Инструменты сборки и библиотеки устанавливаются внутри контейнера; на основной системе достаточно только Docker. Для переносимой сборки лучше всего использовать make docker-gentoo-portable как на наиболее универсальный вариант.
Самостоятельная сборка
Для получения исходного кода требуется Git. Команды сборки выполняются из корня проекта после установки зависимостей для соответствующей операционной системы
git clone --depth=1 https://github.com/precizer/precizer.git
cd precizer
Все цели сборки учитывают переданные через окружение или командную строку переменные CPPFLAGS, CFLAGS и LDFLAGS. Обязательный режим языка -std=gnu2x (C2x с расширениями GNU) добавляется отдельно и не отключается переопределением CFLAGS
При необходимости предыдущие сборки и артефакты удаляются командой:
make purge
Linux
Следующие команды устанавливают компилятор, инструменты и заголовочные файлы библиотек, необходимые для сборки приложения. UPX сжимает копию программы для архива в целях portable, production и dynamic-production; для цели distribution он не нужен
Зависимости для запуска нужны только динамическим сборкам dynamic-production и distribution. Статические сборки portable и production включают необходимые библиотеки в исполняемый файл и не требуют перечисленных ниже пакетов для запуска
Команды установки зависимостей, используемые при автоматической сборке поддерживаемых дистрибутивов, приведены в соответствующих Dockerfile в каталоге .docker/
Arch Linux
Инструменты и библиотеки для сборки:
sudo pacman -S --needed base-devel sqlite pcre2 upx zip unzip
Для запуска динамической сборки:
sudo pacman -S --needed sqlite pcre2
Ubuntu/Debian Linux
Инструменты и библиотеки для сборки:
sudo apt update
sudo apt -y install gcc make libpcre2-dev libsqlite3-dev upx-ucl zip unzip
Для запуска динамической сборки:
sudo apt -y install libpcre2-8-0 libsqlite3-0
Alpine Linux
Инструменты и библиотеки для сборки:
sudo apk add --no-cache build-base pcre2-dev pcre2-static fts-dev sqlite-dev upx zip unzip
Для запуска динамической сборки:
sudo apk add --no-cache pcre2 sqlite-libs fts
AlmaLinux/Rocky/Fedora Linux
Инструменты и библиотеки для сборки:
Набор доступных репозиториев и названия пакетов со статическими библиотеками различаются между выпусками этих дистрибутивов. Для сборки всех вариантов нужны GCC, Make, заголовочные и статические библиотеки glibc, SQLite и PCRE2, а также UPX и ZIP:
sudo dnf -y install gcc make sqlite sqlite-devel glibc-devel pcre2 pcre2-devel upx pcre2-static glibc-static zip unzip
В AlmaLinux и Rocky Linux пакеты pcre2-static и glibc-static могут потребовать предварительного подключения репозиториев CRB, EPEL и репозитория для разработчиков
Подробные команды подключения репозиториев и установки пакетов приведены в Dockerfile соответствующего дистрибутива в каталоге .docker/
Для запуска динамической сборки:
sudo dnf -y install sqlite-libs pcre2
Gentoo Linux
Инструменты и библиотеки для сборки:
echo "dev-libs/libpcre2 static-libs" | sudo tee /etc/portage/package.use/libpcre2
sudo emerge dev-libs/libpcre2 app-arch/upx app-arch/zip app-arch/unzip
Для запуска динамической сборки:
sudo emerge dev-db/sqlite dev-libs/libpcre2
Варианты сборки с помощью Make
Доступны четыре варианта сборки: portable, production, dynamic-production и distribution. Подходящий вариант определяется требованиями к переносимости, производительности и системным библиотекам
Портируемый бинарный файл
make portable
Результатом сборки будет ZIP-архив, содержащий один статически слинкованный, самораспаковывающийся сжатый UPX файл в формате ELF, без каких-либо динамических зависимостей. Этот файл представляет собой всю программу целиком и может быть запущен практически на любом современном дистрибутиве Linux. Файл переносим между системами с той же архитектурой процессора (x64, ARM и другими)
Программа оптимизирована под максимальную переносимость
Особенности компиляции и линковки: -static -O2 -mtune=generic
Альтернатива с использованием Docker:
make docker-gentoo-portable
Вместо -gentoo- может быть указан любой из перечисленных выше дистрибутивов
Единый бинарный файл с оптимизацией под локальный CPU
make production
Архив содержит заточенный под локальный CPU, статически слинкованный, самораспаковывающийся, сжатый UPX файл в формате ELF, не нуждающийся в отдельных библиотеках. Этот файл представляет собой всю программу целиком, может быть запущен на локальном компьютере и будет использовать все возможности CPU по-максимуму
Программа оптимизирована под предельно возможную производительность на локальном железе
Особенности компиляции и линковки: -static -O3 -march=native
Альтернатива с использованием Docker:
make docker-gentoo-production
Вместо -gentoo- может быть указан любой из перечисленных выше дистрибутивов
Исполняемый файл с динамически подгружаемыми библиотеками и оптимизацией под локальный CPU
make dynamic-production
Архив содержит исполняемый файл размером около 50 килобайт в формате ELF. Он будет заточен под локальный CPU, динамически слинкован с установленными в системе библиотеками, самораспаковывающийся, сжатый UPX. Этот файл может быть успешно собран и запущен на локальном компьютере, если в системе были предварительно установлены такие библиотеки, как sqlite3, pcre2 и fts
Файл оптимизирован под максимальную производительность и минимальный размер
При работе программа использует установленные в системе динамические библиотеки. Они могут быть собраны с параметрами оптимизации, отличающимися от параметров сборки precizer, поэтому общая производительность также зависит от этих библиотек
Особенности компиляции: -O3 -march=native
Альтернатива с использованием Docker:
make docker-gentoo-dynamic-production
Вместо -gentoo- может быть указан любой из перечисленных выше дистрибутивов
Исполняемый файл для дистрибутивного пакета
make distribution
Цель distribution предназначена для сборки пакетов Gentoo, Debian, Ubuntu, Fedora и других дистрибутивов. Программа динамически связывается с установленными системными библиотеками
Сборка учитывает стандартные переменные CPPFLAGS, CFLAGS и LDFLAGS, не добавляет настройки для процессора машины, на которой выполняется сборка, не удаляет отладочные символы и не применяет UPX
Оптимизацию, усиление защиты, обработку отладочной информации и создание пакета должна выполнять сборочная система дистрибутива
Установка
Для быстрого вызова программы исполняемый файл precizer размещается в одном из каталогов, указанных в $PATH. Сборки создают архив с этим файлом в корне проекта.
macOS
На macOS статическая линковка не поддерживается. Цель macos-zip создаёт архив со сборкой для локального процессора. Сжатие UPX не применяется.
Зависимости для сборки
Для сборки требуются инструменты командной строки Xcode и зависимости из Homebrew. Они устанавливаются следующими командами:
xcode-select --install
brew install llvm sqlite pcre2
Сборка и установка
Для сборки и упаковки без оптимизации под процессор конкретного компьютера используется цель macos-zip:
make macos-zip
Результат находится в корне проекта, в ZIP-архиве. Сборка учитывает CPPFLAGS, CFLAGS и LDFLAGS и не удаляет отладочные символы. Команда make distribution доступна отдельно: она оставляет только бинарник в .builds/distribution/precizer
Для сборки с оптимизацией под локальный процессор доступна цель dynamic-production:
make dynamic-production
В этом случае результат — ./precizer_macos_<архитектура>_dynamic-production.zip
Для вызова программы по имени и без указания пути нужно поместить распакованный файл precizer в один из каталогов, указанных в $PATH
Системные библиотеки для запуска приложения
На macOS все варианты сборки только динамические. Для запуска требуются системные библиотеки из Homebrew:
brew install sqlite pcre2
Windows
Подготовка MSYS2
Для сборки Windows x64 требуется MSYS2. Команды выполняются в терминале MSYS2 MSYS, а не UCRT64 или MINGW64
Перед сборкой выполняется обновление пакетов:
pacman -Syu
Если обновление требует закрытия терминала, после подтверждения терминал MSYS2 MSYS запускается повторно, а команда выполняется ещё раз для завершения обновления. Подробности — в инструкции MSYS2
Зависимости устанавливаются командой:
pacman -S --needed git gcc make libsqlite-devel pcre2-devel zip
Получение исходного кода описано в начале раздела «Самостоятельная сборка». Все следующие команды выполняются из корня проекта в том же терминале
Команда make msys-build собирает программу в .builds/distribution/precizer.exe без упаковки. Обе цели упаковки, windows-zip и windows-exe, автоматически выполняют эту сборку
EXE с DLL рядом
Следующая команда собирает программу и создаёт ZIP-архив с EXE, необходимой DLL, лицензией, историей изменений и обоими README:
make windows-zip
Результат — архив precizer_windows_x64_portable.zip. После распаковки precizer.exe и msys-2.0.dll должны оставаться в одном каталоге. Для запуска на другом компьютере установка MSYS2 не требуется. SQLite, PCRE2 и argp уже включены в EXE
Единый самораспаковывающийся EXE
Следующие команды устанавливают дополнительные инструменты, собирают программу и создают самораспаковывающийся EXE со встроенными программой и DLL. Предварительно выполнять make windows-zip не требуется:
pacman -S --needed mingw-w64-ucrt-x86_64-gcc mingw-w64-ucrt-x86_64-binutils mingw-w64-ucrt-x86_64-upx
make windows-exe
Переключать терминал не нужно: сборка сама выбирает UCRT-компилятор. В корне проекта появится precizer_windows_x64_portable.exe. Для переноса и запуска достаточно этого файла: при запуске он самостоятельно извлекает программу и DLL в пользовательский каталог кэша
После установки всех перечисленных зависимостей оба пакета можно собрать одной командой. Эти же цели использует GitHub Actions для сборки релизов:
make windows-zip windows-exe
Исполняемый файл автоматически сжимается с помощью UPX. Для отключения сжатия используется команда:
make windows-exe UPX=true
Тестирование
Тестовый набор проверяет отдельные функции, работу приложения через командную строку и результаты обработки файлов из tests/fixtures/.
Для обычной проверки в Linux используется отладочная сборка без санитайзеров:
SLOWTEST=skip make tests-debug
Переменная SLOWTEST=skip пропускает продолжительные сценарии. Полный набор тех же тестов запускается без этой переменной:
make tests-debug
Цель make tests дополнительно включает AddressSanitizer и UndefinedBehaviorSanitizer. Этот режим требует библиотек санитайзеров и llvm-symbolizer:
make tests
Полный перечень системных пакетов и команды их установки приведены в разделе «Системные пакеты для тестирования».
КОНФИГУРАЦИОННЫЙ ФАЙЛ
Конфигурационный файл сохраняет настройки отдельной задачи: какие папки сканировать, где хранить базу и какие файлы исключать. Для разных задач можно подготовить отдельные файлы
Запуск с сохранёнными настройками
Для первого сканирования достаточно сохранить в precizer.conf путь к папке. Например, этот файл также включает отображение прогресса:
path = /mnt/storage
progress = true
Запуск из папки, в которой находится этот файл, не требует аргументов:
precizer
Программа просканирует /mnt/storage и её подпапки. База будет создана в папке запуска под именем компьютера с расширением .db. Для обновления уже существующей базы в файл добавляется update = true. При сканировании хотя бы один path обязателен
Другой конфигурационный файл можно выбрать одной из двух равнозначных команд:
precizer --config=/path/to/task.conf
precizer -g /path/to/task.conf
Относительные пути внутри конфигурации отсчитываются от папки запуска программы, даже если сам файл расположен в другом месте
Готовый precizer.conf в репозитории содержит описания настроек, значения по умолчанию и примеры. Все записи в нём закомментированы: удаление # непосредственно перед именем настройки активирует соответствующую строку
Конфигурация и командная строка
Настройки запуска задаются либо через CLI, либо в конфигурационном файле
Переданные через CLI настройки и пути отключают автоматическое чтение precizer.conf. При явном выборе файла через --config (-g) все настройки задаются в нём; добавление рабочих параметров или путей в командную строку считается ошибкой
Запросы --help, --usage, --version и их короткие формы не читают конфигурацию. Например, precizer --config=task.conf --help показывает справку без открытия файла
Если при запуске без аргументов precizer.conf отсутствует или не содержит настроек, выводится краткая справка. Ошибки в выбранном файле останавливают запуск; отсутствие или недоступность файла, явно указанного через --config, также считается ошибкой
Формат настроек
Имена настроек совпадают с длинными именами CLI-опций без начальных --: например, database, progress, ignore. Имена CLI-опций и ключи конфигурации чувствительны к регистру; дефисы обязательны. Именованные значения (full, machine, always и другие) распознаются без учёта регистра. Регистр путей, имён файлов и регулярных выражений сохраняется. Между именем и значением ставится =; разделитель : также допустим. Параметры help, usage, version и config доступны только в командной строке
Логические настройки принимают все следующие варианты без учёта регистра букв:
| Действие | Значения |
|---|---|
| Включить | true, yes, on, y, 1 |
| Выключить | false, no, off, n, 0 |
Для настройки с одним значением действует последняя запись: например, после progress = true строка progress = false выключает прогресс. Для списков, таких как ignore и include, записи добавляются. Повтор имени и строки продолжения можно использовать вместе:
ignore = "^cache/"
ignore = "^tmp/"
"^build/"
Здесь заданы три правила исключения. Непустая строка с отступом, кроме комментария, добавляет ещё одно значение к предыдущему ключу. Новые ключи записываются без отступа
Значение можно заключить в одинаковые одинарные или двойные кавычки. Снимается только внешняя пара; пробелы и обратные слеши внутри сохраняются. Например, ignore = "\.log$" и ignore = \.log$ задают одинаковое правило. Незакрытая кавычка вызывает ошибку с номером строки. Переменные вроде $HOME остаются буквальным текстом
Внутри значения # после пробела или табуляции начинает комментарий, иначе остаётся частью значения. Кавычки это правило не меняют
database = archive.db # комментарий
database = archive#1.db
ПРИМЕРЫ ИСПОЛЬЗОВАНИЯ
Пример 1
Добавить файлы в две базы данных и сравнить их между собой:
precizer --progress --database=database1.db tests/fixtures/diffs/diff1
precizer --progress --database=database2.db tests/fixtures/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 database2.db but are still present in database1.db deleted path2/AAA/ZAW/D/e/f/b_file.txt These files are present in database2.db but absent from database1.db added path1/AAA/BCB/CCC/b.txt The SHA512 checksums of these files do not match between database1.db and database2.db mismatch 2/AAA/BBB/CZC/a.txt mismatch 3/AAA/BBB/CCC/a.txt mismatch 4/AAA/BBB/CCC/a.txt mismatch path1/AAA/ZAW/D/e/f/b_file.txt mismatch path2/AAA/BCB/CCC/a.txt Comparison of database1.db and database2.db databases is complete Exit status » SUCCESS
Пример 2
Актуализация базы данных
Попробуем использовать предыдущий пример ещё раз. Первая попытка. Сообщение с предупреждением.
precizer --progress --database=database1.db tests/fixtures/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 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. Exit status » WARNING
Должен быть добавлен параметр –update. Этот параметр необходим для защиты базы данных от потери информации из-за случайного запуска.
precizer --update --progress --database=database1.db tests/fixtures/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 traversal size: 48KiB Total items: 59 Directories: 46 Files: 12 Symlinks: 1 Searching for files that no longer exist on the file system… Missing file search finished The database file database1.db has NOT been modified since the program was launched Exit status » SUCCESS
Внесём некоторые изменения:
# Modify a file
echo -n " " >> tests/fixtures/diffs/diff1/1/AAA/BCB/CCC/a.txt
# Add a new file
touch tests/fixtures/diffs/diff1/1/AAA/BCB/CCC/c.txt
# Remove a file
rm tests/fixtures/diffs/diff1/path2/AAA/ZAW/D/e/f/b_file.txt
и запустим precizer ещё раз, но уже с параметром --update:
precizer --update --progress --database=database1.db tests/fixtures/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 traversal size: 44KiB Total items: 59 Directories: 46 Files: 12 Symlinks: 1 Update mode enabled for DB database1.db File traversal started for tests/fixtures/diffs/diff1 Changes reported during this scan against the DB database1.db: rehashed 1/AAA/BCB/CCC/a.txt added as empty 1/AAA/BCB/CCC/c.txt File traversal complete Searching for files that no longer exist on the file system… Dropping DB records for missing or ignored paths in database1.db: dropped as missing path2/AAA/ZAW/D/e/f/b_file.txt Missing file search finished Start vacuuming the primary database… Primary DB vacuumed: saved 0.00%, elapsed 1ms The database file database1.db has been modified since the program was launched Total runtime: 3ms 782μs 866ns Total traversal size: 44KiB Total items: 59 Directories: 46 Files: 12 Symlinks: 1 Scan time: 759μs Scan rate: 10KiB/s Hashing time: 2μs Hashing rate: 2MiB/s Hashed data: 8B Exit status » SUCCESS
Метки изменений в выводе означают:
lsize— логический размер файла в байтах (st_size)asize— размер, выделенный на диске, в байтах (st_blocks * 512)ctime— время изменения метаданных/статусаmtime— время изменения содержимого файла
При каждом запуске precizer обходит файловую систему, после этого проверяя, есть ли запись об определённом файле в базе данных или нет. Другими словами, приоритет для программы имеет состояние файловой системы на диске.
Обход каталогов precizer работает очень похоже на работу rsync, поскольку использует похожий алгоритм.
Для обычных файлов с полной SHA512 в базе данных precizer пересчитывает контрольную сумму при изменении размера или mtime. Опция --watch-timestamps дополнительно учитывает любые изменения в метаданных о файле кроме времени последнего доступа (atime).
Любые новые файлы, удалённые файлы или те файлы, которые изменились между запусками приложения, будут обработаны и, соответственно, все изменения будут отражены в базе данных, если указан параметр --update.
Пример 3
Использование режима --silent. При включении этого режима программа ничего не выводит на экран. Это имеет смысл при использовании precizer в скриптах.
Исключение составляет режим --compare: вместе с --silent остаётся только вывод результатов сравнения. Пути с различиями выводятся с префиксами deleted, added или mismatch, без заголовков категорий
Добавим параметр –silent к предыдущему примеру:
precizer --silent --update --progress --database=database1.db tests/fixtures/diffs/diff1
В результате на экране ничего не отобразится.
Пример 4
Дополнительная информация в режиме --verbose может быть полезна для отладки.
Добавим параметр –verbose к предыдущему примеру:
precizer --verbose --update --progress --database=database1.db tests/fixtures/diffs/diff1
2026-10-25 12:05:32:835 src/show_parse_diagnostics.c:241:show_verbose_diagnostics:Configuration: rational_logger_mode=VERBOSE roots=tests/fixtures/diffs/diff1; database=database1.db; db_file_name=database1.db; verbose=yes; maxdepth=-1; silent=no; quiet-ignored=no; force=no; update=yes; watch-timestamps=no; rehash-locked=no; progress=yes; compare=no, db-drop-ignored=no, db-drop-inaccessible=no, dry-run=no, one-file-system=no, check-level=FULL, rational_logger_mode=VERBOSE, color=auto 2026-10-25 12:05:32:835 src/parse_arguments.c:837:parse_arguments:Argument parsing is finished 2026-10-25 12:05:32:835 src/paths_detect.c:036:paths_detect:Checking directory paths provided as arguments 2026-10-25 12:05:32:835 src/file_availability.c:029:file_availability:Verify that the path tests/fixtures/diffs/diff1 exists 2026-10-25 12:05:32:835 src/file_availability.c:048:file_availability:The path tests/fixtures/diffs/diff1 is exists and it is a directory 2026-10-25 12:05:32:835 src/paths_detect.c:060:paths_detect:Path detection is finished 2026-10-25 12:05:32:835 src/init_signals.c:033:init_signals:Set signal SIGUSR2 OK:pid:664206 2026-10-25 12:05:32:835 src/init_signals.c:042:init_signals:Set signal SIGINT OK:pid:664206 2026-10-25 12:05:32:835 src/init_signals.c:051:init_signals:Set signal SIGTERM OK:pid:664206 2026-10-25 12:05:32:835 src/init_signals.c:062:init_signals:Signals initialized 2026-10-25 12:05:32:835 src/db_determine_name.c:084:db_determine_name:Primary database file name: database1.db 2026-10-25 12:05:32:835 src/db_determine_name.c:087:db_determine_name:Primary database file path: database1.db 2026-10-25 12:05:32:835 src/db_determine_name.c:090:db_determine_name:Finished determining database name 2026-10-25 12:05:32:835 src/file_availability.c:029:file_availability:Verify that the path . exists 2026-10-25 12:05:32:835 src/file_availability.c:048:file_availability:The path . is exists and it is a directory 2026-10-25 12:05:32:835 src/file_availability.c:029:file_availability:Verify that the path database1.db exists 2026-10-25 12:05:32:836 src/file_availability.c:040:file_availability:The path database1.db is exists and it is a file 2026-10-25 12:05:32:836 src/db_determine_mode.c:146:db_determine_mode:Final value for config->sqlite_open_flag: SQLITE_OPEN_READWRITE 2026-10-25 12:05:32:836 src/db_determine_mode.c:147:db_determine_mode:Final value for config->db_initialize_tables: false 2026-10-25 12:05:32:836 src/db_determine_mode.c:149:db_determine_mode:DB mode determined 2026-10-25 12:05:32:836 src/db_integrity_check.c:055:db_integrity_check:Starting database file database1.db integrity check… 2026-10-25 12:05:32:836 src/db_integrity_check.c:077:db_integrity_check:The database verification level has been set to FULL 2026-10-25 12:05:32:836 src/db_integrity_check.c:116:db_integrity_check:Database database1.db has been verified and is in good condition 2026-10-25 12:05:32:837 src/db_retrieve_version.c:093:db_retrieve_version:Version number 4 found in database 2026-10-25 12:05:32:837 src/db_check_version.c:052:db_check_version:The database1.db database file is version 4 2026-10-25 12:05:32:837 src/db_check_version.c:075:db_check_version:The database database1.db is on version 4 and does not require any upgrades 2026-10-25 12:05:32:837 src/db_init.c:040:db_init:Successfully opened database database1.db 2026-10-25 12:05:32:837 src/db_init.c:142:db_init:The primary database and tables do not require initialization 2026-10-25 12:05:32:837 src/db_init.c:176:db_init:The primary database named database1.db is ready for operations 2026-10-25 12:05:32:837 src/db_init.c:208:db_init:The TEMP table the_path_id_does_not_exists is ready for runtime checks 2026-10-25 12:05:32:837 src/db_init.c:216:db_init:Database initialization process completed 2026-10-25 12:05:32:837 src/db_compare.c:316:db_compare:Database comparison mode is not enabled. Skipping comparison 2026-10-25 12:05:32:837 src/db_contains_data.c:092:db_contains_data:The database database1.db has already been created previously 2026-10-25 12:05:32:837 src/db_validate_paths.c:278:db_validate_paths:The paths written against the database and the paths passed as arguments are completely identical 2026-10-25 12:05:32:837 src/file_list.c:154:file_list:File system traversal initiated to calculate file count and storage usage 2026-10-25 12:05:32:838 src/show_statistics.c:093:show_statistics:Total traversal size: 44KiB 2026-10-25 12:05:32:838 src/show_statistics.c:094:show_statistics:Total items: 59 2026-10-25 12:05:32:838 src/show_statistics.c:095:show_statistics:Directories: 46 2026-10-25 12:05:32:838 src/show_statistics.c:096:show_statistics:Files: 12 2026-10-25 12:05:32:838 src/show_statistics.c:097:show_statistics:Symlinks: 1 2026-10-25 12:05:32:839 src/db_delete_missing_metadata.c:203:db_delete_missing_metadata:Searching for files that no longer exist on the file system… 2026-10-25 12:05:32:839 src/db_delete_missing_metadata.c:629:db_delete_missing_metadata:Missing file search finished 2026-10-25 12:05:32:839 src/db_close.c:077:db_close:The database connection has been closed 2026-10-25 12:05:32:839 src/db_primary_consider_vacuum.c:033:db_primary_consider_vacuum:No changes were made. The primary database doesn't require vacuuming 2026-10-25 12:05:32:839 src/db_check_changes.c:073:db_check_changes:The database file database1.db has NOT been modified since the program was launched 2026-10-25 12:05:32:839 src/exit_status.c:030:exit_status:The precizer completed as expected 2026-10-25 12:05:32:839 src/exit_status.c:032:exit_status:Exit status » SUCCESS 2026-10-25 12:05:32:839 src/exit_status.c:033:exit_status:Enjoy your life!
Пример 5
Исследование без рекурсии с помощью параметра --maxdepth
tree tests/fixtures/4
tests/fixtures/4
├── AAA
│ ├── BBB
│ │ ├── CCC
│ │ │ └── a.txt
│ │ └── uuu.txt
│ └── tttt.txt
└── sss.txt
4 directories, 4 files
Параметр --maxdepth со значением =0 полностью отключает рекурсию.
precizer --maxdepth=0 tests/fixtures/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 for tests/fixtures/4
Items reported during this traversal against the DB myhost.db:
added sss.txt
File traversal complete
Start vacuuming the primary database…
Primary DB vacuumed: saved -11.11%, elapsed 895μs
The brand-new primary database file myhost.db was created and modified since the program started (files were added, removed, or updated)
Total runtime: 2ms 288μs 525ns
Total traversal size: 4KiB
Total items: 3
Directories: 2
Files: 1
Symlinks: 0
Scan time: 248μs
Scan rate: 7KiB/s
Hashing time: 1μs
Hashing rate: 1MiB/s
Hashed data: 2B
Exit status » SUCCESS
Пример 6
Пример пути, который следует игнорировать. Для указания шаблона игнорирования файлов или каталогов можно использовать регулярные выражения PCRE2. Внимание! Все пути в регулярном выражении должны быть указаны как относительные.
Чтобы проверить и протестировать регулярные выражения PCRE2, можно использовать ресурс https://regex101.com
Для понимания, как выглядит относительный путь, достаточно запустить сканирование директорий без опции --ignore и посмотреть, как терминал будет отображать относительные пути, записываемые в базу данных:
% tree -L 3 tests/fixtures/diffs
tests/fixtures/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
27 directories, 0 files
precizer --ignore="^diff1/1/.*" tests/fixtures/diffs
В этом примере начальный путь сканирования — ./tests/fixtures/diffs, а сформированный путь для игнорирования — ./tests/fixtures/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 for tests/fixtures/diffs Items reported during this traversal against the DB myhost.db: ignored directory diff1/1/AAA added diff1/2/AAA/BBB/CZC/a.txt added diff1/3/AAA/BBB/CCC/a.txt added diff1/4/AAA/BBB/CCC/a.txt added diff1/path1/AAA/BCB/CCC/a.txt added diff1/path1/AAA/ZAW/A/b/c/a_file.txt added diff1/path1/AAA/ZAW/D/e/f/b_file.txt added diff1/path2/AAA/BCB/CCC/a.txt added diff1/path2/AAA/ZAW/A/b/c/a_file.txt added diff1/path2/AAA/ZAW/D/e/f/b_file.txt added diff2/1/AAA/BCB/CCC/a.txt added diff2/1/AAA/ZAW/A/b/c/a_file.txt added diff2/1/AAA/ZAW/D/e/f/b_file.txt added diff2/2/AAA/BBB/CZC/a.txt added diff2/3/AAA/BBB/CCC/a.txt added diff2/4/AAA/BBB/CCC/a.txt added diff2/path1/AAA/BCB/CCC/a.txt added diff2/path1/AAA/BCB/CCC/b.txt added diff2/path1/AAA/ZAW/A/b/c/a_file.txt added diff2/path1/AAA/ZAW/D/e/f/b_file.txt added diff2/path2/AAA/BCB/CCC/a.txt added diff2/path2/AAA/ZAW/A/b/c/a_file.txt File traversal complete Start vacuuming the primary database… Primary DB vacuumed: saved -11.11%, elapsed 1ms The brand-new primary database file myhost.db was created and modified since the program started (files were added, removed, or updated) Total runtime: 4ms 444μs 867ns Total traversal size: 84KiB Total items: 103 Directories: 81 Files: 21 Symlinks: 1 Scan time: 1ms Scan rate: 48KiB/s Hashing time: 28μs Hashing rate: 2MiB/s Hashed data: 86B Exit status » SUCCESS
Повторим тот же пример, но без опции --ignore, чтобы добавить три ранее проигнорированных файла:
precizer --update tests/fixtures/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 Update mode enabled for DB myhost.db File traversal started for tests/fixtures/diffs Changes reported during this scan against the DB myhost.db: added diff1/1/AAA/BCB/CCC/a.txt added diff1/1/AAA/ZAW/A/b/c/a_file.txt added diff1/1/AAA/ZAW/D/e/f/b_file.txt File traversal complete Searching for files that no longer exist on the file system… Missing file search finished Start vacuuming the primary database… Primary DB vacuumed: saved 0.00%, elapsed 729μs The database file myhost.db has been modified since the program was launched Total runtime: 2ms 756μs 88ns Total traversal size: 96KiB Total items: 115 Directories: 90 Files: 24 Symlinks: 1 Scan time: 912μs Scan rate: 11KiB/s Hashing time: 4μs Hashing rate: 2MiB/s Hashed data: 11B Exit status » SUCCESS
Пример 7
Продолжение предыдущего примера Пример 6.
Несколько регулярных выражений для игнорирования можно указать одновременно, повторив опцию --ignore несколько раз.
База данных будет очищена от упоминаний файлов, соответствующих регулярным выражениям из аргументов --ignore: “diff1/1/.*” и “diff2/1/.*”
Параметр --db-drop-ignored должен быть указан дополнительно, чтобы удалить из базы данных упоминание файлов, соответствующих регулярным выражениям, переданным через опции --ignore.
На файловой системе не было изменений, но игнорируемые файлы будут удалены из БД.
# Обновить базу данных, удалив информацию о тех файлах, которые были указаны как игнорируемые:
precizer \
--update \
--db-drop-ignored \
--ignore="^diff1/1/.*" \
--ignore="^diff2/1/.*" \
tests/fixtures/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 Update mode enabled for DB myhost.db File traversal started for tests/fixtures/diffs Changes reported during this scan against the DB myhost.db: ignored directory diff1/1/AAA ignored directory diff2/1/AAA File traversal complete Searching for files that no longer exist on the file system… Dropping DB records for missing or ignored paths in myhost.db: dropped as ignored diff1/1/AAA/BCB/CCC/a.txt dropped as ignored diff1/1/AAA/ZAW/A/b/c/a_file.txt dropped as ignored diff1/1/AAA/ZAW/D/e/f/b_file.txt dropped as ignored diff2/1/AAA/BCB/CCC/a.txt dropped as ignored diff2/1/AAA/ZAW/A/b/c/a_file.txt dropped as ignored diff2/1/AAA/ZAW/D/e/f/b_file.txt Missing file search finished Start vacuuming the primary database… Primary DB vacuumed: saved 16.67%, elapsed 671μs The database file myhost.db has been modified since the program was launched Total runtime: 2ms 713μs 359ns Total traversal size: 72KiB Total items: 91 Directories: 72 Files: 18 Symlinks: 1 Scan time: 660μs Scan rate: n/a Hashing time: 0ns Hashing rate: n/a Hashed data: 0B Exit status » SUCCESS
Пример 8
Использование параметров --ignore вместе с --include
# Удалим старую базу данных и создадим новую, наполним её данными:
rm -i "${HOST}.db"
precizer tests/fixtures/diffs
Усложним задачу с использованием регулярных выражений.
Регулярные выражения PCRE2 для относительных путей, которые необходимо включить. Включаем указанные относительные пути, даже если они были исключены с помощью одного или нескольких параметров --ignore. Несколько регулярных выражений могут быть указаны с помощью --include
Чтобы проверить и протестировать регулярные выражения PCRE2, можно использовать ресурс https://regex101.com
DB будет очищена от упоминаний файлов, соответствующих регулярным выражениям из аргументов --ignore: “^.*/path2/.*” и “diff2/.*”, но опция --include оставит в базе данных пути, соответствующие заданным шаблонам.
Параметр --db-drop-ignored должен быть указан дополнительно, чтобы удалить из базы данных упоминание файлов, соответствующих регулярным выражениям, переданным через опции --ignore.
# Обновить базу данных, удалив информацию о тех файлах, которые были указаны как игнорируемые за исключением шаблонов путей из --include
precizer --update \
--progress \
--ignore="^.*/path2/.*" \
--ignore="^diff2/.*" \
--include="^diff2/1/AAA/ZAW/A/b/c/.*" \
--include="^diff2/path1/AAA/ZAW/.*" \
--include="^diff1/path2/AAA/ZAW/A/b/c/a_file\..*" \
--db-drop-ignored \
tests/fixtures/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 File system traversal initiated to calculate file count and storage usage Total traversal size: 96KiB Total items: 115 Directories: 90 Files: 24 Symlinks: 1 Update mode enabled for DB myhost.db File traversal started for tests/fixtures/diffs Changes reported during this scan against the DB myhost.db: ignored directory diff1/path2/AAA ignored directory diff1/path2/AAA/BCB ignored directory diff1/path2/AAA/BCB/CCC ignored directory diff1/path2/AAA/ZAW ignored directory diff1/path2/AAA/ZAW/A ignored directory diff1/path2/AAA/ZAW/A/b ignored directory diff1/path2/AAA/ZAW/A/b/c ignored directory diff1/path2/AAA/ZAW/D ignored directory diff1/path2/AAA/ZAW/D/e ignored directory diff1/path2/AAA/ZAW/D/e/f ignored directory diff2/1 ignored directory diff2/1/AAA ignored directory diff2/1/AAA/BCB ignored directory diff2/1/AAA/BCB/CCC ignored directory diff2/1/AAA/ZAW ignored directory diff2/1/AAA/ZAW/A ignored directory diff2/1/AAA/ZAW/A/b ignored directory diff2/1/AAA/ZAW/A/b/c ignored directory diff2/1/AAA/ZAW/D ignored directory diff2/1/AAA/ZAW/D/e ignored directory diff2/1/AAA/ZAW/D/e/f ignored directory diff2/2 ignored directory diff2/2/AAA ignored directory diff2/2/AAA/BBB ignored directory diff2/2/AAA/BBB/CZC ignored directory diff2/3 ignored directory diff2/3/AAA ignored directory diff2/3/AAA/BBB ignored directory diff2/3/AAA/BBB/CCC ignored directory diff2/4 ignored directory diff2/4/AAA ignored directory diff2/4/AAA/BBB ignored directory diff2/4/AAA/BBB/CCC ignored directory diff2/path1 ignored directory diff2/path1/AAA ignored directory diff2/path1/AAA/BCB ignored directory diff2/path1/AAA/BCB/CCC ignored directory diff2/path1/AAA/ZAW included directory diff2/path1/AAA/ZAW/A included directory diff2/path1/AAA/ZAW/A/b included directory diff2/path1/AAA/ZAW/A/b/c included directory diff2/path1/AAA/ZAW/D included directory diff2/path1/AAA/ZAW/D/e included directory diff2/path1/AAA/ZAW/D/e/f ignored directory diff2/path2 ignored directory diff2/path2/AAA ignored directory diff2/path2/AAA/BCB ignored directory diff2/path2/AAA/BCB/CCC ignored directory diff2/path2/AAA/ZAW ignored directory diff2/path2/AAA/ZAW/A ignored directory diff2/path2/AAA/ZAW/A/b ignored directory diff2/path2/AAA/ZAW/A/b/c File traversal complete Searching for files that no longer exist on the file system… Dropping DB records for missing or ignored paths in myhost.db: dropped as ignored diff1/path2/AAA/BCB/CCC/a.txt dropped as ignored diff1/path2/AAA/ZAW/D/e/f/b_file.txt dropped as ignored diff2/1/AAA/BCB/CCC/a.txt dropped as ignored diff2/1/AAA/ZAW/D/e/f/b_file.txt dropped as ignored diff2/2/AAA/BBB/CZC/a.txt dropped as ignored diff2/3/AAA/BBB/CCC/a.txt dropped as ignored diff2/4/AAA/BBB/CCC/a.txt dropped as ignored diff2/path1/AAA/BCB/CCC/a.txt dropped as ignored diff2/path1/AAA/BCB/CCC/b.txt dropped as ignored diff2/path2/AAA/BCB/CCC/a.txt dropped as ignored diff2/path2/AAA/ZAW/A/b/c/a_file.txt Missing file search finished Warnings and errors encountered: dropped as ignored diff1/path2/AAA/BCB/CCC/a.txt dropped as ignored diff1/path2/AAA/ZAW/D/e/f/b_file.txt dropped as ignored diff2/1/AAA/BCB/CCC/a.txt dropped as ignored diff2/1/AAA/ZAW/D/e/f/b_file.txt dropped as ignored diff2/2/AAA/BBB/CZC/a.txt dropped as ignored diff2/3/AAA/BBB/CCC/a.txt dropped as ignored diff2/4/AAA/BBB/CCC/a.txt dropped as ignored diff2/path1/AAA/BCB/CCC/a.txt dropped as ignored diff2/path1/AAA/BCB/CCC/b.txt dropped as ignored diff2/path2/AAA/BCB/CCC/a.txt dropped as ignored diff2/path2/AAA/ZAW/A/b/c/a_file.txt Start vacuuming the primary database… Primary DB vacuumed: saved 16.67%, elapsed 658μs The database file myhost.db has been modified since the program was launched Total runtime: 3ms 656μs 611ns Total traversal size: 96KiB Total items: 115 Directories: 90 Files: 24 Symlinks: 1 Scan time: 1ms Scan rate: n/a Hashing time: 0ns Hashing rate: n/a Hashed data: 0B Exit status » SUCCESS
Те же фильтры в режиме --compare
Та же комбинация --ignore и --include работает и при сравнении двух баз данных. Фильтры определяют не только то, какие строки будут напечатаны, но и то, какая часть относительных путей считается входящей в отчёт сравнения. Поэтому итоговые сводки и сообщения об идентичности относятся только к этой отфильтрованной области
# Продолжая Пример 1, вернём в отчёт только один путь из скрытой группы различий
precizer --compare \
--ignore="^(?:2|3|4)/.*" \
--ignore="^path1/.*" \
--ignore="^path2/.*" \
--include="^2/AAA/BBB/CZC/a\.txt$" \
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
The SHA512 checksums of these files do not match between database1.db and database2.db
mismatch 2/AAA/BBB/CZC/a.txt
Comparison of database1.db and database2.db databases is complete
Exit status » SUCCESS
В этом примере все различия из путей 2/, 3/, 4/, path1/ и path2/ сначала выводятся из области отчёта сравнения, а затем --include возвращает обратно только 2/AAA/BBB/CZC/a.txt. В результате в отчёте снова появится именно этот путь, а остальные скрытые различия останутся вне итоговых списков и сводок
Пример 9
Защита неизменяемых архивов с помощью --lock-checksum
Опция --lock-checksum нужна для архивных каталогов или файлов, содержимое которых не должно переписываться. Она принимает регулярные выражения PCRE2 для относительных путей (тот же формат, что и у --ignore). Пути, совпавшие с любым шаблоном, записываются в БД один раз. После этого их контрольные суммы не пересчитываются даже при --update. Любое дальнейшее изменение размера или временных меток (при использовании режима --watch-timestamps), исчезновение файла с диска, потеря доступа на чтение или неожиданный сбой проверки доступа считается порчей данных и выводится соответствующее сообщение об ошибке вместо обновления записи. Для исчезнувшего или недоступного заблокированного файла запись в БД сохраняется, чтобы нарушение не терялось между последующими запусками. Защита заблокированного пути имеет приоритет над --ignore, --db-drop-ignored и --db-drop-inaccessible: совпадение с этими фильтрами не должно молча удалять такую запись из БД. Та же защита сохраняется и в ситуации, когда --include возвращает только часть ранее скрытого поддерева. Несколько шаблонов могут быть указаны повторением добавления опции --lock-checksum:
precizer \
--lock-checksum="^archive/2024/.*" \
--lock-checksum="^snapshots/monthly/.*" \
/mnt/storage
В последующих запусках необходимо сохранять те же шаблоны блокировки при актуализации базы:
precizer \
--update \
--lock-checksum="^archive/2024/.*" \
--lock-checksum="^snapshots/monthly/.*" \
/mnt/storage
Файлы вне шаблонов обновляются в обычном порядке. Для заблокированных через --lock-checksum записей любое расхождение сразу становится заметным и код возврата при завершении precizer будет больше нуля и это можно использовать в скриптах.
Пример 10
Глубокая проверка заблокированных данных с помощью --rehash-locked
Опция --rehash-locked используется только вместе с --lock-checksum. При её включении каждый файл, попавший под шаблон блокировки и уже присутствующий в базе данных, перечитывается побайтно при каждой актуализации базы данных через --update. Для такого файла заново вычисляется контрольная сумма SHA512 и выполняется сравнение с сохранённым значением. Это позволяет выполнить дополнительный аудит неизменяемых архивов ценой увеличенного дискового ввода-вывода. Наличие или отсутствие параметра --watch-timestamps не влияет на работу --rehash-locked. Если пересчитанная сумма и размер совпадают с записью в БД, файл считается консистентным; если при этом на диске отличаются ctime/mtime, новые значения сохраняются в базе данных. Если заблокированный путь одновременно совпадает с --ignore, параметр --rehash-locked всё равно обязан пройти по этому пути и выполнить проверку, а не пропустить её.
precizer --update \
--lock-checksum="^archive/2024/.*" \
--rehash-locked \
/mnt/storage
Чтобы увидеть взаимодействие параметров командной строки --lock-checksum, --watch-timestamps и --rehash-locked, рассмотрим несколько случаев:
- Размер файла отличается Если размер, записанный в базе, не совпадает с размером на диске, файл будет помечен как «нарушение заблокированной контрольной суммы» вне зависимости от
--watch-timestampsи--rehash-locked. Пересчитывать контрольную сумму бессмысленно: при изменившемся размере она всё равно не совпадёт. - Совпадает размер файла, не указаны ни
--watch-timestamps, ни--rehash-lockedпоэтому остальные значения, такие как SHA512 и временные метки не учитываются и файл считается полностью консистентным, программа завершится со статусомSUCCESS. - Совпадают размер и временные метки; указана
--watch-timestampsи не указана опция--rehash-lockedФайл считается полностью консистентным, он не появится в выводе, а статус завершения программы будетSUCCESS. - Размер совпадает, временные метки различаются; указана
--watch-timestampsи не указана--rehash-lockedФайл будет отмечен как «нарушение заблокированной контрольной суммы» только из-за различающихся временных меток, и программа завершится со статусомWARNING. - Размер совпадает, указан параметр
--rehash-lockedДля проверки учитываются только контрольная сумма и размер, записанные в базе данных. Если они совпадают, файл считается консистентным. Если на диске изменились временные метки, то новые значения ctime/mtime будут сохранены в базе данных независимо от того был ли указан--watch-timestampsили нет.
Подробные примеры поведения в сложных ситуациях собраны в тесте №30 (tests/src/test0030.c). Там проверяются удаления заблокированных файлов, потеря доступа, сбои проверки доступа и взаимодействие с --ignore, --include, --db-drop-ignored и --db-drop-inaccessible.
Практический сценарий: выполнять ежедневное быстрое сканирование без --rehash-locked (и при необходимости без --watch-timestamps), чтобы поддерживать БД в актуальном состоянии, а реже запускать углублённый аудит с --rehash-locked, который гарантированно сверяет контрольные суммы «замороженных» данных.
Пример 11
Сброс записей о недоступных файлах с помощью --db-drop-inaccessible
По умолчанию, если файл недоступен из-за прав доступа, его запись в базе данных сохраняется при --update, чтобы избежать случайной потери данных. Для удаления таких записей используется дополнительный параметр командной строки --db-drop-inaccessible:
precizer --update --db-drop-inaccessible /mnt/storage
dropped as inaccessible archive/secret.bin
Важно: --db-drop-inaccessible относится не к удалённым файлам, а к файлам, которые сейчас нельзя прочитать или для которых не удалось надёжно проверить доступ. Например, могли измениться права, владелец, ACL, или файловая система временно вернула ошибку доступа. По умолчанию такие записи остаются в БД, чтобы временная проблема с доступом не стёрла полезную историю. Если вы уверены, что такие записи больше не нужны, добавьте --db-drop-inaccessible.
Если же файл или один из каталогов в его пути вообще не виден в файловой системе, precizer считает удалённой обычную запись, не защищённую через --lock-checksum, и при --update удалит её из БД без дополнительных опций. Программа не может сама отличить настоящее удаление от ситуации, когда точка монтирования существует, но нужный том не подключился и поэтому каталог выглядит пустым. Перед обновлением БД для внешних, сетевых или съёмных томов сначала убедитесь, что нужный том действительно смонтирован. Для важных архивных путей используйте --lock-checksum: тогда исчезнувший или недоступный файл будет показан как предупреждение, а запись в БД сохранится.
ОСНОВНЫЕ ПАРАМЕТРЫ КОМАНДНОЙ СТРОКИ
Ниже описаны основные опции для повседневной работы. В режиме сканирования после опций указывают исходные каталоги, а с --compare — два файла баз данных. Полный список опций и подробную справку можно получить командой:
precizer --help
Сканирование и обновление базы
-
--database=FILE,-d FILE— Выбрать файл базы данных. По умолчанию используется имя хоста с расширением.db -
--update,-u— Разрешить обновление существующей базы по результатам сканирования: добавление новых файлов, обновление изменившихся и удаление записей об исчезнувших файлах. Используйте те же исходные каталоги, что и при создании базы -
--watch-timestamps,-T— Учитывать изменения метаданныхctimeв дополнение к размеру файла при определении необходимости пересчитать контрольную сумму -
--dry-run,-n— Выполнить пробный обход без записи в базу данных. Вариант--dry-run=with-checksumsдополнительно читает файлы и вычисляет контрольные суммы. На--compareэта опция не влияет
--update не означает полный пересчёт всех контрольных сумм. Для обычных файлов с уже сохранённой полной SHA512 пересчёт запускается при изменении размера или mtime. С --watch-timestamps также учитываются изменения ctime и количества занятых блоков на диске. Правила защиты архивных файлов через --lock-checksum описаны в примере 9, а их принудительная проверка — в примере 10
Сравнение баз
Выбор баз для сравнения
Параметр --compare (-c) сравнивает две базы по относительным путям и контрольным суммам. В CLI после него указываются пути к двум файлам баз данных:
precizer --compare database1.db database2.db
В precizer.conf каждый путь задаётся отдельной записью compare:
compare = database1.db
compare = database2.db
Второй путь также можно записать на следующей строке с отступом:
compare = database1.db
database2.db
Имена файлов могут содержать пробелы, например: compare = my database.db
Фильтрация категорий отчёта сравнения
По умолчанию сравнение показывает все три категории различий. Параметр compare-filter позволяет выбрать нужные: checksum-mismatch — файлы с одинаковыми относительными путями, но разными контрольными суммами; first-source — файлы, присутствующие в первой базе и отсутствующие во второй; second-source — присутствующие во второй и отсутствующие в первой. Параметр можно указывать несколько раз в любых сочетаниях: в отчёт попадут все выбранные категории. Используется в режиме сравнения
В CLI значение передаётся через --compare-filter=TYPE или -F TYPE:
precizer --compare --compare-filter=checksum-mismatch database1.db database2.db
precizer --compare --compare-filter=first-source database1.db database2.db
precizer --compare \
--compare-filter=first-source \
--compare-filter=second-source \
database1.db database2.db
В последнем примере выводятся только пути, присутствующие в одной базе и отсутствующие в другой, а различия SHA512 для общих путей не показываются
В режиме --compare параметры --ignore и --include ограничивают ту область относительных путей, по которой строится отчёт сравнения. Если фильтры скрывают часть различий, итоговые сообщения об идентичности относятся только к оставшейся отфильтрованной области. Пути, возвращённые через --include, снова участвуют и в списках различий, и в итоговых сводках
Выбор файлов и глубина обхода
-
--ignore=REGEXP,-e REGEXP— Исключить пути, совпадающие с регулярным выражением PCRE2 -
--include=REGEXP,-i REGEXP— Вернуть пути, исключённые через--ignore. Сама по себе эта опция не ограничивает обработку только совпавшими путями -
--maxdepth=N,-m N— Ограничить глубину обхода. Исходный каталог имеет глубину0;--maxdepth=0обрабатывает файлы непосредственно в нём, не заходя в подкаталоги
Шаблоны --ignore и --include задаются для относительных путей от исходного каталога. Обе опции можно повторять. В режиме --compare эти фильтры ограничивают и списки различий, и область, для которой выводятся итоговые сообщения об идентичности. Исключение через --ignore само по себе не удаляет существующие записи из базы; управление таким удалением описано в примере 7
Форматы вывода
Параметр --output (-O) выбирает формат вывода:
full— подробный вывод с заголовками, пояснениями и итогами. Используется по умолчаниюcompact— краткий вывод, удобный для формирования автоматизированных отчётов: сообщения о файлах без заголовков, прогресса и итоговой статистикиmachine— такой же краткий вывод для разбора скриптами, по умолчанию без цвета
В режимах full и compact вывод в терминале дополнительно расцвечивается для лучшего визуального восприятия. Режим machine предназначен для разбора скриптами, которому подсветка не нужна, поэтому по умолчанию выводится простой текст без цвета
Пример формирования компактного отчёта:
precizer --output=compact --database=files.db /data
Примеры строк при сканировании в compact и machine:
added [as new] notes/report.txt rehashed [file] notes/archive.txt ignored [not added] cache/session.tmp
В режиме machine вывод имеет вид: действие [пояснение] путь. После слова-действия и после закрывающей квадратной скобки стоит один пробел. Вся оставшаяся чать строки это путь к файлу, включая содержащиеся в нём пробелы, скобки и любые другие символы. Текст в квадратных скобках имеет второстепенное значение и специально заключён в них, чтобы его можно было легко отфильтровать с помощью регулярных выражений.
Пример разбора с помощью awk: $1 — действие, $2 — пояснение без скобок, $3 — весь путь.
precizer --output=machine /data |
awk -F ' \\[|\\] ' '
/^[^ ]+ \[[^]]*\] / {
$3 = substr($0, length($1) + length($2) + 5)
print $1, $2, $3
}
'
В этих форматах --verbose добавляет сведения об изменившихся метаданных:
rehashed [changed: lsize was:1KiB, now:2KiB] notes/report.txt
При сравнении БД строки имеют вид:
deleted notes/old.txt added notes/new.txt mismatch notes/report.txt
Типы вывода
-
--progress,-p— Показывать ход обработки и объём данных. Для оценки прогресса программа сначала выполняет дополнительный обход и подсчёт файлов -
--verbose,-v— Выводить подробные диагностические сообщения для разбора работы программы -
--silent,-s— Подавить обычный вывод. В режиме--compareвыводятся только строкиdeleted PATH,added PATHиmismatch PATH, без заголовков категорий
Цвет и оформление текста
Параметр --color=auto|always|never управляет цветом и выделением текста, например полужирным шрифтом, в сообщениях программы. Значение обязательно: используйте, например, --color=never или короткую форму -S never
auto— режим по умолчанию. Оформление включено при выводе в терминал, в том числе псевдотерминал, и выключено при выводе в файл или pipe. В CI, cron и системной службе без терминала вывод также будет без оформленияalways— добавлять ANSI-последовательности оформления даже при выводе в файл или pipenever— не добавлять ANSI-последовательности оформления, включая сброс стиля, даже при выводе в терминал
В режиме auto наличие переменной окружения NO_COLOR, даже с пустым значением, или значение TERM=dumb отключает оформление. Это правило действует и при явном --color=auto. Режимы always и never имеют приоритет над этими переменными
Проверяется именно поток, в который выводится сообщение. Например, при перенаправлении stdout в файл сообщения в этом потоке остаются без оформления в режиме auto, даже если stderr всё ещё подключён к терминалу. Режим auto определяет подключение к терминалу, но не проверяет, какие цвета и эффекты он поддерживает
Примеры для двух уже существующих баз данных first.db и second.db:
# Автоматически включать оформление при выводе в интерактивный терминал
precizer --compare --color=auto first.db second.db
# Сохранить отчёт сравнения без оформления в режиме auto по умолчанию
precizer --compare first.db second.db > comparison.txt
# Сохранить оформление при передаче отчёта другой программе через pipe
precizer --compare --color=always first.db second.db | cat
# Отключить оформление даже при выводе в интерактивный терминал
precizer --compare -S never first.db second.db
# Отключить автоматическое оформление через переменную окружения
NO_COLOR=1 precizer --compare first.db second.db
УСТРАНЕНИЕ НЕПОЛАДОК (ТРАБЛШУТИНГ)
Антивирус замедляет работу под Windows
Антивирусная защита в реальном времени может значительно замедлять обход файлов и расчёт контрольных сумм, в отдельных случаях — на один-два порядка. Причина в том, что антивирус проверяет каждый файл при обращении. Для ускорения работы обрабатываемые каталоги рекомендуется добавить в исключения проверки в реальном времени.
precizer считывает каждый байт всех файлов в указанной директории для расчёта контрольной суммы, но НЕ запускает файлы и НЕ исполняет их содержимого. Для самого расчёта контрольных сумм антивирус не требуется.
Медленный проход по файлам, медленный расчёт контрольных сумм, медленная запись в БД. Или решение проблемы под названием «ВСЁ МЕДЛЕННО»
Чтобы выяснить причину, попробуйте запустить precizer в режиме --dry-run или --dry-run=with-checksums.
--dry-run рекурсивно проходит по Файловой Системе. В этом режиме, кроме обхода дерева файлов, больше ничего не выполняется. Можно добавить --progress — тогда добавится подсчёт занимаемого файлами места и количества файлов, но записи в БД не будет. В этом режиме можно проверить доступность ФС и частично — аппаратные возможности. Если медленно даже с --dry-run, то маловероятно, что причина в самой программе precizer.
Режим --dry-run=with-checksums отличается от --dry-run только тем, что каждый встреченный файл будет полностью (побайтово) считан с диска, и для него будет рассчитана контрольная сумма. Это значительно более ресурсоёмкий процесс, практически идентичный реальной работе программы. Режим полностью раскрывает аппаратный потенциал, но при этом не делает записей в БД. Если при этом указать --progress, то после прохода по файловой системе будет показан статус: количество байт, которые прошли через хеширование, а так же средняя скорость хеширования в B/s Показатель скорости хеширования можно сравнивать с результатами сторонних бенчмарков для поиска «бутылочного горлышка».
Возможна ситуация, когда даже с --dry-run=with-checksums программа работает очень быстро, но в режиме реальной работы (без Dry-Run) наблюдается заметная деградация производительности, особенно при массовых добавлениях или изменениях в БД. В этой ситуации нужно проверить ФС, на которой расположен файл базы данных. Именно там может скрываться причина.
База данных SQLite открывается программой precizer с такими параметрами, чтобы максимально сохранить уже записанное и всеми силами противостоять повреждению файла БД. Однако это предполагает больше дисковых I/O-операций и больше синхронизаций ФС с блочным устройством. На практике SQLite действительно очень быстрая БД и обычно не является «слабым звеном». Но если ФС с компрессией, сетевая или просто медленная, это может ощутимо отразиться на производительности программы в целом.
Например, при массовых добавлениях precizer ждёт, когда информация о файле будет записана в БД и транзакция будет завершена, и только потом переходит к следующему файлу. В такой ситуации для решения проблем производительности имеет смысл попробовать временно разместить файл .db, например, на tmpfs, — это может значительно увеличить общую производительность и понять где именно кроется проблема.
Если по-прежнему всё медленно в любых режимах, то имеет смысл проверить:
Целостность файловой системы
Сделайте системные проверки ФС, на которой делаются слепки контрольных сумм файлов, а также той ФС, где хранится и обновляется файл базы данных .db. Наблюдаемые просадки производительности могут быть связаны с логическими проблемами на уровне ФС.
Аппаратные возможности:
Скорость диска
Файлы считываются полностью и побайтово. Производительность дисковой подсистемы прямо пропорциональна скорости работы precizer. Программа работает поверх ФС как с более высоким слоем абстракции, а не с блочными устройствами напрямую. Любые логические ошибки ФС имеют значение.
Падение производительности может сильно зависеть от выбранной ФС. Например, скорость обработки файлов из смонтированной точки NFS может упираться в производительность сети и заметно отличаться от скорости доступа к ФС с отключённым atime на локальном диске NVMe (atime — access time, метка «время последнего доступа» к файлу). Используйте сторонние утилиты для проверки производительности файловой подсистемы.
Производительность CPU
Расчёт контрольных сумм — это чистая математика и достаточно трудоёмкий процесс. Современные процессоры справляются с этим незаметно быстро, но имеет смысл убедиться, что производительность не деградирует из-за разделяемых ресурсов виртуальных CPU в случае контейнеризации или виртуализации. Используйте сторонние системы мониторинга и бенчмарки для проверки производительности CPU.
Матрица диагностики узких мест
| Шаг | Режим/команда | Что проверяем | Если здесь медленно | Что делать дальше |
|---|---|---|---|---|
| 1 | precizer –dry-run | Доступность ФС, скорость обхода дерева файлов, базовая скорость I/O | Вероятнее всего проблема вне precizer: ФС/диск/сеть/нагрузка |
Проверить ФС и подсистему хранения, состояние монтирования, нагрузку системы |
| 2 | precizer –dry-run=with-checksums | Реальную скорость чтения файлов + вычисления checksum (без БД) | Узкое место: чтение данных (диск/сеть/ФС) или CPU (реже) | Проверить скорость диска/сети, параметры ФС, ограничение ресурсов CPU (виртуализация/контейнеры) |
| 3 | Реальный режим (без Dry-Run) | Влияние записи в БД (SQLite) и транзакций | Часто проблема в ФС, где лежит .db (медленная/сетевая/компрессия) |
Проверить ФС под .db, попробовать временно перенести .db на быстрый носитель или tmpfs |
АЛЬТЕРНАТИВЫ
Инструменты с открытым исходным кодом для проверки целостности, сравнения файлов и резервного копирования. Другие программы: alternativeto.net
- AIDE — aide.github.io
- Назначение: контроль целостности файлов и каталогов для выявления изменений относительно эталонного состояния. Проверяет контрольные суммы, права, владельцев, размеры и временные метки. Поддержка ACL, расширенных атрибутов и SELinux зависит от сборки
- Платформы: Linux и другие Unix-подобные системы. Язык: C
- Правила включения и исключения задаются регулярными выражениями. База хранится в текстовом формате, доступно сжатие gzip
- Samhain — la-samhna.de/samhain
- Назначение: обнаружение признаков вторжения на компьютерах и серверах. Проверяет целостность файлов, анализирует журналы и ищет признаки руткитов
- Платформы: Linux и другие POSIX-системы; Windows через Cygwin. Язык: C
- Работает как отдельно на одном компьютере, так и с центральным сервером. Поддерживает PGP-подписи баз и конфигурации
- OSSEC — ossec.net
- Назначение: обнаружение вторжений и реагирование на события безопасности компьютеров и серверов. Объединяет анализ журналов, проверку целостности файлов и централизованный сбор событий от агентов
- Платформы агентов: Linux, Windows, macOS, *BSD и другие Unix-системы. Основной язык: C
- Модуль Syscheck проверяет содержимое и атрибуты файлов. В Linux и Windows доступно отслеживание изменений содержимого в реальном времени; другие проверки выполняются при сканировании
- Open Source Tripwire — github.com/Tripwire/tripwire-open-source
- Назначение: выявление изменений файлов и каталогов и уведомление об отличиях от эталонной базы. Политика задаёт пути и проверяемые свойства, включая контрольные суммы, права и владельцев
- Платформы: Linux, macOS, *BSD и другие POSIX-подобные системы; Windows через Cygwin. Язык: C++
- Конфигурация, политика и база подписываются ключами; отчёты также могут быть подписаны. Подтверждённые изменения можно выборочно внести в эталонную базу
- integrit — github.com/integrit/integrit
- Назначение: проверка целостности файлов путём сравнения текущего состояния с эталонной базой. За тот же проход может создать новую базу состояния
- Платформы: Unix-подобные системы. Язык: C
- Использует формат cdb и контрольные суммы RIPEMD-160. Поддерживает правила для путей и вывод отчёта в XML
- mtree (NetBSD mtree) — man.netbsd.org/mtree.8
- Назначение: описание состава и свойств дерева каталогов и проверка файловой системы на соответствие этому описанию. Текстовая спецификация может содержать типы объектов, права, владельцев, размеры, временные метки и контрольные суммы, включая SHA-256 и SHA-512
- Вариант утилиты из NetBSD. Язык: C
- Может сравнивать две спецификации. По отдельным параметрам также исправляет права и владельцев или создаёт недостающие каталоги
- hashdeep (md5deep/sha*deep) — github.com/jessek/hashdeep
- Назначение: массовое вычисление контрольных сумм файлов и аудит наборов файлов по ранее сохранённым спискам хешей. Поддерживает рекурсивный обход каталогов
- Платформы: Windows и POSIX-системы, включая Linux и macOS. Языки: C++ и C
- Режим аудита сравнивает файлы с сохранённым списком и сообщает о несовпадениях, новых и отсутствующих файлах
- hashit — github.com/boyter/hashit
- Назначение: вычисление нескольких хешей файлов из командной строки. Поддерживает разные алгоритмы и параллельную обработку файлов
- Платформы: Linux, Windows, macOS. Язык: Go
- Поддерживает текстовый вывод, JSON, форматы sum и hashdeep, а также SQLite. Режим
--auditпроверяет файлы по списку в формате hashdeep
- RHash — github.com/rhash/RHash
- Назначение: вычисление и проверка контрольных сумм для контроля целостности данных при хранении и передаче. Поддерживает рекурсивный обход и несколько алгоритмов за один проход
- Платформы: Linux, Windows, macOS и другие Unix-системы. Язык: C
- Работает со списками контрольных сумм в разных форматах, включая SFV и BSD, создаёт magnet-ссылки и дополняет списки сумм записями о новых файлах
- rsync — rsync.samba.org
- Назначение: копирование и синхронизация файлов локально или между компьютерами с сокращением объёма передачи за счёт передачи различий. По умолчанию необходимость передачи определяется по размеру и времени изменения;
--checksumвключает сравнение содержимого по контрольным суммам - Платформы: Unix-подобные системы; Windows через Cygwin. Основной язык: C
--dry-runпоказывает предполагаемые изменения без копирования. Параметры--partialи--partial-dirсохраняют частично переданные файлы для повторного использования при следующем запуске
- Назначение: копирование и синхронизация файлов локально или между компьютерами с сокращением объёма передачи за счёт передачи различий. По умолчанию необходимость передачи определяется по размеру и времени изменения;
- rclone — rclone.org
- Назначение: управление файлами в облачных и других удалённых хранилищах, а также обмен данными между ними и локальными каталогами. Поддерживает копирование, синхронизацию и проверку файлов
- Платформы: Linux, Windows, macOS, FreeBSD и другие системы. Язык: Go
rclone checkсравнивает размеры и доступные хеши без изменения файлов. С--downloadчитает и сравнивает содержимое, в том числе когда хранилище не предоставляет хеши
- QuickHash GUI — github.com/tedsmith/quickhash
- Назначение: вычисление хешей и сравнение данных через графический интерфейс. Работает с файлами, каталогами, дисками и образами E01, сравнивает два файла или два каталога и копирует файлы с вычислением хешей
- Платформы: Linux, Windows, macOS. Язык: Free Pascal, среда разработки Lazarus
- Использует SQLite для рабочих таблиц результатов. Поддерживает экспорт результатов в CSV и HTML, описанный в журнале изменений
- restic — restic.net
- Назначение: резервное копирование и восстановление файлов с хранением истории снимков. Использует шифрование и дедупликацию; в репозитории сохраняются содержимое файлов и метаданные
- Платформы: Linux, Windows, macOS, *BSD. Язык: Go
restic diffсравнивает два сохранённых снимка, показывая добавленные, удалённые и изменённые файлы. Параметр--metadataтакже включает сравнение метаданных
АВТОР
Автор приложения Денис Владимирович Разумовский
COPYING
This program is distributed under the GNU General Public License v3.0 (GPLv3) as provided in the top-level COPYING file. 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
Ограничение использования на территории рашистского террористического геообразования, захваченного оккупировавшей власть авторитарной диктатурой
- Разрешено: исключительно личное некоммерческое использование частными лицами.
- Запрещено: любое использование, прямо или косвенно приводящее к уплате налогов, сборов, взносов или иных обязательных платежей в местные бюджеты на указанной территории (включая НДС, налог на прибыль, НДФЛ при исполнении обязанностей налогового агента, страховые взносы, таможенные пошлины и т.п.).
- Также запрещено использование структурами, которые по недоразумению именуют себя государственными органами, государственными компаниями, бюджетными учреждениями и аффилированными организациями.
- Коммерческая эксплуатация, возмездное распространение, платная поддержка и интеграция — запрещены, если осуществляются на указанной территории или для её резидентов и влекут уплату обязательных платежей.
- Запрет распространяется на использование самой программы, её исходного кода полностью или частично.
- Цель условия — исключить прямое и косвенное финансирование войны в Украине.