Ubuntu

儘管文件相同,但 os x / ubuntu 上 tar 文件的 shasum 不同

  • January 16, 2018

我有一個問題讓我感到絕望,並且在最後幾天一直困擾著我,我希望有人能給我一個提示,因為 bash/sh 不是我每天都在工作的領域:

場景:我有一個在 OS X 10.11.6 中開發的項目,它被打包到一個 tar 文件中,併計算了這個 tar 文件的 sha 256 校驗和。

在 git pre-commit 鉤子上,我將 .sha 文件中的計算校驗和添加到儲存庫,以便另一個想要安裝該項目的系統可以通過將文件打包到 tar 文件和計算來比較文件是否相同校驗和並將其與目錄中的 .sha 校驗和進行比較。如果這些校驗和相同,則此軟體包的版本已“驗證”並且對最終使用者有效,否則將顯示警告。

所以 pre-commit 鉤子和 checksum.sh 文件基本上是一樣的,除了第一個將計算出來的校驗和添加到儲存庫中。

我在兩個系統上使用相同的 tar 實用程序,在 Ubuntu 上使用 (GNU) tar 1.28(也用 1.30 嘗試過,沒有區別)和在 OS X 上使用 gtar (gnu-tar) 1.30。

問題:我在 OS X 上得到的校驗和與在 Ubuntu(Virtualbox 中為 16.04)上得到的校驗和不同,即使 pkgdiff / diffMerge / filemerge (OS X) 在任何文件中都沒有顯示任何差異,並且我在建構 tar 時排除並規範了一堆東西,不包括任何git 元件、臨時文件、安裝後目錄、奇怪不一致的 npm 文件(請參閱我的另一個問題:npm install different package-lock)和 .sha/sha.tar 文件本身以及規範化修改時間和設置所有者:group 到 root:root。

當我將 Ubuntu 建構的 tar 存檔與使用 pkgdiff 建構的 OS X 進行比較時,我沒有發現任何差異,OSX 上的 FileMerge 有一堆混淆(?)和重新排列的程式碼,我懷疑這可能是問題所在,因為我稍後比較這些 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

如果有人在這方面有一些專業知識並能幫助開發人員解決這個問題,我會非常高興,但我很感激任何意見 - 在此先感謝!

我的 checksum.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

最後,在比較從 Ubuntu 和 OS X 創建的 tar 文件並消除差異的方向後,找到了解決方案:

部分是因為 shell / linux 不是我的正常工作領域,我忽略了一些可用於跨平台 tar 歸檔創建的參數/選項,如下所示:

  • 所有權:我用過
--owner=root --group=root

代替

--owner=0 --group=0

規範化輸入文件的所有權。但是,由於 Ubuntu 中有一個“root”組,但我的 OS X 上沒有,所以值“0”假定預設使用者/組,而“root”或任何其他顯式聲明首先必須映射到系統上才能分配正確的使用者/組。顯然,這對組不起作用,因為在 OS XI 上總是在 tar 標頭中獲得預設的“員工”組 ID。

  • 權限:我不知道文件權限也必須規範化,因此
--mode="600"

選項只是將要打包到存檔中的所有文件設置為相同的值(不管是哪一個,因為我使用 tar 存檔僅計算校驗和,而不是分發文件)。

  • 其他標誌:作為預防措施,我包括
- 可移植性

--取消引用

標誌 - 第一個見https://www.math.utah.edu/docs/info/tar_8.html

當您指定它時,tar 會忽略有關目錄、管道、fifo、連續文件和設備文件的資訊,並通過組和使用者 ID 而不是組和使用者名指定文件所有權。

並在同一頁面上取消引用:

導致 tar 歸檔符號連結指向的文件,而不是連結本身

  • 查找和排序: 我注意到通過比較 tar 檔案,文件的順序變化很大。事實證明,在列出原始文件夾的內容時,Ubuntu 使用了不同的“文件排序順序”,可以通過在 .bashrc 文件中導出“LC_COLLATE=C”變數來標準化,以使用另一種排序方式(這與數字/日期無關/ 名稱,但關於大寫字母和隱藏文件/目錄的不同順序。這意味著,由於我最初將所有文件夾內容定義為輸入,因此 Ubuntu 上的 tar 工具在創建存檔時可能也具有不同的文件順序。但是,解決方案是規範化存檔的輸入文件的順序,因此“-T”選項很有用,它接受要存檔的文件列表。結合所有這些,首先找到目前目錄中的文件,

完成所有這些之後,在 OS X 和 Ubuntu 上創建具有相同 sha256 校驗和的跨平台 tar 存檔的最終工作命令是(在 Ubuntu 上將“gtar”替換為“tar”,因為 gtar 是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 header format

我剛剛在我的 Linux Debian 和 Mac OS 上做了一個測試,結果完全一樣。

也許 shasum 命令不是原因,這僅僅是因為您的 ./sha.tar 文件不一樣。您是否嘗試使用 diff 命令比較 2 個 sha.tar 文件?

引用自:https://serverfault.com/questions/891923