Autor Zpráva
Tomášeek
Profil *
Ahoj,

nevím, jestli to dát sem, nebo do Webových serverů, kdyžtak prosím o přesun.

Mám na serveru v CRONu zálohovací script, který mi z vybraných složek vrací jeden velký tar.gz soubor. Běžně mívá cca 7GB, dnes v noci se vytvořil pouze 2GB soubor, tak jsem začal pátrat po příčině. Když spustím script ručně, /path/backup.sh, do konzole se mi vypíše několik chyb typu "No such file or directory", typicky, když je v adresáři/filename mezera. Tyto chyby mě netrápí, nemohu je opravit, data jsou nahrána jednotlivými uživateli. Tyto chyby byly vždy, i v době, kdy script tvořil 7GB zálohy. Možná by se ale do toho scriptu dala přidat nějaká podmíka, aby toto nevypisoval? I když, nevidím to, běží to cronem, jen mě to napadlo.

Nyní mi to ale po několika chybách tohoto typu hlásí tar: Exiting with failure status due to previous errors. S tím si neumím poradit. Podíval jsem se, kde ten 2GB soubor končí, ale weby, které se začaly stahovat, se stáhly kompletní, jen se nezačaly stahovat/zálohovat další.

Konkrétní znění backup scriptu zní - zálohovat vše kromě "c1" - přiznávám, že mu moc nerozumím, ale kdysi jsem ho s někým dal dokupy a fungoval až dosud na jedničku:

#!/bin/bash

DATE=`date +%Y%m%d`

tar czfP /var/www/backup/$DATE.tar.gz `find /var/www/cs -type d | grep -E '/var/www/cs/c[0-9]+/web[0-9]+/web' | grep -v 'c1'`

Na www.cs.duke.edu/csl/docs/unix_course/intro-69.html jsem našel, že logovat by se mělo dát pomocí 2>file, ale když jsem toto přidal na konec scriptu a spustil, vůbec se mi nezačal tvořit výsledný tar.gz soubor.

tar czfP /var/www/backup/$DATE.tar.gz `find /var/www/cs -type d | grep -E '/var/www/cs/c[0-9]+/web[0-9]+/web' | grep -v 'c1'` 2>file.log

Poradí někdo zkušenější tápajícímu začátečníkovi?

Děkuji za rady.


Edit: případně alespoň možnost nějakého echa do konzole - pokud se backup nepovede, poznám to na velikosti a nemám problém spustit script ručně a podívat se, kde skončil. Teď se ale nemám absolutně od čeho odrazit :-(
mckay
Profil
Tomášeek:
2> Vám přesměrovává stderr pro daný příkaz. Ve vašem případě grep -v 'c1'.

Chcete-li logovat chyby od tar příkazu, napasujte přesměrování přímo za něj, nějak takto:

tar cvzfP /var/www/backup/$DATE.tar.gz 2>file.log `find /var/www/cs -type d   | grep -E '/var/www/cs/c[0-9]+/web[0-9]+/web' | grep -v 'c1'`

Nemám teď k dispozici terminál, abych ověřil, že to funguje, ale mělo by.
Tomášeek
Profil *
mckay:
Vyzkouším, děkuji za odpověď.

Jen se ještě zeptám, jestli jsem dobře pochopil z načtených zdrojů, 2> znamená chybu, 1> vše (nebo pouze success, to teď není podstatné), že? file.log je mnou vytvořený file, kam mi spadnou všechny chyby typu "No such file or directory", "Exiting with failure status due to previous errors". Cesta k souboru, kde chyba nastala, tam předpokládám bude, že?
Keeehi
Profil
mckay:
Takto loguješ chyby programu find. Má tam subshell.

Tomášeek:
2> znamená chybu, 1> vše (nebo pouze success, to teď není podstatné), že?
To co se ti vypisuje do terminálu jsou vlastně 2 proudy textu, které se spojují do jednoho, který se vypisuje. Je úplně v kompetenci programu (tar) do kterého proudu bude vypisovat které informace. Standardně do proudu 1 posílá informace když je vše v pořádku, do proudu 2 když je problém. Aby jsi dostal v souboru stejný výpis, jako máš v konzoli, přesměruje se jeden proud do duhého a ukládá se pak jeden 2>&1 1>/cesta/kam/chces/ulozit/soubor.log

2>file.log vytvoří soubor file.log v aktuálním umístění. Kde to, když se příkaz spouští přes cron nevím, ale tipoval bych že to bude v /root/file.log
mckay
Profil
Keeehi:
Whoops, pardon, nevšiml jsem si. Upravil jsem původní odpověď, díky.
Tomášeek
Profil *
Keeehi:
mckayův postup jsem vyzkoušel, error.log prázdný, v konzoli chyba jako minule.

Soubor budu adresovat absolutně, takže na defaultním umístění tolik nezáleží.

Správně dle tebe by to tedy mělo být takto?
#!/bin/bash
 
DATE=`date +%Y%m%d`
 
tar czfP /var/www/backup/$DATE.tar.gz `find /var/www/cs -type d 2>&1 1>/var/www/backup/error.log | grep -E '/var/www/cs/c[0-9]+/web[0-9]+/web' | grep -v 'c1'`

Vzhledem k tomu, že vytvořit ten tar.gz soubor o velikosti 2GB (než dojde k chybě), chvíli trvá, přiznám se, že jsem z toho úplně vyěťavený už a bojím se dalších pokusných spuštění :-)
mckay
Profil
Tomášeek
Omlouvám se, zmátl jsem Vás špatnou pozicí přesměrování výstupu. Odpověď jsem nyní znovu upravil.

