chundev
日期:2026-06-19 環境:macOS Sequoia + Synology NAS(SMB 掛載)+ Synology Drive Client
從 Mail.app 拖曳存出的附件會帶 com.apple.quarantine extended attribute。這個 xattr 會被 macOS 背景程序(Gatekeeper、Spotlight)反覆讀寫,每次都更新檔案的 ctime,導致 Synology Drive 誤判為「檔案已修改」而重複上傳。在 SMB 掛載的 NAS 上問題更嚴重,因為 xattr 是以 ._ sidecar 檔案的形式儲存,額外觸發同步事件。
在 macOS 上透過 SMB 掛載 Synology NAS 作為日常工作目錄,用 Synology Drive 做雙向同步。偶爾觀察到某些檔案會不明原因地重新同步,特別是從 Mail.app 拖出來的附件。這些檔案在 Finder 中會有一個小小的 Mail 圖示標記。
Synology Drive Client 會週期性地重新上傳某些檔案,即使檔案內容完全沒有變動。用 xattr -l 檢查這些檔案:
$ xattr -l /path/to/mail-attachment.pdf
com.apple.quarantine: 0083;6a33e047;Mail;4248A508-8C13-4101-B12A-A083273B847C
com.apple.metadata:kMDLabel_xn6o5jlcs3x2dfgarrhz3pcaym: (binary data)
帶 com.apple.quarantine 的檔案就是問題來源。
macOS 檔案有三個關鍵時間戳:
| 時間戳 | 意義 | 什麼時候更新 |
|---|---|---|
| mtime | 內容修改時間 | 檔案內容被寫入 |
| ctime | metadata 變更時間 | 任何 inode 屬性變動(含 xattr) |
| atime | 最後存取時間 | 檔案被讀取 |
重點:xattr 被修改 → ctime 更新 → 即使 mtime 不變,同步工具仍可能偵測到「檔案有變化」。
Synology Drive 偵測檔案變更時,不只看 mtime,也參考 ctime 和檔案大小。ctime 一變,就被視為需要同步的對象。
com.apple.quarantine 不是設了就靜止不動的標記。macOS 有多個背景機制會讀取或修改它:
Gatekeeper 驗證流程:
0083(未驗證)更新為 00C3(已驗證)Spotlight indexer(mds/mdworker):
kMDLabel)Finder 預覽:
每次被碰 → ctime 更新 → Synology Drive 又偵測到變更。
._ 檔案存的這是在 NAS 場景下問題放大的關鍵。
macOS 原生檔案系統(APFS、HFS+)內建支援 extended attributes,xattr 直接存在檔案系統的 inode 中。但在非 Apple 檔案系統上(包括 SMB/CIFS 掛載的 NAS),macOS 會把 xattr 存成 AppleDouble sidecar 檔案:
報告.pdf ← 本體(內容沒變)
._報告.pdf ← xattr 資料(被背景程序改寫)
這個 ._ 檔案的建立和修改,對 NAS 來說就是一次真實的檔案寫入事件。Synology Drive server 端偵測到 ._報告.pdf 被修改 → 觸發同步 → 可能連帶重新處理 報告.pdf 本體。
Mail.app 存出附件(自動帶 quarantine xattr)
↓
macOS 在 SMB 上建立 ._ sidecar 檔案存放 xattr
↓
Spotlight indexer 掃到新檔案,讀取 quarantine xattr
↓
ctime 更新 + ._ 檔案可能被改寫
↓
Synology Drive 偵測到變更 → 重新上傳
↓
NAS 端檔案更新 → 其他同步 client 偵測到變更
↓
其他 client 下載更新 → 可能觸發該端 Spotlight 重新索引
↓
(如果 Spotlight 又碰了 xattr...循環繼續)
# 清除單一檔案
xattr -d com.apple.quarantine /path/to/file.pdf
# 清除整個目錄(只刪 quarantine,不動其他 xattr)
xattr -dr com.apple.quarantine /path/to/directory/
-d 指定只刪除 com.apple.quarantine 這一個 xattr,不影響 Finder 標籤等其他 metadata。
先看有多少檔案帶 quarantine(不做任何修改):
find /path/to/nas/mount/ -maxdepth 4 -type f \
-exec sh -c 'xattr -p com.apple.quarantine "$1" 2>/dev/null && echo " → $1"' _ {} \; \
| grep -c "→"
不要對整個 NAS 目錄跑 xattr -cr(清除所有 xattr):
-c 會清掉所有 xattr,包括 Finder 顏色標籤和註解正確做法是只清 quarantine(-d com.apple.quarantine),或養成從 Mail 存出附件後就立刻清的習慣。
com.apple.quarantine 的格式quarantine xattr 的值是一個分號分隔的字串:
0083;6a33e047;Mail;4248A508-8C13-4101-B12A-A083273B847C
│ │ │ │
│ │ │ └─ 下載事件 UUID(對應 LaunchServices 資料庫)
│ │ └─ 來源應用程式名稱
│ └─ 時間戳(hex,Unix epoch)
└─ 狀態 flag(0083=未驗證, 00C3=已驗證通過)
macOS 將完整的 quarantine 事件記錄在 SQLite 資料庫:
~/Library/Preferences/com.apple.LaunchServices.QuarantineEventsV2
._ sidecar 檔案。在 APFS 上 xattr 變動是 inode 層級的事,但在 SMB 上會變成一次實際的檔案寫入,對同步工具來說影響更大。xattr -d vs xattr -c:-d 指定刪單一 xattr(安全),-c 清除全部(會丟 Finder 標籤)。清同步問題用 -d com.apple.quarantine 就好。