Könyvtárstruktúrák szinkronizálása

Üdv!

Adott két gép, amiken szinkronizálva van ugyanaz a méretes könyvtárstruktúra, rengeteg fájllal. Azonban az egyik gépen ez a struktúra jelentősen megváltozott, sok fájl át lett mozgatva más könyvtárakba, új könyvtárak lettek létrehozva. (Pár fájl módosítva vagy törölve lett, de ez a teljes könyvtárstruktúra méretéhez képest elenyésző változás.) A kérdés az, hogy van-e valamilyen kész megoldás arra (lehetőleg windowsra), hogy úgy szinkronizáljam a két gépen ezt a könyvtárstruktúrát, hogy a nem változtatott, csak mozgatott fájlok ne legyenek újra átküldve a hálózaton?

Persze le tudnám programozni, de biztos vagyok benne, hogy más már megírta, csak nem volt szerencsém a google-lel.

Hozzászólások

Elsőre biztató volt, mivel ismeri a rename operationt is, de mint kiderült, fájlmozgatásra ezt már nem alkalmazza.


Operations     Count
--------------------
Delete Folder  0*
Delete         0
Overwrite      306
Rename         0
New            6,310
Create Folder  116

Found 14 631 files that did not require action.

Total bytes to copy: 9,794,139,654
Avoided copying 28 629 368 847 bytes in 14 631 files.

*: A biztonság kedvéért elsőre nem akartam, hogy töröljön is, gondoltam ha látom hogy jó, akkor majd átállítom vagy beállítom újra.

Tehát több, mint 9 gigányi adatot másolna így át, egy 54Mbps-os wifi kapcsolaton. Végül is pár óra alatt megvan...

Végül nem futtattam le semmilyen hagyományos szinkronizáló programot, noha ennyi idő alatt már sokszor lefutott volna. Inkább elkezdtem lekódolni powershellben, mert elkezdett érdekelni a probléma. Az első verzió hamar elkészült, az alapelv az volt, hogy különböző metaadatok (fájlnév, utolsó módosítás dátuma) megkeresem az egyező fájlokat, ha jó helyen van semmit nem csinálok, ha rossz helyen van átmozgatom a helyére, és csak akkor másolom át ha nem létezik a távoli oldalon. Csakhogy nem gondoltam arra, mi a helyzet a duplikátumokkal, amik hatására természetesen a script mindenféle hülyeséget csinált az ilyen esetekben.

Ezután pihentettem pár napig a dolgot, végül kigondoltam mit kell tenni. Csoportosítani kell a fájlokat a fenti metaadatok szerint, ekkor az azonos fájlok egy csoportba kerülnek. Amikor egyezőséget keresünk, akkor a csoportok metaadatait kell összehasonlítani. Ezután ha nem találtunk a távoli oldalon csoportot, át kell másolni a fájlt a helyi oldalról. Ha találtunk, és a távoli csoportban van olyan fájl, ami jó helyen van, nem kell tenni semmit. Ha nincs, akkor a távoli csoportban kell keresni olyan fájlt, ami a helyi csoportban nincs az adott helyen, azt át lehet mozgatni. Ha ilyen sincs, a távoli csoport egyik fájlját kell másolni a megfelelő helyre. Megírtam a scriptet, de végül nem futtattam le. Ugyanis kiderült, hogy a módszer bár működik, de iszonyatosan lassú. Sokkal lassabb, mintha az egész könyvtárt másolnám át, úgy ahogy van. Gondolom a hatalmas fájllistában való keresés viszi el az idő nagy részét. Talán át lehetne írni úgy, hogy végül quick search-t használjon, vagy egy ciklussal egyszerre járnám be a két listát (lásd sort merge join), de más ötletem van.

Ugyanis idő közben ismertem meg a compare-object cmdlet-et, amit ha megfelelően fel tudnék paraméterezni, a munka nagy részét el is végezné, remélhetőleg sokkal hatékonyabban, mint amit én akármilyen trükközéssel össze tudok hozni. Úgyhogy a terv az, hogy a harmadik verzió compare-object-et fog használni.

Ez a "compare-object" is a powershell része?

Miért lassú a metaadatok nyálazása? Exponenciálisan elfut az összehasonlítások száma?

