Назад | Перейти на главную страницу

Шасум tar-файла отличается на os x / ubuntu, хотя файлы идентичны

У меня проблема, которая доводит меня до отчаяния и преследует меня в последние дни, и я надеюсь, что кто-нибудь сможет подсказать мне, что я упустил, поскольку bash / sh - это не та область, в которой я работаю каждый день:

Сценарий: У меня есть проект, разработанный в OS X 10.11.6, который упаковывается в tar-файл, и для этого tar-файла вычисляется контрольная сумма sha 256.

В ловушке git pre-commit я добавляю вычисленную контрольную сумму в файле .sha в репозиторий, чтобы другая система, которая хочет установить этот проект, могла сравнить, совпадают ли файлы, также упаковав файл в файл tar и вычислив контрольную сумму и сравнивая ее с контрольной суммой .sha из каталога. Если эти контрольные суммы совпадают, версия этого пакета «проверена» и действительна для конечного пользователя, в противном случае отображается предупреждение.

Таким образом, ловушка предварительной фиксации и файлы checkum.sh в основном делают то же самое, за исключением того, что первый добавляет вычисленную контрольную сумму в репозиторий.

Я использую одну и ту же утилиту tar в обеих системах: (GNU) tar 1.28 в Ubuntu (пробовал и с 1.30, без разницы) и gtar (gnu-tar) 1.30 в OS X.

Проблема: Я получаю разные контрольные суммы в OS X, чем в Ubuntu (16.04 в Virtualbox), хотя pkgdiff / diffMerge / filemerge (OS X) не показывает различий ни в каких файлах, и я исключаю и нормализую кучу вещей при создании tar, исключая любой git части, временные файлы, каталоги после установки, странно несовместимые файлы npm (см. мой другой вопрос здесь: npm установить другую блокировку пакетов) и самих файлов .sha / sha.tar, а также нормализовав время модификации и установив в качестве владельца: группу значение root: root.

Когда я сравниваю tar-архив, созданный Ubuntu, с OS X, созданной с помощью pkgdiff, я не вижу различий, с FileMerge на OSX есть куча запутанного (?) И переупорядоченного кода, который, как я подозреваю, может быть проблемой, поскольку я сравнивая контрольные суммы этих tar-архивов позже, но я не могу понять, в чем причина этой разницы.

Система 1 - OS X: 10.11.6, gtar 1.30, git v 2.10.1 Система 2 - Ubuntu 16.04 LTS, tar 1.28 (и tar 1.30), git 2.74

Я был бы очень рад, если бы у кого-нибудь был некоторый опыт в этом вопросе и он помог бы другому разработчику решить эту проблему, но я благодарен за любой вклад - заранее спасибо!

Моя контрольная сумма.sh выглядит примерно так:

unameOut="$(uname -s)"

case "${unameOut}" in
    Linux*)     tar --mtime='2017-01-01' --exclude='.sha' --exclude='*.git' --exclude='.DS_Store' --exclude='node_modules' --exclude='package-lock.json' --exclude='workstation.json' --exclude="npm-debug.log" --exclude-vcs --exclude=".gitignore" --exclude="sha.tar" --owner=0 --group=0 -cf ./sha.tar ./ 2>/dev/null;
    sha256sum ./sha.tar | cut -d " " -f 1 > .sha_temp_check;;
    Darwin*)    command -v gtar >/dev/null 2>&1 || { echo >&2 "On MacOS gnu compatible TAR is needed, please install gtar via homebrew \n -> brew install gnu-tar ('xcode-select --install' maybe also needed)!\n…Aborting."; exit 1; };
    gtar --mtime='2017-01-01' --exclude='.sha' --exclude='*.git' --exclude='.DS_Store' --exclude='node_modules' --exclude='package-lock.json' --exclude='workstation.json' --exclude="npm-debug.log" --exclude-vcs --exclude=".gitignore" --exclude="sha.tar" --owner=0 --group=0 -cf ./sha.tar ./ 2>/dev/null;
    shasum -a 256 ./sha.tar | cut -d " " -f 1 > .sha_temp_check;;
#    CYGWIN*)    machine=Cygwin;;
#    MINGW*)     machine=MinGw;;
    *)          echo >&2 "Incompatible OS: ${unameOut} \n…Aborting."; exit 1;;
esac

rm sha.tar

stored_sha=$(cat .sha)
checked_sha=$(cat .sha_temp_check)

