У меня есть проблема, которая доводит меня до отчаяния и мучит меня последние дни, и я надеюсь кто-нибудь может подсказать мне, что я упустил, поскольку bash / sh - это не та область, в которой я работаю каждый день:
Сценарий : У меня есть проект, разработанный в OS X 10.11.6, который упаковывается в tar файла, и для этого tar-файла вычисляется контрольная сумма sha 256.
В обработчике git pre-commit я добавляю вычисленную контрольную сумму в файл.sha в репозиторий, чтобы другая система, которая хочет установить этот проект, могла сравнить, являются ли файлы одинаковыми, также упаковав файл в файл tar и вычислив контрольную сумму и сравнив ее с контрольной суммой .sha из каталога. { {1}} Если эти контрольные суммы совпадают, версия этого пакета «проверена» и действительна для конечного пользователя, в противном случае отображается предупреждение.
Таким образом, ловушка предварительной фиксации и файлы 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 install different package-lock ) и сами файлы .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
Наконец, решение было найдено после того, как я пошел в направлении сравнения созданных файлов 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-архив только для вычисления контрольной суммы, а не для распространять файлы).
Другие флаги : В качестве меры предосторожности я включил флаги
- переносимостьи
- разыменование- для первого см. https: //www.math.utah.edu/docs/info/tar_8.html:
Когда вы его указываете, tar оставляет информацию о каталогах, каналы, FIFO, смежные файлы и файлы устройств, а также указывает файл владение группой и идентификаторами пользователей, а не именами групп и пользователей.
и для разыменования на той же странице:
заставляет tar архивировать файлы, на которые указывают символические ссылки, вместо самих ссылок
Find & Sort : Я заметил, сравнивая архивы tar, порядок файлов сильно различается. Оказалось, что при перечислении содержимого исходной папки Ubuntu использует другой «порядок сортировки файлов», который можно стандартизировать путем экспорта переменной «LC_COLLATE = C» в файл .bashrc для использования другого стиля сортировки (это не о числах / дате / name, но о другом порядке заглавных букв и скрытых файлов / каталогов. Это означало, что инструмент tar в Ubuntu, вероятно, также имел другой порядок файлов при создании архива, поскольку я изначально определил все содержимое папки как входные. Однако решение состояло в том, чтобы нормализовать порядок входных файлов для архива, поэтому опция «-T» полезна, она принимает список файлов для архивации. Объединив все это, сначала будут найдены файлы в текущем каталоге, некоторые пути исключены (постоянное изменение хэшей git), результат передан в инструмент сортировки путем явной установки переменной LC_COLLATE = C и передачи результата в архиватор tar, поэтому что с опцией "-T -" будут архивироваться только предварительно отсортированные / предварительно отфильтрованные файлы.
После того, как все это было сделано, последняя рабочая команда для создания архива tar на разных платформах с той же контрольной суммой sha256 на либо OS X, либо Ubuntu (замените «gtar» на «tar» в Ubuntu, поскольку gtar - это версия tar с gnu-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
Я только что провел тест на своих Linux Debian и Mac OS, и результаты точно такие же.
Возможно, причина не в команде shasum, а просто потому, что ваш ./sha.tar файлы не совпадают. Вы пытались сравнить 2 файла sha.tar с помощью команды diff?