Ugye 1 irányú szinkről van szó?

Azon gondolkodok, hogy ha a meta adatok szerint rendezed a fájlokat (amúgy is végig kell menni minden fájl meta adatán legalább egyszer), akkor a fenti gondolatmeneted első része kellene hogy működjön szerintem.

Tehát a meta adat 3 részből állna. 2 rész: fájl méret és utolsó módosítás dátuma, a harmadik pedig vagy név, vagy pedig checksum. Ez utóbbi jobb lenne, nem tudom elérhető-e windows-on.

Ha ez meg van, akkor nem értem hogy miért lenne lassú.

Ha mindkét oldalon megcsinálnád a listát, majd pl. egymásba merge-eled, de úgy, mintha minden meta adatra (az összes elemére) egy hash-t generálnál, majd a 2 listát egyetlen változóba tolod, majd ezt sorba rendezed. Meg kell jegyeztetni még soronként a path-t és hogy helyi vagy távoli-e. Elsődlegesen meta adat, másodlagosan path alapján kell rendezni.

Ekkor az egyforma hash-ek egymás mellett lesznek. Így sorba kell menni a lista egyforma tagjain, melyek egymás mellett lesznek. Ezek után vizsgálnád a path-t. Ha jól gondolom, akkor a következő lehetőségek lesznek:

1) meta adatok egyeznek + path is egyezik -> nincs tennivaló

2) meta adatok egyeznek + path nem egyezik (itt ez azt jelenti, hogy habár művelet kellhet, de mivel van ilyen metaadattal fájl a távoli gépen, ezért mindenképp csak a távoli gépen hajtjuk végre a műveletet az ottani fájllal a hálózati átvitelt megspórolva):

2-a) helyi path-al nincs távoli fájl és távoli path-al nincs helyi fájl -> fájl mozgatása távoli path-ról helyi path-ba a távoli gépen

2-b) helyi path-al nincs fájl a távoli gépen -> a távoli path-ról másoljuk a fájlt a helyi path-ra a távoli gépen

2-c) távoli path-al nincs fájl a helyi path-on, akkor fájl törlése a fenti műveletek után

3) nincs távoli meta adat a helyin, ekkor távoli törlése

4) nincs helyi meta adat a távolin, ekkor helyi másolása a távolra

Ugye a fentieknél ha egy állítás igaz volt és végeztünk műveletet, akkor tovább nem vizsgáljuk a többi feltételt (1-4-ig).

"Ez a "compare-object" is a powershell része?"

Igen, PowerShell 2.0 óta. Lényegében egy diff-et valósít meg objektumok listáin, de szépen lehet okosítani, hogy milyen propertyket vizsgáljon, mekkora legyen a slide window (ha kell), stb.

"Miért lassú a metaadatok nyálazása? Exponenciálisan elfut az összehasonlítások száma?"

Ha n a helyi oldal csoportjainak száma és m a távoli oldal csoportjainak száma, akkor n*m az összes összehasonlítás száma. Mivel a távoli oldal csoportját egy egyszerű where-object-tel keresem, az pedig lineáris keresést valósít meg. Ráadásul most jutott eszembe, hogy akkor is tovább keres, ha már megvan a keresett csoport, ezen egy "|select-object -first 1" elvileg segítene, de még így is n*m/2 összehasonlítás történne. Tehát nem a metaadatok lekérése vagy összehasonlítása lassú, egyszerűen rossz a kereső algoritmus, amit egyébként egyszerű lenne javítani, pl. amit te leírtál (és amire már én is utaltam).

"Ugye 1 irányú szinkről van szó?"

Igen.

Unison is a file-synchronization tool for Unix and Windows.

...

-rsync

(default true)
Unison uses the 'rsync algorithm' for 'diffs-only' transfer of updates to large files.

...

-xferbycopying

(default true)
When this preference is set, Unison will try to avoid transferring file contents across the network by recognizing when a file with the required contents already exists in the target replica. This usually allows file moves to be propagated very quickly.

Ez nem jó?

:)

Jól hangzik, meglesem, köszi!

Szerk: hát, több probléma is van.

Az első ez:

If your replicas are large and at least one of them is on a Windows system, you may find that Unison's default method for detecting changes (which involves scanning the full contents of every file on every sync—the only completely safe way to do it under Windows) is too slow. Unison provides a preference fastcheck that, when set to true, causes it to use file creation times as 'pseudo inode numbers' when scanning replicas for updates, instead of reading the full contents of every file.

Namost a "file creation time" azért nem lesz jó, mert vannak olyan megváltoztatott fájlok, amiknek ez az attribútuma nem változott, csak a "file modification time".

A másik ez:

When path is given without any protocol prefix, the protocol is assumed to be file:. Under Windows, it is possible to synchronize with a remote directory using the file: protocol over the Windows Network Neighborhood. For example,

unison foo //host/drive/bar

synchronizes the local directory foo with the directory drive:\bar on the machine host, provided that host is accessible via Network Neighborhood. When the file: protocol is used in this way, there is no need for a Unison server to be running on the remote host. However, running Unison this way is only a good idea if the remote host is reached by a very fast network connection, since the full contents of every file in the remote replica will have to be transferred to the local machine to detect updates.

Arról nem ír, hogy a fastcheck opció erre az esetre alkalmazható-e (gyanítom azért, hogy igen).

Gondoltam trükközzünk, szépen felcsatoltam a megfelelő könyvtárat egy hálózati meghajtóként, gondoltam akkor majd azt hiszi lokálisan érhető el. Egy fenét, egy szép errorral honorálta:

Fatal error: Cannot find canonical name of "Z:/": unable to cd either to it

("Z:/": A fájlnév, a könyvtárnév vagy a kötetcimke szintaxisa nem megfelelő.)
or to its parent "Z:
("Z:: A fájlnév, a könyvtárnév vagy a kötetcimke szintaxisa nem megfelelő.)

Persze ugyanez történik akkor is, ha a fent leírt //host/share módon adom meg az útvonalat.

Amit még nem próbáltam, hogy a másik gépen elindíthatnám a szervert, és akkor socketen talán menne. De kezdem úgy érezni, hogy ezt a szoftvert nem windows-windows szinkronizációra találták ki.

A ráadás az, hogy jó lenne egy olyan opció, ami csak logolja, hogy mit tenne, de valójában nem tesz semmit. Így láthatnám, hogy egyáltalán úgy működik-e ahogy azt szeretném.

A

fastcheck false

nem oldja meg?

However, running Unison this way is only a good idea if the remote host is reached by a very fast network connection, since the full contents of every file in the remote replica will have to be transferred to the local machine to detect updates.

Itt nem pont azt írja, hogy mindenképpen áthúzza az összes adatot? Innentől kezdve neked semmiképpen nem jobb így, mint bármilyen eddigi megoldás. Valamilyen más módon kell biztosítanod a kiszolgálást.

Szerintem a grafikus felületű cucc részben vagy egészben mutatja, mit akar csinálni.

:)

Az eredeti poszt írásakor elkezdtem én is gondolkodni, mert érdekelt a probléma, és bár nem programoztam le, a működés a következő lenne:

Egy file-t az md5 hash + filehossz (ID) azonosítson. Ekkor:
1) mindkét gépen állítsuk elő az összes file-ra az ID-ket (de ne hálózaton keresztül:))
2) másoljuk a célgépre a hiányzó fileokat egy pool-ba (pl. a forrásgépen tarolva/a célgépen kitarolva, esetleg az eredeti filenevek helyett ID-t használva)
3) a célgépen a pool-ból, és a régi könyvtárstruktúrában lévő fileokból gazdálkodva építsük fel az új könyvtárstruktúrát; ha két file-nak ugyanaz az ID-je, akkor lehet másolni/linkelni, különben csak mozgatni kell

Kicsit késő, illetve nem tudom mennyire jó válasz a késésedre, úgyhogy csak a későbbi keresgélők életét megkönnyítendő írok.

Én a FreeFileSynch -et használom szinkronizálásra. Nem tudom van e elég esze ahhoz, hogy az átmozgatott fájlokat felismerje és nem másolja újra, de egyébként jó kis eszköz.

Esetleg még a link shell extension jöhet szóba. Különösen a smart mirror opciója lehet érdekes. Azért megjegyzem, én csak sima linkelésre használom.

Szerk:
ezek szerint a Free File Synch tudja kezelni az átnevezett és mozgatott fájlokat is.