echo "STORED checksum: $stored_sha"
echo "CALC'D checksum: $checked_sha"

if [ "$checked_sha" = "$stored_sha" ]
then
    echo >&1 "Version verified. Continuing. "
    rm .sha_temp_check
    exit 0
else
    echo >&2 "Keys didn't match. UNVERIFIED VERSION! \n Stored SHA: $stored_sha \n Checked SHA: $checked_sha"
    rm .sha_temp_check
    exit 1
fi

Я только что провел тест на своих Linux Debian и Mac OS, и результаты точно такие же.

Возможно, причина не в команде shasum, а просто потому, что ваши файлы ./sha.tar не совпадают. Вы пробовали сравнить 2 файла sha.tar с помощью команды diff?

Наконец, решение было найдено после того, как мы перешли к сравнению созданных файлов tar из Ubuntu и OS X и устранили различия:

Частично из-за того, что оболочка / linux не является моей обычной областью работы, я упустил из виду некоторые параметры / параметры, используемые для создания межплатформенных tar-архивов, а именно:

  • Владение: Я использовал

    --owner=root --group=root
    вместо того
    --owner=0 --group=0
    для нормализации владения входными файлами. Однако, поскольку в Ubuntu есть «корневая» группа, но ее не было в моей OS X, значение «0» предполагает пользователя / группу по умолчанию, в то время как «root» или любое другое явное объявление сначала должно быть отображено в системе, чтобы назначить правильный пользователь / группа. По-видимому, это не сработало для группы, так как в OS X я всегда получал идентификатор группы по умолчанию в заголовке tar.

  • Разрешения: Я не знал, что права доступа к файлам также должны быть нормализованы, поэтому

    --mode="600"
    опция просто устанавливает для всех файлов, которые должны быть упакованы в архив, одно и то же значение (не имеет значения, какое именно, потому что я использую tar-архив только для вычисления контрольной суммы, а не для распространения файлов).

  • Другие флаги: В качестве меры предосторожности я включил

    --portability
    и
    --dereference
    flags - Для первого см. https://www.math.utah.edu/docs/info/tar_8.html:

    Когда вы его указываете, tar не учитывает информацию о каталогах, каналах, FIFO, смежных файлах и файлах устройств и указывает права собственности на файлы по группам и идентификаторам пользователей вместо имен групп и пользователей.

    и для разыменования на той же странице:

    заставляет tar архивировать файлы, на которые указывают символические ссылки, вместо самих ссылок

  • Найти и отсортировать: Я заметил, сравнивая архивы tar, порядок файлов сильно различается. Оказалось, что при перечислении содержимого исходной папки Ubuntu использует другой «порядок сортировки файлов», который можно стандартизировать, экспортируя переменную «LC_COLLATE = C» в файл .bashrc для использования другого стиля сортировки (это не о числах / дате / name, но о другом порядке заглавных букв и скрытых файлов / каталогов. Это означало, что инструмент tar в Ubuntu, вероятно, также имел другой порядок файлов при создании архива, поскольку я изначально определил все содержимое папки как входные. решение состояло в том, чтобы нормализовать порядок входных файлов для архива, поэтому опция "-T" полезна, она принимает список файлов для архивации. Объединив все это, сначала будут найдены файлы в текущем каталоге, некоторые пути исключены (постоянное изменение хэшей git), результат передается в инструмент сортировки путем явной установки переменной LC_COLLATE = C и передачи результата в архиватор tar, так что с параметром «-T -» только предварительно отсортированные / предварительно отфильтрованный филь es будут заархивированы.

После того, как все это было сделано, последняя рабочая команда для создания архива tar с перекрестной платформой с той же контрольной суммой sha256 в OS X и Ubuntu (замените «gtar» на «tar» в Ubuntu, поскольку gtar - это версия gnu-tar для tar, установленный Homebrew в OS X):

find . -type f -not -path "./.git/*" -not -path "./node_modules/*" | LC_COLLATE=C sort | gtar --mtime='2017-01-01' --exclude='.sha' --exclude='*.git' --exclude='.DS_Store' --exclude='node_modules' --exclude='package-lock.json' --exclude='workstation.json' --exclude="npm-debug.log" --exclude-vcs --exclude=".gitignore" --exclude="sha.tar" --portability --mode="600" --owner=0 --group=0 --dereference -T - -cf ./sha.tar

(Полезная ссылка для анализа заголовка tar: формат заголовка tar