FK~

Moje odkazy

Ostatní odkazy

Close Windows
Nenajdete mě na Facebooku ani Twitteru
Rozpad EU
Jsem členem FSF
There Is No Cloud …just other people's computers.
Sane software manifesto / Manifest příčetného softwaru

Zálohujeme internet: Zdrojové kódy

vydáno: 26. 4. 2019 19:48, aktualizováno: 13. 1. 2020 17:33

Říká se, že když něco vypustíte na internet, už to nejde vzít zpátky – ostatní to začnou kopírovat a informace/data se nekontrolovatelně šíří. Bohužel to ale platí spíš v případech, kdy byste to vzít zpátky chtěli. A naopak jindy se může stát, že hodnotný obsah zmizí a už jej nedohledáte. Software resp. jeho zdrojové kódy se většinou neztrácejí – alespoň ne ty hojně používané programy – u nich se vždy najde někdo, kdo měl kopii a podělí se o ni s ostatními. Ale u různých menších programů a knihoven se klidně může stát, že je autor smaže a už je nedohledáte.

Mercurial a Git – zálohujeme zdrojové kódy

Tohle je jeden z důvodů, proč mít zálohované zdrojové kódy programů, které používáme. V tomto článku se tedy podíváme na to, jak tyto zálohy systematicky udržovat.

Jak se říká: buď připraven. Pak jen sáhneme do vlastních záloh – třeba až na nás příště vyskočí 404 Page not found na GitHubu (i když tam se to běžně děje i kvůli tomu, že autor jen přešel z této proprietární služby na svobodný a lépe vybavený Gitlab nebo na vlastní hosting – takže dané zdrojáky ztracené nejsou). Dalším důvodem k zálohování je příprava na situaci, že se my sami ocitneme offline nebo dojde k rozpadu globální sítě. O tom si ale povíme zase příště.

Požadavky

Než začneme něco dělat, je dobré si sepsat požadavky, které na dané řešení máme. Chceme něco trochu robustnějšího než když běžně klonujeme cizí zdrojáky do lokálního adresáře na disku své pracovní stanice nebo notebooku. Na druhou stranu by to mělo být jednoduché řešení s minimem závislostí. Chceme tedy:

  • Podporu dvou hlavních verzovacích systémů, kterými jsou Mercurial (Hg) a Git. Další systémy jako Subversion (SVN), Fossil, Monotone, Bazaar (Bzr) a další můžeme přidat později v případě potřeby.
  • Automatické stahování nových změn – chceme mít vždy k dispozici poslední verzi od původního autora.
  • Zároveň nechceme za žádnou cenu přijít o historii – zálohy by měly být nezničitelné a co se do nich jednou zapsalo, to už by se nemělo nikdy ztratit nebo přepsat (tzn. integrita dat).
  • HTTPS přístup pouze pro čtení – abychom mohli např. někomu poslat odkaz nebo si mohli sami ty zdrojáky odkudkoli stáhnout.
  • SSH přístup pro čtení i zápis – můžeme zde hostovat i úložiště, do kterých zapisujeme resp. které se neaktualizují automaticky, ale děláme do nich push odněkud jinud.
  • Do systému by mělo „být vidět“ a měl by poskytovat přehledy o svém stavu ve strojově čitelném formátu.

Návrh řešení

Samozřejmě se nabízí otázka, zda nepoužít nějaké hotové řešení. Existuje řada nadstaveb nad verzovacími systémy, které jsou určené k tomu, abyste si zprovoznili vlastní hosting se vším všudy (Kallithea, Phabricator, Gitlab, Gitea a další), ale většinou jim něco chybí (např. podporují jen jeden VCS), spousta jim toho přebývá a trpí vysokou komplexitou (stovky tisíc nebo milion řádků kódu).

Proto jsem se vydal minimalistickou cestou, kdy řešení poskládám jen ze samotného verzovacího systému (Mercurial, Git a v budoucnu možná další) a ze základních nástrojů poskytovaných operačním systémem.

Úloha je to v principu jednoduchá: potřebujeme udělat clone vzádáleného úložiště, a pak v periodických intervalech dělat pull, abychom si průběžně dotahovali změny. Systém potřebujeme nějak ovládat (přidávat nová úložiště) a zjišťovat, v jakém je stavu.

