5

Знаете ли вы, есть ли объединенная fs для GNU/Linux, которая показывает также "теневые" файлы с немного другими именами? То есть если у меня есть две фс как:

root1
+dir1
+dir2
 +file1
 +file2
 +file3

root2
+dir1
+dir2
 +file1
 +file2
 +file4

Результирующий "объединенный" fs должен привести:

unioned
+dir1
+dir2
 +file1
 +file1.1
 +file2
 +file2.1
 +file3

Чтобы можно было быстро проверить различия между "объединенными" фс

Похоже, что UnionFS и Aufs не предлагают эту опцию

Спасибо

3 ответа3

1

Альтернатива с использованием git-annex:

Сначала мы настроим тестовые файлы:

#!/bin/bash 
# faster than /dev/urandom
randfile='openssl enc -aes-256-ctr -pass pass:"$(dd if=/dev/urandom bs=128 count=1 2>/dev/null | base64)" -nosalt < /dev/zero'
dd='dd bs=1M count=5 iflag=fullblock'

for I in 1 2
do
  mkdir root$I
  cd root$I
  for J in 1 2
  do
    mkdir dir$J
    if [ -e dir2 ]
    then
      cd dir2
      eval $randfile | eval $dd of=file1
      eval $randfile | eval $dd of=file2
      if [ `pwd | grep root1` ]; then
        eval $randfile | eval $dd of=file3
      elif [ `pwd | grep root2` ]; then
        eval $randfile | eval $dd of=file4
      fi
      cd ..
    fi
  done
  cd ..
done

Это создает каталоги с двоичными файлами, содержащими случайные данные. На данный момент файлы:

user@host$ find root? -path '*/.git*' -prune -o -print | sort -n 
root1
root1/dir1
root1/dir2
root1/dir2/file1
root1/dir2/file2
root1/dir2/file3
root2
root2/dir1
root2/dir2
root2/dir2/file1
root2/dir2/file2
root2/dir2/file4

Теперь мы инициализируем репозитории и выполняем синхронизацию:

cd root1
  git init
  git annex init 'root1'
  git remote add root2 ../root2
  #git annex direct
  git annex add .
  git commit -a -m 'Files added.'
cd ..
cd root2
  git init
  git annex init 'root1'
  git remote add root1 ../root1
  #git annex direct
  git annex add .
  git commit -a -m 'Files added.'
cd ..
mkdir unioned
cd unioned
  git init
  git annex init 'unioned'
  git remote add root1 ../root1
  git remote add root2 ../root2
  git annex add . 
  git commit -a -m 'Files added.'
  git annex sync
cd ..

На данный момент, содержимое unioned/ являются:

user@host$ find root? unioned -path '*/.git*' -prune -o -print | sort -n
root1
root1/dir1
root1/dir2
root1/dir2/file1
root1/dir2/file2
root1/dir2/file3
root2
root2/dir1
root2/dir2
root2/dir2/file1
root2/dir2/file2
root2/dir2/file4
unioned
unioned/dir2
unioned/dir2/file1
unioned/dir2/file1.variant-065a
unioned/dir2/file1.variant-a33e
unioned/dir2/file2
unioned/dir2/file2.variant-08f3
unioned/dir2/file2.variant-75c4
unioned/dir2/file3
unioned/dir2/file4

Где *.variant-* ссылка на разные файлы в разных репозиториях. Кроме того, unioned прежнему не содержит данных, пока мы не проведем git annex get . На данный момент, git annex list показывает, где файлы находятся и / или получены из:

user@host$ cd unioned; git annex list
here
|root1
||root2
|||web
||||
__X_ dir2/file1.variant-065a
_X__ dir2/file1.variant-a33e
__X_ dir2/file2.variant-08f3
_X__ dir2/file2.variant-75c4
_X__ dir2/file3
__X_ dir2/file4

Альтернативой в более длинной форме является git annex whereis . Наконец, чтобы разрешить конфликты и распространить слияние изнутри unioned/dir2:

cd unioned/dir2
git annex get # retrieve the actual content
git annex unlock # unlock the files - replace the symlinks with the actual repofiles
rm file1
git mv file1.variant-065a file1
git rm -f file1.variant-a33e
rm file2
git mv file2.variant-75c4 file2
git rm -f file2.variant-08f3
git annex add . # "commits" the changes, converts files back into symlinks
git annex sync  # propagates the changes back to the other repos

Который дает:

git annex sync
commit  ok
pull root2 
ok
pull root1 
ok
push root2 
Counting objects: 61, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (26/26), done.
Writing objects: 100% (37/37), 2.67 KiB | 0 bytes/s, done.
Total 37 (delta 14), reused 0 (delta 0)
To ../root2
   e5df80f..720b34b  git-annex -> synced/git-annex
   b055385..ad8c5c2  master -> synced/master
ok
push root1 
Counting objects: 61, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (26/26), done.
Writing objects: 100% (37/37), 2.67 KiB | 0 bytes/s, done.
Total 37 (delta 14), reused 0 (delta 0)
To ../root1
   e5df80f..720b34b  git-annex -> synced/git-annex
   b055385..ad8c5c2  master -> synced/master
ok

Наконец, git annex list показывает, где эти файлы находятся после синхронизации: в unioned/ есть копии всех файлов, выбранных на разных серверах, как указано выше.


