Unison同步时文件属主、组及权限异常变更问题排查
跨Windows 10与Debian 12的Unison同步文件属性异常问题分析与解决
问题现象
在Windows 10与Debian 12之间使用Unison 2.53.3同步文件后,Debian端文件的属主、用户组及权限出现异常变更:
同步前Debian端文件信息:
-rw-rw---- 1 www-data www-data 7448 Nov 30 09:13 trac.ini
同步后Debian端文件信息:
-rw-r--r-- 1 thomas thomas 7447 Nov 30 09:24 trac.ini
执行同步的用户thomas属于www-data用户组,当前Unison配置如下:
owner = false group = false dontchmod = true perms=0 acl = false
补充推测与同步日志
2023-12-01补充推测:Unison通过创建临时文件→删除原文件→重命名临时文件的流程完成同步,新创建的临时文件会继承运行Unison的用户thomas的默认属主、用户组及权限,最终替换原文件后覆盖了原有属性。
同步日志如下:
Unison 2.53.3 (ocaml 4.14.0) started propagating changes at 12:17:50.57 on 30 Nov 2023 [BGN] Updating file trac/conf/trac.ini from D:/ServerSync/www to //debian12//home/www [files] copy D:/ServerSync/www trac/conf/trac.ini ---> //debian12//home/www trac/conf/trac.ini [update] updateArchive D:/ServerSync/www trac/conf/trac.ini [pred] ignore 'trac/conf/trac.ini' = false [files] copyRec trac/conf/trac.ini ---> .unison.trac.ini.3cf645660f038354c49973b861281767.unison.tmp (really to trac.ini) [abort] Checking line 0 [copy] copyRegFile(D:/ServerSync/www,trac/conf/trac.ini) -> (//debian12//home/www,trac.ini,/home/www/trac/conf,.unison.trac.ini.3cf645660f038354c49973b861281767.unison.tmp,modified on 2023-11-30 at 12:15:04 size 7449 unknown permissions) [abort] Checking line 0 [server: pred] follow 'trac/conf/trac.ini' = false [server: fspath] Os.findWorkingDir(/home/www,trac/conf/trac.ini) = (/home/www/trac/conf,trac.ini) [server: copy] tryCopyMovedFile: -> .unison.trac.ini.3cf645660f038354c49973b861281767.unison.tmp /(86a468d364d8ac9b053abc05705cade5,)/ [server: xferhint] lookup: fp = (86a468d364d8ac9b053abc05705cade5,) [server: copy] tryCopyMovedFile didn't work, so now we actually transfer [server: copy] reallyTransferFile(D:/ServerSync/www,trac/conf/trac.ini) -> (/home/www/trac/conf,.unison.trac.ini.3cf645660f038354c49973b861281767.unison.tmp,trac.ini,modified on 2023-11-30 at 12:15:04 size 7449 unknown permissions) [server: rsync] preprocessing [server: rsynclog] block size = 700 bytes; block count = 10; strong checksum size = 3 [abort] Checking line 0 [rsync] compressing [rsynclog] compression buffer size = 8192 bytes [rsynclog] block size = 700 bytes [rsynclog] 64 hash table entries [rsynclog] 54 empty, 10 used, 0 collided [rsynctoken] updating the compression buffer [rsynctoken] new length = 7449 bytes [rsynctoken] pushing string (pos:0/65500 len:702) [rsynctoken] pushing block (pos:705/65500) [rsynctoken] growing blocks (pos:710/65500) [rsynctoken] pushing string (pos:710/65500 len:447) [rsynctoken] pushing EOF (pos:1160/65500) [rsynctoken] flushing the token queue [rsynclog] hit-hit = 9, hit-miss = 0, miss-miss = 3, hit rate = 100% [server: rsynclog] 10 blocks [server: copy] Starting the actual transfer [server: abort] Checking line 0 [server: rsynctoken] decompressing string (702 bytes) [server: rsynctoken] decompressing 9 block(s) (sequence 1->9) [server: rsynctoken] decompressing string (447 bytes) [server: copy] transferResourceForkAndSetFileinfo .unison.trac.ini.3cf645660f038354c49973b861281767.unison.tmp [server: copy] Resource fork transferred for trac.ini; doing last paranoid check [server: xferhint] insertEntry: fspath=/home/www/trac/conf, path=.unison.trac.ini.3cf645660f038354c49973b861281767.unison.tmp, fp=(86a468d364d8ac9b053abc05705cade5,) [files] rename(root=//debian12//home/www, localPath=trac/conf/trac.ini, pathOld=.unison.trac.ini.3cf645660f038354c49973b861281767.unison.tmp, pathNew=trac.ini) [server: update] checkNoUpdates /home/www trac/conf/trac.ini [server: update] buildUpdateRec: /home/www/trac/conf/trac.ini [server: update] checkContentsChange: archStamp is inode (106173286) / info.inode (106173286) / times: 1701342849.592926 = 1701342849.592926... true / lengths: 7447 - 7447 [server: xferhint] insertEntry: fspath=/home/www, path=trac/conf/trac.ini, fp=(11c589c1b5293a98bf86827d1068c654,) [server: update] archive digest = (11c589c1b5293a98bf86827d1068c654,) current digest = (11c589c1b5293a98bf86827d1068c654,) [server: files] Renaming .unison.trac.ini.3cf645660f038354c49973b861281767.unison.tmp to trac.ini in /home/www/trac/conf; root is /home/www [server: files] rename: moveFirst=false [server: stasher] backup: /home/www / trac/conf/trac.ini [server: pred] follow 'trac/conf/trac.ini' = false [server: fspath] Os.findWorkingDir(/home/www,trac/conf/trac.ini) = (/home/www/trac/conf,trac.ini) [server: pred] backup 'trac/conf/trac.ini' = false [server: stasher] Path /home/www / trac/conf/trac.ini does not need to be backed up [server: os] rename /home/www/trac/conf/.unison.trac.ini.3cf645660f038354c49973b861281767.unison.tmp to /home/www/trac/conf/trac.ini [update] updateArchive D:/ServerSync/www trac/conf/trac.ini [pred] ignore 'trac/conf/trac.ini' = false [update] replaceArchiveLocal D:/ServerSync/www trac/conf/trac.ini [update] Setting archive for //mywindows/D:/ServerSync/www [pred] backupcurr 'trac/conf/trac.ini' = false [END] Updating file trac/conf/trac.ini <>[server: files] Contents of /home/www/trac/conf/trac.ini after renaming = 86a468d364d8ac9b053abc05705cade5 [server: pred] backupcurr 'trac/conf/trac.ini' = false [server: xferhint] insertEntry: fspath=/home/www, path=trac/conf/trac.ini, fp=(86a468d364d8ac9b053abc05705cade5,) [server: update] replaceArchiveLocal /home/www trac/conf/trac.ini [server: update] Setting archive for //debian12//home/www Unison 2.53.3 (ocaml 4.14.0) finished propagating changes at 12:17:50.77 on 30 Nov 2023, 0.202 s
问题原因分析
你的推测完全正确:
- Windows没有Unix式的属主、用户组和权限体系,无法向Debian端传递这些元数据;
- Unison同步时会在Debian端创建临时文件,该文件默认继承运行Unison的用户
thomas的属主、组和权限; - 当前配置的
owner=false/group=false是告诉Unison不尝试同步源端(Windows)的属主/组信息,而非保留目标端原有的属性;dontchmod=true和perms=0则禁止Unison修改文件权限,但临时文件创建时已经使用了用户默认权限,后续不会调整。
解决方法
1. 修改Unison配置,强制同步属性
若需要保持目标端文件属主为www-data,可调整配置如下:
owner = true group = true perms = -1 dontchmod = false acl = false
owner=true/group=true:Unison会尝试将目标文件的属主/组设置为源端对应值,但Windows无相关数据,因此需要在Debian端以拥有修改文件属主权限的用户(如root)运行Unison,或给thomas添加sudo权限并在同步时调用(注意安全风险)。
2. 同步后自动修正属性
若不想修改Unison运行用户,可在同步完成后执行脚本批量修正目标目录属性:
chown -R www-data:www-data /home/www/trac/conf/ chmod -R 660 /home/www/trac/conf/
可将该脚本与Unison同步命令合并为一个脚本,实现同步后自动修正。
3. 用rsync辅助同步(可选)
如果Unison的权限处理不符合需求,可先用rsync从Windows同步到Debian并强制设置属性,再用Unison做双向同步补充:
rsync -avz --chown=www-data:www-data /mnt/windows-share/www/ /home/www/
跨系统同步局限性
Windows与Unix-like系统的文件元数据体系差异极大,Unison作为双向同步工具难以完美兼容两端属性。若需保证Unix端属性稳定,优先在Unix端控制同步后的属性修正,或搭配更侧重Unix元数据的同步工具。
内容的提问来源于stack exchange,提问作者Thomas853
相关产品推荐
相关产品推荐