Operace clonepull zavoláme z bashového skriptu. Přidání nového úložiště se bude dělat vzdáleně přes SSH a periodická aktualizace klasicky přes Cron.

Kromě toho budeme každý den dělat snapshot na úrovni souborového systému (Btrfs), abychom nepřišli o historii. Někomu to možná přijde zbytečně paranoidní – verzovací systém by měl přeci sám o sobě zachovávat historii – ale není tomu tak. Verzovací systémy sice historii uchovávají, ale zároveň ji umožňují přepisovat. Sice by se to dělat nemělo (zvlášť na úložišti, které si někdo jiný stahuje), ale zabránit tomu nelze. Pokud by např. někdo skrize git push --force dostal na vzdálené úložiště destruktivní změny, historie by se ztratila i u nás na zálohovacím serveru. Pokud se tomu budeme bránit, tak zase hrozí, že se nám stahování aktualizací zasekne a nebudou se nám stahovat nové změny. Mercurial si dává větší pozor na zachování historie než Git, takže u něj bychom o dříve stažené změny přijít neměli, ale jistota je jistota. Snapshoty na úrovni Btrfs nás nestojí prakticky nic. Takže i kdyby se na původním URL objevilo třeba prázdné nebo úplně jiné úložiště, o dříve stažená data nepřijdeme.

Jednotlivé části systému běží pod různými uživateli a musí spolu nějak komunikovat. Potřebujeme tedy nějakou formu IPC (meziprocesové komunikace). Pro jednoduchost jsem vybral unixové doménové sokety (UDS) v jejich datagramové variantě (tzn. bez navazování spojení – jen posílání zpráv). Alternativně bychom mohli použít sudo nebo SUID bit.

Pro přístup přes HTTP použijeme Apache2, vestavěné webové rozhraní Mercurialu a pro Git rozhraní cgit.

Stručně: napíšeme si jeden skript s pár funkcemi, které budeme volat buď přes SSH nebo z Cronu, a k tomu přidáme už jen nějakou konfiguraci serveru.

Soukromí

Neměli bychom zapomínat na ochranu soukromí. Když totiž vystavíme svůj zálohovací server na internetu, tak tím zveřejňujeme, co nás zajímá, na čem pracujeme… což nemusí být vždy žádoucí. Na druhou stranu, některé věci zálohujeme, protože na ně chceme odkazovat a chceme je zpřístupnit i ostatním, zvlášť, když je pravděpodobné, že z původního umístění mohou zmizet. Řešením je nenasměrovat webová rozhraní (hg servecgit) na adresář, kam zálohujeme vzdálená úložiště, ale na jiný adresář, do kterého budeme dávat pouze symbolické odkazy na úložiště určená ke zveřejnění. Ke všem (veřejným i neveřejným) pak můžeme přistupovat přes SSH (klonování na lokální disk).

Seznam materiálu

Budeme potřebovat:

  • virtuální stroj (může být i fyzický, ale to je asi zbytečné), typicky KVM/Qemu
  • GNU/Linux – spolehlivý základ; běžné distribuce obsahují všechny další součásti:
  • Btrfs – souborový systém s podporou snapshotů
  • Mercurial
  • Git + cgit
  • Apache HTTP server
  • OpenSSH
  • GNU Bash – univerzální lepidlo, skriptování
  • Cron – automatické spouštění úloh

Vše je samozřejmě svobodný software (jinak bychom tomu nemohli důvěřovat).

Implementace

Implementace spočívá v nakonfigurování systému a v napsání krátkého shellového skriptu.

GNU/Linux

Je celkem jedno, jakou distribuci zvolíme. Následující postup je pro distribuce založené na Debianu/Ubuntu, ale nepoužíváme zde nic speciálního, takže obdobně by to mělo fungovat i v jiných distribucích.

Nainstalujeme si potřebné balíčky:

apt install socat mercurial git cgit apache2

Souborový systém: Btrfs

Je dobré oddělit disk pro data (časem může zabírat hodně místa – záleží, jak velkou část internetu budeme zálohovat) a pro operační systém (ten zase můžeme chtít časem přeinstalovat). Pro začátek jsem udělal 10 GB systémový disk a 40 GB datový, který budu postupně rozšiřovat (na úrovní hypervizoru je LVM). Datový disk je připojený v /mnt/data, což jsem nastavil v /etc/fstab.