git-annex также имеет прямой режим, который работает непосредственно с файловой системой без использования символических ссылок.

Настройка этого для использования на удаленных компьютерах - это вопрос настройки удаленных устройств через ssh с использованием стандартного git, однако его поведение описано здесь: http://git-annex.branchable.com/walkthrough/using_ssh_remotes/

Общее описание приложения git находится здесь: http://git-annex.branchable.com/walkthrough/

0

Ответ на первоначальный вопрос, кажется, "не в данный момент".

Обходные пути были предложены, они основаны:

  • на пресловутый инструмент (rsync, с активированной опцией резервного копирования)
  • на специальных файловых системах (таких как ZFS или btrfs), предлагающих "снимок"

Оба предложения предполагают интенсивный ввод-вывод, потому что они создают новую файловую систему, а не отображают существующие в виртуальную файловую систему.

0

Вместо того, чтобы смотреть на уровень файловой системы, так как вам нужно видеть / поддерживать различия между версиями. Если они являются текстовыми файлами, то git http://git-scm.com/ предоставит хорошее решение. git - это система контроля версий, используемая для исходного кода, которая обрабатывает как сравнение нескольких каталогов файлов (так называемые репозитории), но и ветвление, различия и слияния.

Если вы не можете использовать git , тогда rsync предоставит решение, но вам нужно будет вручную разработать решение для проверки файлов, которые вы хотите сравнить или объединить. С git эти различия автоматически отслеживаются.

Если они в основном бинарные файлы - возможно, вы захотите что-то сделать с rsync. Например, с помощью следующего скрипта: Для настройки теста:

set -x
for DIR in a b c ; do mkdir $DIR ; done
for DIR in `ls -d ?`; do
  echo "TESTMSG1-$DIR" >> $DIR/A;
  echo "TESTMSG2-$DIR" >> $DIR/B;
  echo "TESTMSG3-$DIR" >> $DIR/C;
  done
ls
ls -R
grep -r $ ?

И чтобы выполнить тест, с -av для подробной архивной копии и -c для сравнения файлов с контрольной суммой, и -b --suffix= для создания резервных копий файлов с отметкой времени для последующего сравнения:

rsync -avc -b --suffix=-$(date +%s.bk) a/ b
ls -R
grep -r $ ?
find . -name "*.bk"

Мы показываем, что файлы копируются, добавляется метка времени с .bk , а затем вы можете найти файлы резервных копий для дальнейшего анализа: find . -name "*.bk"

$ sh test.sh
...output deleted for brevity...
+ ls
a  b  c  test.sh
+ ls -R
a  b  c  test.sh

./a:
A  B  C
./b:
A  B  C
./c:
A  B  C
+ grep -r $ a b c
a/A:TESTMSG1-a
a/B:TESTMSG2-a
a/C:TESTMSG3-a
b/A:TESTMSG1-b
b/B:TESTMSG2-b
b/C:TESTMSG3-b
c/A:TESTMSG1-c
c/B:TESTMSG2-c
c/C:TESTMSG3-c

+ date +%s.bk
+ rsync -avc -b --suffix=-1403746846.bk a/ b
sending incremental file list
A
B
C
sent 300 bytes  received 73 bytes  746.00 bytes/sec
total size is 33  speedup is 0.09
+ ls -R
a  b  c  test.sh

./a:
A  B  C
./b:
A  A-1403746846.bk  B  B-1403746846.bk  C  C-1403746846.bk
./c:
A  B  C
+ grep -r $ a b c
a/A:TESTMSG1-a
a/B:TESTMSG2-a
a/C:TESTMSG3-a
b/A:TESTMSG1-a
b/A-1403746846.bk:TESTMSG1-b
b/B:TESTMSG2-a
b/B-1403746846.bk:TESTMSG2-b
b/C:TESTMSG3-a
b/C-1403746846.bk:TESTMSG3-b
c/A:TESTMSG1-c
c/B:TESTMSG2-c
c/C:TESTMSG3-c

+find . -name "*.bk"
./b/B-1403746846.bk
./b/C-1403746846.bk
./b/A-1403746846.bk

Другой альтернативой является использование моментальных снимков ZFS для «зеркалирования» каталогов в одно и то же пространство имен.«Псевдокод для этих шагов (поскольку передо мной нет zfs) будет выглядеть примерно так:

for X in (a b c); do 
  zfs snapshot zfs-destination@baseline
  rsync -avc /src-$X/ zfs-destination
  zfs snapshot zfs-destination@$X
  diff -r zfs-destination/ zfs-destination/.zfs/snapshot/$X/
  # analyze diff files and validate changes to commit
  # restore files to not change from .zfs/snapshot/baseline
done

Не то, чтобы вы могли «зацикливать» цикл как сценарий из-за ручного требования к анализу исправлений, но повторение вышеуказанных шагов для каждого исходного каталога даст вам возможность объединить и создать полную историю с помощью снимков. Замените «ab c» на что-то вроде date -Is чтобы пометить моментальные снимки.

Я пропустил команду zfs diff . Разница в строке выше должна быть:

zfs diff -FH zfs-destination/ zfs-destination@baseline | \
  awk '/^[+MR]\tF/ {print $3}' > list

Где awk выбирает (+) для добавленных файлов (M) для измененных (R) для переименованных. Это намного быстрее, чем рекурсивный diff для каталогов.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .