Tao zálohování s pevnými odkazy

24. 10. 2002
Doba čtení: 5 minut

Sdílet

Proč existují v linuxových souborových systémech pevné odkazy? Jak se liší od odkazů symbolických? V článku naleznete odpověď a na závěr si ukážeme elegantní způsob zálohování dat na pevný disk s využitím pevných odkazů.

Každý zřejmě ví, že pomocí příkazu ln můžeme v Linuxu tvořit symbolické odkazy (symlinks, příkaz ln -s) a pevné odkazy (hard links, příkaz ln bez parametru -s). Přestože se vytvářejí stejným příkazem, nemají symbolické a pevné odkazy mnoho společného a jejich využití a chování se značně liší.

V zásadě můžeme říci, že pevné odkazy jsou odkazy na soubor, kdežto symbolické odkazy jsou odkazy na jméno souboru. Pro vysvětlení předchozí věty si uděláme malou exkurzi do nitra souborového systému. Soubory v souborovém systému Linuxu jsou uloženy v lineární struktuře. Každý soubor je označen identifikačním číslem (inode number), které je pro daný soubor v souborovém systému jedinečné. Kromě tohoto „skladiště souborů“ obsahuje souborový systém ještě hierarchickou strukturu adresářů obsahující jména souborů. Každému jménu souboru je pak přiřazeno číslo inode souboru, na který dané jméno „ukazuje“.

Vše si ukážeme na příkladu. Příkaz ls má volbu -i, která ke každému jménu souboru vypíše číslo inode, na nějž jméno souboru ukazuje:

# ls -i1
  84970 fff
  84985 x.x
  84983 xxx
  84983 yyy

Jak vidíme, vazba mezi soubory a jmény souborů umožňuje, aby jeden fyzický soubor na disku měl několik odpovídajících jmen souboru, případně žádné (návod, jak vytvořit v Linuxu soubor beze jména, zde raději nebudu uvádět, protože si nedokážu přestavit žádné legální využití této „featury“ :-)) Pojmem pevný odkaz (hard link) se rozumí právě vazba mezi inode souboru a jménem souboru.

Oproti pevnému odkazu je symbolický odkaz (symlink) speciální soubor, který obsahuje cestu k jinému jménu souboru. Vlastní soubory a jejich inode v symbolickém odkazu nefigurují. Nyní se budeme věnovat tomu, co rozdíly mezi symbolickými a pevnými odkazy znamenají v praxi.

Náročnost na diskový prostor

Pevný odkaz je vlastně pouze jedna položka v adresářové struktuře (jméno odkazu). Symbolický odkaz naproti tomu vyžaduje položku v adresářové struktuře (jméno odkazu) a speciální soubor, ve kterém je zapsána cesta k cílovému jménu souboru. Pevné odkazy tedy zabírají méně místa.

Univerzálnost

Pevné odkazy jsou, díky své vazbě na inode, omezeny na použití v rámci jednoho souborového systému. Navíc není možné tvořit pevné odkazy na adresáře. Symbolické odkazy, díky použití jmen souborů, mohou ukazovat i na adresáře a nejsou omezeny na jeden souborový systém, lze je použít i na svazky připojené pomocí NFS apod. Díky této vlastnosti byly do UNIXu také zavedeny.

Síla vazby mezi odkazem a cílovým souborem

Pokud smažeme nebo přesuneme soubor, na který ukazuje symbolický odkaz, přestane odkaz fungovat (broken link). U pevných odkazů je tomu jinak. Nově vytvořený pevný odkaz nemá žádnou vazbu na původní jméno souboru, takže s původním souborem můžeme manipulovat (přesouvat, mazat), aniž by se to jakkoli dotklo našeho odkazu. Zvídavý čtenář si teď jistě klade otázku, jak systém pozná, zda má při mazání souboru vymazat pouze položku v adresářové struktuře, nebo i vlastní soubor (inode). K tomuto účelu se pro každý soubor (inode) udržuje čítač, obsahující počet pevných odkazů na daný soubor. Při mazání souboru pak systém vymaže položku v adresářové struktuře a zmenší čítač odkazů o jedničku. Jakmile čítač dosáhne nuly, vymaže se i vlastní soubor. Také proto se v jazyce C funkce pro smazání souboru jmenuje unlink(), a ne třeba delete() nebo remove(). Pro zjištění, kolik jmen souborů ukazuje na daný soubor, můžeme v shellu použít příkaz stat (položka Links):

