儘管文件相同,但 os x / ubuntu 上 tar 文件的 shasum 不同
我有一個問題讓我感到絕望,並且在最後幾天一直困擾著我,我希望有人能給我一個提示,因為 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 文件?