備份和恢復文件/目錄的時間戳?
我們需要備份文件和目錄的 a/c/mtime-stamps,並有能力在必要時恢復它們。
備份的範例命令可能是:
$ timestamp backup --all-stamps --incl-dir-stamps --recursive out.stampbak file.bin /dir/with/files/
恢復可能是:
$ timestamp restore --all-stamps out.stampbak
是否存在這樣的命令來實現我正在尋找的結果?納秒精度將是首選,或者其他更精細的精度,儘管我相信大多數文件系統停止在納秒。POSIX 合規性也很重要,因為我們需要支持/恢復 BSD 和 GNU/Linux 系統上的時間戳。
**編輯:*為了澄清一些事情,我列出的文件系統在很大程度上是暫時保留文件,直到我最終可以將它們移動到主 ZFS 伺服器。這就是讓我們考慮在將數據遷移到 ZFS之前*保留時間戳的可能性的原因。以防郵票在傳輸過程中發生變化(我們使用 HTTP、FTP、SMB 等幾種方法),我們希望確保它們可以恢復到應有的狀態。即使是在傳輸後,將時間戳保留為小備份也是有益的,因此無論文件最終會在 ZFS 上如何,問題仍然只是關於備份/恢復時間戳的問題。可以從備份中省略權限和組資訊。
用於備份時間戳的作業系統包括 macOS Mojave 10.14.6、Ubuntu Server 18.04.5 LTS、Debian 10.2/7.8、FreeBSD 12.2 和 CentOS 8。恢復將主要在 FreeBSD(ZFS 伺服器主機)上完成,我不認為在其他任何地方都沒有必要。如果有幫助的話,我有幾個驅動器,其中包含 NTFS 分區上的文件。是否有必要執行一個小型 Windows 實例來正確備份這些標記?
此外,我的印像是大多數文件系統使用 atime、ctime 和 mtime,而沒有其他文件系統(我認為這最終在文件系統之間有所不同)。如果可能的話,我的目標是保存和恢復所有這些。
我提到了 POSIX 合規性,該工具可以在任一平台上使用——如果我之前的描述不正確或不充分,我深表歉意。我還認為 ctime = 創建/出生時間,我現在看到它是更改時間。
要保留的最重要的時間戳是創建/出生時間和修改時間。訪問時間也會很好,更改時間是最不重要的,但仍然會有所幫助。再次,我為這個錯誤道歉,我還在學習。
**編輯 2:**從這篇文章中我了解到:
- 大多數文件系統中沒有保存文件創建時間戳——這意味著你不能執行像“顯示在特定日期創建的所有文件”這樣的命令。這就是說,通常可以從 ctime 和 mtime 推斷出相同的結果(如果它們匹配 - 這可能意味著創建文件的時間)。
- 創建新文件或目錄時,通常將所有三個時間(atime、ctime 和 mtime)都配置為擷取目前時間。
由於目標文件系統將是 ZFS,文件/目錄的時間戳將在其中恢復,因此最好至少保存 atime、ctime、mtime,以防保存時間戳的文件系統不儲存出生時間。
如果你有 GNU find 和 Perl,你可以用它們來裝點東西。可以列印時間戳的
-printf
操作find
,Perl 具有utime
修改它們的功能。或者兩個,內置一個,一個在 Time::HiRes 模組中,後者支持亞秒級精度。一些用於測試的文件:
$ find . -printf '%A@ %T@ %p\n' 1631866504.4180281370 1631866763.5380257720 . 1631866763.5380257720 1631866768.2101700800 ./dir 1631866768.2101700800 1631866768.2101700800 ./dir/bar.txt 1631866760.2619245850 1631866760.2619245850 ./foo.txt
將時間戳保存到文件中:
$ find . -printf '%A@ %T@ %p\0' > ../times
讓我們刪除時間戳:
$ touch -d 1999-01-01 **/* $ find . -printf '%A@ %T@ %p\n' 1631866771.6022748540 1631866763.5380257720 . 915141600.0000000000 915141600.0000000000 ./dir 915141600.0000000000 915141600.0000000000 ./dir/bar.txt 915141600.0000000000 915141600.0000000000 ./foo.txt
並從文件中重新載入它們:
$ perl -MTime::HiRes=utime -0 -ne 'chomp; my ($atime, $mtime, $file) = split(/ /, $_, 3); utime $atime, $mtime, $file;' < ../times 1631866771.6022748950 1631866763.5380258560 . 1631866771.6022748950 1631866768.2101700310 ./dir 1631866768.2101700310 1631866768.2101700310 ./dir/bar.txt 1631866760.2619245050 1631866760.2619245050 ./foo.txt
該文件僅包含帶有 atime、mtime 和文件名的以 NUL 結尾的欄位,並且 Perl 片段呼叫
utime
每組值。使用 NUL 作為終止符,它應該能夠處理任意文件名,但請注意,我在這裡使用
\n
而不是\0
用於列印輸出,這不適用於該 Perl 片段,因為它需要 NUL,而不是換行符。另外,我完全忽略了 ctime,因為據我所知,它無論如何都不能用
utime()
/設置。utimensat()
任何出生時間戳都一樣。