У меня проблема, которая доводит меня до отчаяния и преследует меня в последние дни, и я надеюсь, что кто-нибудь сможет подсказать мне, что я упустил, поскольку 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и
--dereferenceflags - Для первого см. 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