Každé úložiště bude mít svůj vlastní Btrfs pododdíl (subvolume) a každý den svůj vlastní snapshot. Lépe tak uvidíme, kolik místa co zabírá, a když nějaké úložiště budeme chtít vyřadit, jednoduše smažeme příslušné oddíly a nebudeme muset mazat soubor po souboru. Případně si časem můžeme nastavit kvóty pro jednotlivá uložiště, aby nám jedno nevyplýtvalo všechno místo na disku a nenarušilo zálohování ostatních.

Init systém: systemd

Použil jsem systemd, protože je v mé distribuci. Pokud ale používáte jiný init systém, není problém služby spouštět přes něj.

vcs-backup-createSubvolume.service – tato služba naslouchá na UDS a čeká na požadavky na vytvoření Btrfs oddílů pro nově zakládaná úložiště. Proto musí běžet pod rootem – mohli bychom sice změnit vlastníka disku, ale pak by tentýž uživatel mohl i mazat oddíly, takže mi přišlo vhodnější to takto izolovat a udělat z toho službu:

[Unit]
Description = VCS Backup: createSubvolume
After = network.target

[Service]
ExecStart = /usr/local/bin/vcs-backup.sh serverStartSubvolumeService

[Install]
WantedBy = multi-user.target

vcs-backup-clone.service – tato služba funguje v principu stejně (taky čeká na požadavky na UDS) a stará se o samotné stažení zdrojových kódů z původního vzdáleného úložiště. Protože stahuje data do složky připravené v přechozím kroku s nastavenými právy, může už běžet pod neprivilegovaným uživatelem:

[Unit]
Description = VCS Backup: clone
After = network.target

[Service]
User=vcs-backup
ExecStart = /usr/local/bin/vcs-backup.sh serverStartCloneService

[Install]
WantedBy = multi-user.target

vcs-backup-web-hg.service – tato služba zpřístupňuje veřejná mercurialová úložiště přes HTTP:

[Unit]
Description = Mercurial
After = syslog.target network.target

[Service]
User=vcs-backup
ExecStart = /usr/bin/hg serve --web-conf /mnt/data/etc/hg-serve.cfg --address 127.0.0.1 --port 16169
SuccessExitStatus = 255

[Install]
WantedBy = multi-user.target

; Obsah hg-serve.cfg:
; [paths]
; / = /mnt/data/public/hg/*
; [web]
; style = gitweb

Před ní je jako reverzní proxy Apache. Webové rozhraní pro Git je řešeno jako CGI skript, takže v systemd ho nenastavujeme.

Webový server: Apache2

HTTP server Apache se používá pouze pro webové rozhraní k veřejným úložištím. Každý typ verzovacího systému má vlastní subdoménu – zatím máme tedy dva virtualhosty:

Mercurial:

<VirtualHost *:80>
                ServerNameServerAliasServerAdmin webmaster@localhost
                DocumentRoot /var/www/html

                ProxyPass "/" "http://localhost:16169/"
                ProxyPassReverse "/" "http://localhost:16169/"

                ErrorLog ${APACHE_LOG_DIR}/error.log
                CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

Git:

<VirtualHost *:80>
                ServerNameServerAliasServerAdmin webmaster@localhost
                DocumentRoot /var/www/html

                Alias /cgit-css "/usr/share/cgit/"
                ScriptAlias / "/usr/lib/cgit/cgit.cgi/"
                <Directory "/usr/share/cgit/">
                        AllowOverride None
                        Options None
                        Require all granted
                </Directory>
                <Directory "/usr/lib/cgit/">
                        AllowOverride None
                        Options ExecCGI FollowSymlinks
                        Require all granted
                </Directory>

                ErrorLog ${APACHE_LOG_DIR}/error.log
                CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

HTTPS jsem zde neřešil, protože na vnitřní síti mám ještě jednu reverzní proxy, která se o šifrování stará.

Cron

Pravidelně spouštěné úlohy si naplánujeme klasicky v Cronu. První stahuje nové změny (pull):

root@zdrojaky:~# crontab -l -u vcs-backup
# m  h  dom mon dow   command
 10 23    *   *   *   /usr/local/bin/vcs-backup.sh serverPullCronTask > /mnt/data/log/pull.rec

a druhá vytváří snapshoty:

root@zdrojaky:~# crontab -l -u root
# m  h  dom mon dow   command
 55 23    *   *   *   /usr/local/bin/vcs-backup.sh serverSnapshotCronTask > /mnt/data/log/snapshot.rec

Skript vcs-backup.sh

Všechny funkce jsou implementované ve skriptu vcs-backup.sh. Stažení aktuální verze:

hg clone https://hg.frantovo.cz/vcs-backup/

Pro jednoduchost se používá jeden skript na serveru i na klientovi. Při ovládání systému tak volá skript přes SSH svoji kopii nacházející se na serveru. Vše tak máme v jednom souboru (cca 230 řádek kódu), který můžeme snadno upravovat – a pak jen přes scp nahrajeme na server.

Metadata a logy

Systém nepotřebuje žádnou databázi. Metadata jsou „zakódovaná“ v adresářové struktuře a případně v jednotlivých textových souborech (url.txtstate.txt). Logy periodicky prováděných operací, stejně jako výpis úložišť, jsou ve strojově čitelném textovém formátu recfile.

Konfigurace

Jedinou věc, kterou potřebujeme nastavit, je adresa serveru v souboru ~/.config/vcs-backup/client.cfg. Server má sice taky svůj konfigurační soubor /etc/vcs-backup/server.cfg, ve kterém lze přepsat výchozí nastavení, ale ten není potřeba upravovat.

Použití

Když spustíme skript bez parametrů, vypíše nám funkce/příkazy svého „veřejného API“:

$ ./vcs-backup.sh 
Unsupported sub-command: 
Available sub-commands:
  clientListRepositories
  clientSubmitBackupRequest
  serverListRepositories
  serverPullCronTask
  serverSnapshotCronTask
  serverStartCloneService
  serverStartSubvolumeService
  serverSubmitBackupRequest

Z jejich názvů je zřejmé, zda se spouštějí na klientovi nebo na serveru a zda se tam volají přes Cron nebo jako služba. Nás budou zajímat hlavně ty dva klientské příkazy. Kromě toho tam jsou pro často používané operace připravené zkratky:

vcs-backup-clone-private-git
vcs-backup-clone-private-hg
vcs-backup-clone-public-git
vcs-backup-clone-public-hg

které volají clientSubmitBackupRequest s různými parametry. Jsou to symbolické odkazy na tentýž skript (ten se podívá, pod jakým názvem byl spuštěn, a podle toho pokračuje). Do skriptu si můžeme snadno dopsat další zkratky nebo funkce dle potřeby.

Zálohování a volitelné lokální klonování

Základní operací je přidání nového úložiště.

# přidání mercurialového úložiště:
vcs-backup.sh clientSubmitBackupRequest hg "https://…";

# přidání mercurialového úložiště
# + jeho zveřejnění přes webové rozhraní:
vcs-backup.sh clientSubmitBackupRequest hg "https://…" public;

# přidání mercurialového úložiště
# + jeho zveřejnění přes webové rozhraní
# + stažení na lokální disk z naší nové zálohy:
vcs-backup.sh clientSubmitBackupRequest hg "https://…" public clone;

V případě gitu akorát píšeme git místo hg. Místo public můžeme dát private, ale povinné je to jen v případě, kdy chceme zároveň klonovat na místní disk na klientské straně.

Případně použijeme ty zkratky jako vcs-backup-clone-private-hg, u kterých zadáme už jen URL. Práce se systémem tak není o nic náročnější než klasické hg clone https://example.com/… nebo git clone https://example.com/…. Získáváme ale spolehlivou zálohu, která se automaticky aktualizuje. Lokálně stažené zdrojáky také můžeme po prozkoumání smazat, ale na serveru nám zůstanou a nepřijdeme o ně.

Příkazy by měly být tzv. idempotentní, což znamená, že je můžeme volat opakovaně a výsledek bude pořád stejný – nevadí tedy, pokud nějaké úložiště (totožné URL) přidáme víckrát – přidané bude jen jednou. Hodí se to pro případ, kdy chceme podruhé něco lokálně naklonovat z našeho zálohovacího serveru, nebo když chceme změnit stav veřejný/neveřejný.

Přehledy

Důležité je, aby systém nebyl černá skříňka a abychom věděli, co se uvnitř děje, a mohli se snadno podívat, v jakém je stavu. Skript proto umožňuje vypsat zálohovaná úložiště a jejich stav, velikost a čas poslední změny:

$ ssh vcs-backup@$server vcs-backup.sh serverListRepositories | relpipe-in-recfile | relpipe-out-tabular 
repository:
 ╭───────────────┬───────────────────────────────────────────────────────┬────────────────┬─────────────────┬────────────────────────────────────────────────────────────────────┬───────────────┬───────────────────────────╮
 │ type (string) │ url                                          (string) │ state (string) │ public (string) │ serverPath                                                (string) │ size (string) │ lastCommit       (string) │
 ├───────────────┼───────────────────────────────────────────────────────┼────────────────┼─────────────────┼────────────────────────────────────────────────────────────────────┼───────────────┼───────────────────────────┤
 │ git           │ https://github.com/bafe/gr-pocsag                     │ cloned         │ true            │ /mnt/data/current/git/github.com/bafe/gr-pocsag                    │ 71935         │ 2013-01-06 15:02:46 +0100 │
 │ git           │ https://github.com/Bystroushaak/clanky                │ cloned         │ true            │ /mnt/data/current/git/github.com/Bystroushaak/clanky               │ 98421427      │ 2019-04-18 12:51:25 +0200 │
 │ git           │ https://github.com/clibs/dumpasn1                     │ cloned         │ true            │ /mnt/data/current/git/github.com/clibs/dumpasn1                    │ 55006         │ 2014-06-26 22:57:50 +0900 │
 │ git           │ https://github.com/FreeSpacenav/libspnav              │ cloned         │ true            │ /mnt/data/current/git/github.com/FreeSpacenav/libspnav             │ 99028         │ 2018-08-23 05:26:22 +0300 │
 │ git           │ https://github.com/JaroslavTulach/sieve               │ cloned         │ true            │ /mnt/data/current/git/github.com/JaroslavTulach/sieve              │ 105181        │ 2017-02-16 04:19:33 +0100 │
 │ git           │ https://github.com/JaroslavTulach/talk2compiler       │ cloned         │ true            │ /mnt/data/current/git/github.com/JaroslavTulach/talk2compiler      │ 48963         │ 2019-04-09 11:50:25 +0200 │
 │ git           │ https://github.com/rvoicilas/inotify-tools            │ cloned         │ true            │ /mnt/data/current/git/github.com/rvoicilas/inotify-tools           │ 325646        │ 2018-03-06 10:26:28 +0200 │
 │ git           │ https://github.com/vlm/asn1c                          │ cloned         │ true            │ /mnt/data/current/git/github.com/vlm/asn1c                         │ 20712839      │ 2019-02-10 01:15:52 -0800 │
 │ hg            │ https://bitbucket.org/pidgin/main                     │ cloned         │ true            │ /mnt/data/current/hg/bitbucket.org/pidgin/main                     │ 179601587     │ 2019-04-15 07:00:44 +0000 │
 │ hg            │ https://hg.frantovo.cz/alt2xml                        │ cloned         │ true            │ /mnt/data/current/hg/hg.frantovo.cz/alt2xml                        │ 426611        │ 2014-10-29 02:03:14 +0100 │
 │ hg            │ https://hg.frantovo.cz/spacenav/spacenav-demo-qt      │ cloned         │ true            │ /mnt/data/current/hg/hg.frantovo.cz/spacenav/spacenav-demo-qt      │ 42225         │ 2019-03-07 18:33:22 +0100 │
 │ hg            │ https://hg.frantovo.cz/spacenav/spacenav-lib-hack     │ cloned         │ true            │ /mnt/data/current/hg/hg.frantovo.cz/spacenav/spacenav-lib-hack     │ 31380         │ 2019-03-09 12:30:52 +0100 │
 │ hg            │ https://hg.frantovo.cz/spacenav/spacenav-simulator-qt │ cloned         │ true            │ /mnt/data/current/hg/hg.frantovo.cz/spacenav/spacenav-simulator-qt │ 36094         │ 2019-03-15 00:14:25 +0100 │
 │ hg            │ https://hg.frantovo.cz/sql-api                        │ cloned         │ true            │ /mnt/data/current/hg/hg.frantovo.cz/sql-api                        │ 13638         │ 2014-09-02 10:25:23 +0200 │
 │ hg            │ https://hg.frantovo.cz/sql-dk                         │ cloned         │ true            │ /mnt/data/current/hg/hg.frantovo.cz/sql-dk                         │ 592699        │ 2019-03-04 22:28:29 +0100 │
 │ hg            │ https://hg.frantovo.cz/telco-dictionary               │ cloned         │ true            │ /mnt/data/current/hg/hg.frantovo.cz/telco-dictionary               │ 185192        │ 2014-04-29 12:16:27 +0200 │
 ╰───────────────┴───────────────────────────────────────────────────────┴────────────────┴─────────────────┴────────────────────────────────────────────────────────────────────┴───────────────┴───────────────────────────╯
Record count: 16

Aktualizaci všech úložišť budeme normálně spouštět z Cronu, ale můžeme si ji pustit i ručně a prohlédnout si výsledky:

$ ssh vcs-backup@$server vcs-backup.sh serverPullCronTask | relpipe-in-recfile | relpipe-out-tabular 
pull:
 ╭────────────────────────────────────────────────────────────────────┬───────────────┬────────────────┬───────────────────────────┬───────────────────────────┬───────────────────┬─────────────────────┬───────────────────────────────────────────────────────────────────────────────────────────────────────────╮
 │ serverPath                                                (string) │ type (string) │ state (string) │ started          (string) │ finished         (string) │ duration (string) │ resultCode (string) │ message                                                                                          (string) │
 ├────────────────────────────────────────────────────────────────────┼───────────────┼────────────────┼───────────────────────────┼───────────────────────────┼───────────────────┼─────────────────────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────┤
 │ /mnt/data/current/git/github.com/bafe/gr-pocsag                    │ git           │ cloned         │ 2019-04-24T20:31:04+00:00 │ 2019-04-24T20:31:05+00:00 │ 674               │ 0                   │                                                                                                           │
 │ /mnt/data/current/git/github.com/Bystroushaak/clanky               │ git           │ cloned         │ 2019-04-24T20:31:05+00:00 │ 2019-04-24T20:31:06+00:00 │ 600               │ 0                   │                                                                                                           │
 │ /mnt/data/current/git/github.com/clibs/dumpasn1                    │ git           │ cloned         │ 2019-04-24T20:31:06+00:00 │ 2019-04-24T20:31:06+00:00 │ 607               │ 0                   │                                                                                                           │
 │ /mnt/data/current/git/github.com/FreeSpacenav/libspnav             │ git           │ cloned         │ 2019-04-24T20:31:06+00:00 │ 2019-04-24T20:31:07+00:00 │ 627               │ 0                   │                                                                                                           │
 │ /mnt/data/current/git/github.com/JaroslavTulach/sieve              │ git           │ cloned         │ 2019-04-24T20:31:07+00:00 │ 2019-04-24T20:31:08+00:00 │ 583               │ 0                   │                                                                                                           │
 │ /mnt/data/current/git/github.com/JaroslavTulach/talk2compiler      │ git           │ cloned         │ 2019-04-24T20:31:08+00:00 │ 2019-04-24T20:31:08+00:00 │ 615               │ 0                   │                                                                                                           │
 │ /mnt/data/current/git/github.com/rvoicilas/inotify-tools           │ git           │ cloned         │ 2019-04-24T20:31:08+00:00 │ 2019-04-24T20:31:09+00:00 │ 641               │ 0                   │                                                                                                           │
 │ /mnt/data/current/git/github.com/vlm/asn1c                         │ git           │ cloned         │ 2019-04-24T20:31:09+00:00 │ 2019-04-24T20:31:10+00:00 │ 694               │ 0                   │                                                                                                           │
 │ /mnt/data/current/hg/bitbucket.org/pidgin/main                     │ hg            │ cloned         │ 2019-04-24T20:31:10+00:00 │ 2019-04-24T20:31:11+00:00 │ 1395              │ 0                   │ pulling from https://bitbucket.org/pidgin/main↲searching for changes↲no changes found                     │
 │ /mnt/data/current/hg/hg.frantovo.cz/alt2xml                        │ hg            │ cloned         │ 2019-04-24T20:31:11+00:00 │ 2019-04-24T20:31:13+00:00 │ 1525              │ 0                   │ pulling from https://hg.frantovo.cz/alt2xml↲searching for changes↲no changes found                        │
 │ /mnt/data/current/hg/hg.frantovo.cz/spacenav/spacenav-demo-qt      │ hg            │ cloned         │ 2019-04-24T20:31:13+00:00 │ 2019-04-24T20:31:14+00:00 │ 1318              │ 0                   │ pulling from https://hg.frantovo.cz/spacenav/spacenav-demo-qt↲searching for changes↲no changes found      │
 │ /mnt/data/current/hg/hg.frantovo.cz/spacenav/spacenav-lib-hack     │ hg            │ cloned         │ 2019-04-24T20:31:14+00:00 │ 2019-04-24T20:31:16+00:00 │ 1656              │ 0                   │ pulling from https://hg.frantovo.cz/spacenav/spacenav-lib-hack↲searching for changes↲no changes found     │
 │ /mnt/data/current/hg/hg.frantovo.cz/spacenav/spacenav-simulator-qt │ hg            │ cloned         │ 2019-04-24T20:31:16+00:00 │ 2019-04-24T20:31:16+00:00 │ 668               │ 0                   │ pulling from https://hg.frantovo.cz/spacenav/spacenav-simulator-qt↲searching for changes↲no changes found │
 │ /mnt/data/current/hg/hg.frantovo.cz/sql-api                        │ hg            │ cloned         │ 2019-04-24T20:31:17+00:00 │ 2019-04-24T20:31:18+00:00 │ 1401              │ 0                   │ pulling from https://hg.frantovo.cz/sql-api↲searching for changes↲no changes found                        │
 │ /mnt/data/current/hg/hg.frantovo.cz/sql-dk                         │ hg            │ cloned         │ 2019-04-24T20:31:18+00:00 │ 2019-04-24T20:31:19+00:00 │ 1247              │ 0                   │ pulling from https://hg.frantovo.cz/sql-dk↲searching for changes↲no changes found                         │
 │ /mnt/data/current/hg/hg.frantovo.cz/telco-dictionary               │ hg            │ cloned         │ 2019-04-24T20:31:19+00:00 │ 2019-04-24T20:31:21+00:00 │ 2003              │ 0                   │ pulling from https://hg.frantovo.cz/telco-dictionary↲searching for changes↲no changes found               │
 ╰────────────────────────────────────────────────────────────────────┴───────────────┴────────────────┴───────────────────────────┴───────────────────────────┴───────────────────┴─────────────────────┴───────────────────────────────────────────────────────────────────────────────────────────────────────────╯
Record count: 16

V terminálu jsou tabulky barevné:

VCS Backup: výpis úložišť a výsledek operace pull

Samotný skript poskytuje data ve strojově čitelném formátu zvaném recfile, který můžeme dále zpracovat pomocí GNU Recutils nebo Relational pipes. Ukázky výše pocházejí z výstupního filtru relpipe-out-tabular, ale máme i řadu jiných možností, jak si data naformátujeme (např. je můžeme pomocí relpipe-out-ods převést do formátu ODS a otevřít v LibreOffice Calc) nebo je můžeme různě fitrovat a tranformovat, ať už v GNU Guile (Scheme), XQuery, XSLT (např. z nich generovat XHTML stránku, která bude dostupná přes HTTP) nebo pomocí základních nástrojů jako jsou relační varianty grep, cut nebo sed.

Díky tomuto přístupu můžeme se systémem pracovat jako s relační databází a psát podobné dotazy, přestože tam žádná databáze není a data pocházejí z různých zdrojů – některá jsou zakódovaná v adresářové struktuře, některá uložená v jednoduchých textových souborech, některé se dopočítávají za chodu (např. velikost úložiště nebo čas poslední změny). Je to tedy něco jako databázový pohled (view), přes který se díváme na stav našeho systému.

Můžeme si tak snadno přidat např. kontroly, že všechny aktualizace proběhly v pořádku (resultCode == 0), sledovat stav v Zabbixu nebo jiném monitorovacím systému (dají se z toho kreslit i grafy velikostí či doby stahování) nebo si nechat posílat e-maily (to umí i Cron).

Veřejné webové rozhraní

Jedná se o standardní webové rozhraní Mercurialu a cgit. Z nich se dá klonovat nebo si na nich prohlížet zdrojové kódy. Ukázka z mého úložiště:

Další operace

Vše ostatní (např. odstranění některého ze zálohovaných úložišť) se zatím řeší ručním zásahem na serveru. Skript obsahuje funkci allRepositories(), díky které se dá v cyklu iterovat přes všechna úložiště – není tedy problém si tam dopsat libovolnou další operaci, pokud budeme něco potřebovat často a reprodukovatelně.

Závěr

Cílem tentokrát nebylo vytvářet softwarový produkt, ale nakonfigurovat si systém tak, aby mi zálohoval zdrojové kódy projektů, o které bych nerad přišel. Tak snad to pomůže i někomu dalšímu. Čím více lidí bude zálohovat, tím je menší riziko, že se nějaké zajímavé zdrojáky ztratí. (distribuované verzovací systémy naštěstí takové zálohování skvěle podporují) Většinou programuji v Javě, což je o několik úrovní abstrakce výš – a není od věci si občas něco napsat jen s spoužitím základních prostředků, které jsou dostupné v operačním systému. Časem to možná do té Javy (GraalVM?) přepíši a udělám nějaké robustnější řešení, ale první verzi jsem chtěl pojmout spíš jako konfiguraci systému než vývoj nějakého softwaru, proto je to jen shellový skript.

Odkazy a zdroje:

  • VCS Backup – skript pro zálohování zdrojových kódů
  • Mercurial – distribuovaný verzovací systém
  • Git – distribuovaný verzovací systém
  • GNU Recutils – nástroje pro práci s textovými databázemi
  • Relational pipes – datový formát pro relační data + související nástroje
  • cgit – webové rozhraní pro Git

Témata: [verzovací systémy] [Bash]

Komentáře čtenářů


Roman, 28. 4. 2019 16:01 [odpovědět]

Dalsi uzitecne nastroje okolo git: Gitolite, Gogs, GitLab


jiwopene, 29. 4. 2019 18:52, Oddíl na disku nebo virtuální počítač v souboru? [odpovědět]

Zmínil jste, že použijete virtuální počítač. Zajímalo by mne, jestli mu přidělíte oddíl na disku nebo se všechna data ukládají do soubory s obrazem disku (např. qcow2, VDI, …). S VDI (VirtualBox) a VHD (Windows) mám špatnou zkušenost – při poškození „nadřazeného“ souborového systému během používání (asi něco bylo v cachi) se poškodil.

Já osobně bych virtuálnímu stroji dal jeden či více oddílů s LVM, které dostane jako samostatné disky nebo přes NBD, a bootoval bych s jádrem a initrd v souboru (QEMU volba -kernel). To samozřejmě potřebuje trochu víc práce (jádro uložené mimo „disk“), ale asi by to mohlo být méně náchylné k selhání.


Franta, 29. 4. 2019 20:11 [odpovědět]

Na hostitelském počítači mám KVM a disky klasicky v LVM. COW je už uvnitř toho virtuálu (Btrfs) a mít ještě jeden COW pod tím by nebylo optimální. Disky tam mám připojené tak, že jsou uvnitř vidět jako /dev/vdavdb. NBD by šlo taky použít, ale to by mi dávalo smysl spíš, kdyby virtuálky běžely na jiném počítači, než kde jsou disky.

Ta volba -kernel je zajímavá, ale zatím jsem to ještě nikdy nepoužil – jádro mám normálně uvnitř a aktualizuje se zevnitř z distribučních balíčků.

Přidat komentář

reagujete na jiný komentář (zrušit)
jméno nebo přezdívka
název příspěvku
webová stránka, blog
e-mailová adresa
nápověda: možnosti formátování
ochrana proti spamu a špatným trollům

Náhled komentáře