Backup

備份和恢復文件/目錄的時間戳?

  • September 17, 2021

我們需要備份文件和目錄的 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()任何出生時間戳都一樣。

引用自:https://unix.stackexchange.com/questions/669234