Sistema de arquivos Union com nomes de arquivos “versionados”?

5

Você sabe se existe um fs unificado para GNU / Linux que mostra também arquivos "sombreados" com nomes ligeiramente diferentes? I.E. se eu tiver dois fs como:

root1
+dir1
+dir2
 +file1
 +file2
 +file3

root2
+dir1
+dir2
 +file1
 +file2
 +file4

O resultante "unioned" fs deve resultar:

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

Para que seja possível verificar rapidamente as diferenças entre o "unioned" fs

Parece que a UnionFS e a Aufs não oferecem essa opção

Obrigado

    
por atrent 09.06.2014 / 15:14

3 respostas

1

Uma alternativa usando git-annex :

Primeiro, vamos configurar os arquivos de teste:

#!/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

Isso cria os diretórios, com arquivos binários contendo dados aleatórios. Neste ponto, os arquivos são:

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

Agora, inicializamos os repositórios e realizamos uma sincronização:

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 ..

Neste ponto, o conteúdo de 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

Em que *.variant-* vincula os arquivos diferentes nos diferentes repositórios. Além disso, unioned ainda não contém dados até que conduzamos um git annex get . Por enquanto, git annex list mostra onde os arquivos estão localizados e / ou provenientes de:

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

Uma alternativa em um formato mais longo é git annex whereis . Finalmente, para resolver os conflitos e propagar a mesclagem, de dentro de 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

Quais rendimentos:

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

Por fim, um git annex list mostra onde esses arquivos estão localizados após a sincronização: o diretório unioned/ tem cópias de todos os arquivos, escolhidos nos diferentes servidores conforme acima.

git-annex também tem um modo direto que opera diretamente no sistema de arquivos sem o uso de links simbólicos.

Configurar isso para uso em computadores remotos é uma questão de configurar controles remotos sobre o ssh usando o git padrão, no entanto, o comportamento é descrito aqui: link

O passo a passo geral do git anexo está localizado aqui: link

    
por 23.11.2014 / 05:26
0

A resposta à pergunta original parece ser "não no momento".

Soluções alternativas foram propostas: elas são baseadas:

  • em uma ferramenta notória (rsync, com a opção de backup ativada)
  • em sistemas de arquivos especiais (como ZFS ou btrfs) que oferecem "instantâneos"

Ambas as propostas envolvem E / S pesadas porque criam um novo sistema de arquivos em vez de mapear os existentes em um sistema de arquivos virtual.

    
por 04.07.2014 / 08:40
0

Em vez de olhar para o nível do sistema de arquivos, você precisa ver / manter as diferenças entre as versões. Se forem arquivos de texto, o link git fornecerá uma boa solução. git é um sistema de controle de versão usado para o código-fonte, e lida com ambos, comparando múltiplos diretórios de arquivos (aka repositórios), mas ramificando, difere e mescla.

Se você não puder usar git , o rsync fornecerá uma solução, mas você precisará desenvolver manualmente uma solução para examinar os arquivos que deseja comparar ou mesclar. Com o git essas diferenças são rastreadas automaticamente.

Se eles são principalmente arquivos binários - você pode querer fazer algo com o rsync. Por exemplo, com o seguinte script: Para configurar o teste:

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 $ ?

E para executar o teste, com -av para cópia de arquivo detalhado e -c para comparar os arquivos com uma soma de verificação e -b --suffix= para criar backups de arquivos com registro de data e hora para comparação posterior:

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

Mostramos que os arquivos são copiados, um sufixo .bk com carimbo de hora é adicionado e, em seguida, você pode encontrar os arquivos de backup para análise posterior: 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

Outra alternativa é usar os instantâneos do ZFS para "espelhar" os diretórios no mesmo "namespace". Pseudo-código para essas etapas (já que não tenho zfs na minha frente) seria algo como:

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

Não que você 'possa' fazer loop como um script, devido ao requisito manual de analisar as correções, mas repetir as etapas acima para cada diretório de origem forneceria a capacidade de mesclagem e um histórico completo por meio de instantâneos. Substitua 'a b c' por algo como date -Is para marcar a hora dos instantâneos.

Ignorei o comando zfs diff . A linha de diferenças acima deve ser:

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

Where awk seleciona (+) para arquivos adicionados (M) para modificados (R) para renomeados. Isso é muito mais rápido que o diff recursivo nos diretórios.

    
por 26.06.2014 / 03:57