# stat xxx
  File: `xxx'
  Size: 5               Blocks: 8          IO Block: 4096 Regular File
Device: 342h/834d       Inode: 84983       Links: 2
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (  0/    root)
Access: 2002-10-14 18:08:29.000000000 +0200
Modify: 2002-10-15 11:43:46.000000000 +0200
Change: 2002-10-15 11:43:46.000000000 +0200

Správa odkazů

Běžný souborový systém v Linuxu obsahuje hned po instalaci několik tisíc jak symbolických, tak pevných odkazů. Symbolické odkazy, které jsou speciálním typem souboru, lze je snadno vyhledat například pomocí příkazu find:

 find / -type l -print

U pevných odkazů je situace složitější. Mezi jednotlivými jmény souborů ukazujících na jeden inode neexistuje žádná vazba. Je tedy potřeba projít celý souborový systém, najít soubory, které mají více než jedno jméno, a jména pak spárovat podle čísla inode. Viz tento krátký skript find_hard_links:

#!/bin/sh

res="";
for i in `find $1 -type f -xdev -print`; do
    if [[ `stat -c "%h" $i` > 1 ]]; then
        res="`stat -c %i $i` $i\n"$res;
    fi
done
echo -e $res | sort

Vyhledávání může v závislosti na množství souborů trvat značně dlouho.

Zálohování s využitím pevných odkazů

Při dnešních cenách hardware mnoho uživatelů zálohuje data na pevné disky. Jedna ze základních zkušeností při zálohování říká, že není problém data zálohovat, problém představuje je v případě potřeby obnovit, zvláště používáme-li inkrementální zálohy.

Protože při zálohování na pevný disk máme k dispozici souborový systém včetně pevných odkazů, ukážeme si, jak tvořit komfortní řady záloh, které se tváří jako kompletní „kopie“ zálohovaných dat v daném čase a přitom zabírají velmi málo místa. Trik je v tom, že v zálohovaných datech je od poslední zálohy vždy jen určité množství změn a zbytek souborů zůstává stejný. Místo udržování několika kopií takových nezměněných souborů použijeme pevné odkazy.

Teď už jen potřebujeme mechanismus, který nezměněné soubory ponechá a u změněných souborů vytvoří novou kopii, na kterou se neodkazují ostatní zálohy. Přesně takto se chová synchronizační utilita rsync. Postup při zálohování pak bude následující:

  • Vytvoříme kopii aktuální zálohy pomocí pevných odkazů (příkaz cp -l)
  • Spustíme rsync, který aktualizuje změněné soubory v aktuální záloze

Zde je hotový skript do_backup, který můžeme spouštět v určitých intervalech pomocí cron:

!/bin/sh

#Number of backup copies to keep
NUM_DIRS=5

#Source and destination dirs for backup
SOURCE=/home
DEST=/nekam/backup

#See how many dirs already exist, purge if neccessary
if [[ `ls $DEST | wc -l | awk '{print $1;}'` == $NUM_DIRS ]]; then
  rm -rf $DEST/`ls $DEST | head -1`;
fi

#If exists 'current' copy it to its time's dir
if [ -d $DEST/current ]; then
  NAME=`ls -ld --time-style="+%F-%T" $DEST/current |
   awk '{print $6;}'`;
  #mkdir $DEST/$NAME
  cp -al $DEST/current $DEST/$NAME
fi

#Do rsync
rsync -a --delete $SOURCE/  $DEST/current/
touch $DEST/current

v adresáři /nekam/backup pak bude adresář current, obsahující aktuální zálohu a adresáře označené datumem a časem, obsahující předchozí zálohy:

bitcoin_skoleni

ls -1 backup
2002-10-14-10:29:56/
2002-10-15-10:29:57/
2002-10-16-10:29:58/
2002-10-17-10:42:28/
current/

Jednotlivé adresáře se tváří jako naprosto nezávislé, obsahující kompletní kopii zálohovaných dat, všechny nezměněné soubory jsou však ve skutečnosti na disku uloženy pouze jednou a výrazně se šetří diskový prostor.

Pro úplnost ještě připomeňme, že pokud se u souboru změní pouze přístupová práva, rsync nevytvoří kopii souboru a změna se tak projeví i ve všech předchozích zálohách.

Autor článku