Kromě změny místa přesměrování chybového výstupu jsem přidal přepínač -v, který chyby produkované tar příkazem snad bude zobrazovat. Pravděpodobně by jen přidání tohoto přepínače do Vašeho původního skriptu mohlo problém vyřešit (přičemž je tedy třeba zohledit to, zda přepínač -v opravdu generuje chybový (2>) a ne jen klasický (1>) výstup).
Keeehi
Profil
Zkusil bych to takto:
tar czfP /var/www/backup/$DATE.tar.gz $(find /var/www/cs/ -maxdepth 3 -type d | grep -E "/var/www/cs/c[02-9][0-9]*/web[0-9]+/web")) 2>&1 1>/var/www/backup/error.log
Tou změnou parametrů pro find a grep jsem snad vyřešil ty mezery v jménech souborů.

Navíc původní | grep -v 'c1'` není úplně vhodné a spolehlivé. Když uživatel bude mít někde hluboko vytvořenou složku se jménem kde i někde uprostřed je c1, tak mu ji to vyřadí.
Tomášeek
Profil *
Keeehi:
Uf... a já si myslel, že to bude brnkačka :-)

Mezitím, než jsi napsal (i mckay podruhé), jsem ten script zkusil spustit, do logu se mi zapisovalo, ale viděl jsem totéž, co v konzoli,

... # nekolik No such file or directory errors
tar: /var/www/cs/c2/web10/web/upload/images/testové: Cannot stat: No such file or directory
tar: otázky: Cannot stat: No such file or directory #jasně, testové otázky je neplatný dirname, nejde do backupu, ale nevadí
tar: Exiting with failure status due to previous errors #tady jsem očekával uvedení, v jakém souboru chyba nastala (a proč)

Pokud zkusím kód uvedený v [#8], jen se zeptám. Co konkrétně v tomto případě omezuje maxdepth 3? zanoření souborů je vyšší.
Další změna pak je v tom "c+číslo", kde [02-9][0-9], přes to ale neprojde třeba "11", ne? Potřebuju vynechat pouze jedničku, nic jiného (nebo je to ekvivalent tomu mému a že by se mi už teď backupovala jen část záznamů a 10-19 jsem vynechával)?

mckay pak zmínil přidat ještě v, když už budu v úpravách, přidat, nebo nepřidat? Nevím, nakolik jsem tvoje a mckayovy změny konzistentní a jak moc jdou kombinovat.


Ještě doplním, že těch "neexistujících" adresářů, které obsahují mezeru, se předtím vypsalo více, Exit ale nastal z nějakého důvodu až u tohoto. Pokud jméno adresáře opravím na testove-otazky, skončí běh scriptu hned u dalšího adresáře s mezerou v názvu. Proč ale zde u Xtého a ne u prvního, to je mi záhadou :-/
mckay
Profil
Tomášeek:
Přidání přepínače k příkazu tar je konzistentní se změnami, které doporučuje Keeehi. Jde jen o to, jak moc bude vykonávání toho příkazu "ukecané".
Keeehi
Profil
Tomášeek:
Co konkrétně v tomto případě omezuje maxdepth 3? zanoření souborů je vyšší.
Další změna pak je v tom "c+číslo", kde [02-9][0-9], přes to ale neprojde třeba "11", ne? Potřebuju vynechat pouze jedničku, nic jiné
find jde rekurzivně tak hluboko, kam až se jen dostane a jeho výpis pak vypadá nějak takto
/var/www/cs/c2564/web68489/web
/var/www/cs/c2564/web68489/web/xxx
/var/www/cs/c2564/web68489/web/xxx/111
/var/www/cs/c2564/web68489/web/xxx/111/000
/var/www/cs/c2564/web68489/web/xxx/222
/var/www/cs/c2564/web68489/web/xxx/333
/var/www/cs/c2564/web68489/web/xxx/333/000
/var/www/cs/c2564/web68489/web/xxx/333/000/999
/var/www/cs/c2564/web99999/web
/var/www/cs/c2564/web99999/web/abcdefgh
....
Ten limit to omezí, že se to zasekne jen u složky web. Tudíž předchozí výpis se zkrátí na
/var/www/cs/c2564/web68489/web
/var/www/cs/c2564/web99999/web
....
To dodatečné rekurzivní zanoření do podsložek už si zajistí tar sám. Tímto se právě vyřešily ty mezery ve vnořených adresářích*

Další změna pak je v tom "c+číslo", kde [02-9][0-9], přes to ale neprojde třeba "11", ne?
Ano, c11 přes to neprojde. Ale to ani v přdchozím případě, protože jsi ho pomocí grep -v 'c1' odstranil.Myslel jsem tedy, že jednička nesmí být na začátku nikdy a ne že jen c1 a to je vše. Pokud chceš odviltrovat jen a pouze ten jeden adresář c1, pak regex by mohl vypadat /var/www/cs/(c[02-9]|c[0-9]{2,})/web[0-9]+/web. Počítá i s tím, že na začátku, mohou být nuly. Např. c00123.

* Přemýšlel jsi, co by se stalo, pokud by někdo měl takovouto cestu adresářů /var/www/cs/c2564/web68489/web/xxx/111 /etc/passwd? Mezera v názvu adresáře, pokud to nemáš ošetřené může být velmi nebezpečná.
Tomášeek
Profil *
mckay:
O ukecanost nejde, pouští se to CRONem a log potřebuji jen pro případ, kdy uvidím, že se něco nepovedlo (podle velikosti dat, ta je +- MB konzistentní).

Zkusím tedy ještě Keeehiho postup doplněn o tebou navržený přepínač...

Keeehi:
Hm, tak jsem to měl špatně i teď. Adresáře "Cx" jsou číslované od 1 postupně nahoru, přičemž vynechat potřebuju jen jedničku. To jsem měl tedy špatně :-/ Zkusím tedy (c[02-9]|c[0-9]{2,}).

Jinak co se adresářů týče, tak ten tebou uvedený nikdo nevytvoří, mezera povolená je, ale lomítko nikoliv. Zkusím prokonzultovat i tu mezeru, jestli bychom je nezakázali (nebo nenahradili za "-"), ale to půjde u nových adresářů, nikoliv zpětně. děkuji ale za zpětnou vazbu, nad tímto jsem třeba osobně nepřemýšlel, neb jsem o tom nevěděl...
Keeehi
Profil
Tomášeek:
mezera povolená je, ale lomítko nikoliv.
Lomítko není v názvu souboru. Vytvoří adresář 111 , přejde do něj a v něm vytvoří další adresář etc, přejde do něj a tam vytvoří adresář passwd.
Program find pak vytvoří ve výpisu toto ....../111 /etc/passwd
TomášK
Profil
Je lepší mezery ve vstupu ošetřit než pohlídat, aby žádné nebyly. tar umožňuje načítat názvy souborů oddělené nulovým bytem.

Tento příkaz funguje pro adresáře s mezerami, ale nepovoluje zalomení řádku.
Zneužít se dá podobně jako s těmi mezerami.

find /var/www/cs -type d | \
       grep -E '/var/www/cs/c[0-9]+/web[0-9]+/web' | \
       grep -v 'c1'` | \
       tr "\n" "\0" | \
       tar -czvf /var/www/backup/$DATE.tar.gz --null -T -

Pokud by byl problém s tím, že uživatel může do zálohy dostat jakýkoliv
adresář, bude potřeba přepsat podmínky do find a pak použít:
find /var/www/cs -type d -print0 | \
       tar -czvf /var/www/backup/$DATE.tar.gz --null -T -

Jak fungují ty regexpy jsem nekoukal, jen je opsal.

Vaše odpověď


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: