<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Je to divočina &#187; Programování</title>
	<atom:link href="http://blog.urbasek.cz/tag/programovani/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.urbasek.cz</link>
	<description>Práce na volné noze je divočina! Na tomto blogu publikuji zápisky ze svého safari. Ve zbývajícím čase programuji aplikace pro iPhone.</description>
	<lastBuildDate>Fri, 29 Nov 2013 15:44:55 +0000</lastBuildDate>
	<language>cs-CZ</language>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=3.9.40</generator>
	<item>
		<title>Nette, IIS a web.config</title>
		<link>http://blog.urbasek.cz/nette-iis-a-web-config/</link>
		<comments>http://blog.urbasek.cz/nette-iis-a-web-config/#comments</comments>
		<pubDate>Wed, 07 Apr 2010 21:56:31 +0000</pubDate>
		<dc:creator><![CDATA[JIří Urbášek]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[IIS]]></category>
		<category><![CDATA[nette]]></category>
		<category><![CDATA[Programování]]></category>

		<guid isPermaLink="false">http://blog.urbasek.cz/?p=149</guid>
		<description><![CDATA[Nette je výborný PHP framework založený na MVC struktuře obsahující spousty moderních vymožeností atd. atd. O dobrých vlastnostech Nette bych tu mohl psát ještě dlouho. Pokud na localhostu i hostingu používáte apache server podporující mod_rewrite a .htaccess, nebudete mít vůbec žádné problémy se správnou funkčností frameworku včetně routování, které je právě na mod_rewrite závislné. Mně...<br /><a class="more-link" href="http://blog.urbasek.cz/nette-iis-a-web-config/">Continue reading &#187;</a>]]></description>
				<content:encoded><![CDATA[<p>Nette je výborný <a title="Nette PHP Framework" href="http://nettephp.com/">PHP framework</a> založený na MVC struktuře obsahující spousty moderních vymožeností atd. atd. O dobrých vlastnostech Nette bych tu mohl psát ještě dlouho. Pokud na localhostu i hostingu používáte apache server podporující mod_rewrite a .htaccess, nebudete mít vůbec žádné problémy se správnou funkčností frameworku včetně routování, které je právě na mod_rewrite závislné. Mně se však stalo, že jsem musel svůj web hostovat na Microsoft serveru IIS. Ti znalejší ví, že IIS nepodporuje sobory .htaccess a má jiný systém přepisování url. Tak jak tedy rozjet routování v Nette aplikaci běžící na IIS serveru?</p>
<p><span id="more-149"></span></p>
<h2>.htaccess vs web.config</h2>
<p>Struktura základního nette .htaccess je následující:<br />
[sourcecode]# disable directory listing<br />
Options -Indexes</p>
<p># mod_rewrite</p>
<p>RewriteEngine On<br />
#RewriteBase /</p>
<p># front controller<br />
RewriteCond %{REQUEST_FILENAME} !-f<br />
RewriteCond %{REQUEST_FILENAME} !-d<br />
RewriteRule !\.(pdf|js|ico|gif|jpg|png|css|rar|zip|tar\.gz)$ index.php [L]<br />
[/sourcecode]<br />
Abychom rozjeli routování a přepisování na naše velmi cool URLs musíme tento .htaccess soubor portovat na soubor web.config, který používá IIS. Výše zmíněný .htaccess převedený do web.config by měl vypadat následovně:<br />
[sourcecode language="xml"]<br />
<?xml version="1.0" encoding="UTF-8"?><br />
<configuration><br />
<system.webServer><br />
<rewrite><br />
<rules><br />
<rule name="Nette App Rule"><br />
<match url="^\.(pdf|js|ico|gif|jpg|png|css|rar|zip|tar\.gz)$" ignoreCase="false" negate="true" /><br />
<conditions logicalGrouping="MatchAll"><br />
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" pattern="" ignoreCase="false" /><br />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" pattern="" ignoreCase="false" /><br />
</conditions><br />
<action type="Rewrite" url="index.php/{R:1}"/><br />
</rule><br />
</rules><br />
</rewrite><br />
</system.webServer><br />
</configuration><br />
[/sourcecode]<br />
Tento soubor pak uložíme do stejného adresáře, kde se nachází .htaccess, často to bývá adresář <code>document_root</code>.</p>
<h2>Trochu na vysvětlenou</h2>
<p>Jak je jistě vidět, web.config je XML soubor definující všechno možné. Nastavení přepisovaných URL je v sekci <code>&lt;rewrite&gt;</code>. Tato sekce obsahuje sobor pravidel (<code>&lt;rules&gt;</code>), každé jako samostatný tag (<code>&lt;rule&gt;</code>) uvnitř kterého mohou být podmínky (<code>&lt;conditions&gt;</code>), jsou zde specifikovány URL adresy, které vyhovují danému pravidlu (<code>&lt;match&gt;</code>) a také jiné URL adresy, na které se mají vyhovující URL přepsat (<code>&lt;action&gt;</code>).</p>
<p>Samotná dokumentace pro strukturu souboru web.config nejspíš neexistuje, jelikož, jak praví můj kamarád &#8211; windowsový adminisrátor a znalec prostředí .NET &#8211; programátoři by vůbec neměli do web.config ručně zasahovat, takže Microsoft nepovažoval za nutné k tomuto souboru vytvářet dokumentaci. Pokud budete úspěšnější než já a podaří se vám něco o web.config vygooglit, nebojte se o své tipy podělit v komentáři.</p>
<p></p>]]></content:encoded>
			<wfw:commentRss>http://blog.urbasek.cz/nette-iis-a-web-config/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cocoa Objective-C a práce s pamětí</title>
		<link>http://blog.urbasek.cz/cocoa-objective-c-a-prace-s-pameti/</link>
		<comments>http://blog.urbasek.cz/cocoa-objective-c-a-prace-s-pameti/#comments</comments>
		<pubDate>Thu, 01 Apr 2010 11:34:51 +0000</pubDate>
		<dc:creator><![CDATA[JIří Urbášek]]></dc:creator>
				<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Objective-C]]></category>
		<category><![CDATA[Programování]]></category>

		<guid isPermaLink="false">http://blog.urbasek.cz/?p=14</guid>
		<description><![CDATA[Práce s pamětí v objective-c je velmi zásadní (přece jen je to klasické Cčko v novém kabátě). Zvlášť, pokud programujeme pro iPhone, který nepoužívá garbage collector, musíme se o vše postarat sami. Určitě jste se někdy setkali s názvy jako alloc, init, release, dealloc, retain, či autorelease. Z Cčka víme, že pokud nějakou proměnnou vytvoříme...<br /><a class="more-link" href="http://blog.urbasek.cz/cocoa-objective-c-a-prace-s-pameti/">Continue reading &#187;</a>]]></description>
				<content:encoded><![CDATA[<p>Práce s pamětí v objective-c je velmi zásadní (přece jen je to klasické Cčko v novém kabátě). Zvlášť, pokud programujeme pro iPhone, který nepoužívá garbage collector, musíme se o vše postarat sami. Určitě jste se někdy setkali s názvy jako <code>alloc</code>, <code>init</code>, <code>release</code>, <code>dealloc</code>, <code>retain</code>, či <code>autorelease</code>. Z Cčka víme, že pokud nějakou proměnnou vytvoříme pomocí <code>malloc</code>, nesmíme ji zapomenout zase odalokovat pomocí <code>free</code>. Obdobně v C++ je to <code>new</code> a <code>delete</code>. V Objective-C je to podobné, abychom mohli správně uvolnit již nepotřebnou paměť, musíme vědět, kdo je <em>vlastníkem</em> daného objektu.</p>
<p>V tomto článku si povíme kdy a jak správně uvolňovat objekty, které používáme, představíme si objective-c property a vysvětlíme si různé typy, kterými property pracují s pamětí. Na závěr si povíme něco o automatickém uvolňování paměti (nikoliv o garbage collectoru).</p>
<p><code><span id="more-14"></span></code></p>
<h2>Retain Count &#8211; počítáme reference</h2>
<p>Práce s pamětí v objective-c a Cocoa frameworku je založena na počítání referencí (odkazů) na objekty. To znamená, že pokud si vytvoříme nějaký objekt &#8211; jsme jeho vlastníkem &#8211; zvýší se jeho počet referencí (<em>retain count </em>nebo také <em>reference count</em>) o číslo 1. Pokud tento objekt již nechceme používat, naznačíme to tím, že jeho <em>retain count</em> opět snížíme. Jakmile počet referencí objektu dosáhne hodnoty 0, objekt bude automaticky odalokován. Ale pozor! Ne vždy jsme vlastníkem objektu, přestože ho používáme.</p>
<h3>Vlastnictví objektů</h3>
<ul>
<li>Vlastníkem objektu jsme tehdy, pokud ho sami vytvoříme. Objekty se vytváří pomocí metod začínajících na <code>alloc</code>, <code>new</code> nebo metod obsahujících slovo <code>copy</code> (např. <code>alloc</code>, <code>newObject</code>, <code>mutableCopy</code>)</li>
<li>Vlastnictví objektu se dá získat také prostřednictvím metody <code>retain</code>, o které si povíme za chvíli</li>
<li>Pokud jsme vlastníky objektu, jsme zodpovědní za jeho uvolnění (<em>relinquishing ownership</em>) &#8211; typicky pomocí metod <code>release</code>, či <code>autorelease</code></li>
<li>Naproti tomu, pokud objekt nevlastníme, <strong>nesmíme</strong> ho uvolňovat</li>
</ul>
<p>Několik příkladů vytvoření objektů:</p>
<pre lang="objc">NSString *message = [[NSString alloc]
                      initWithString:@"Toto je muj retezec."];
NSString *copiedMessage = [message copy];
copiedMessage = @"Tento retezec je take muj!";

NSLog(message);
NSLog(copiedMessage);

[message release];
[copiedMessage release]</pre>
<p>Doplňme tedy, že při vytvoření objektu se automaticky nastaví retain count na hodnotu 1. Metoda <code>release</code> nedělá nic jiného, než že tuto hodnotu opět sníží (vlastně dělá ještě něco jiného &#8211; vrací <code>self</code>, tzn. objekt, jehož reference count byl snížen).</p>
<h3>Vypůjčené objekty</h3>
<p>Ptáte se nyní, jakéže jsou ty objekty, které používáme ale nevlastníme je?<br />
Jejich vytváření mají na starosti třídní metody (tzv. <em>Convenience Methods</em>). To jsou metody, které většinou na začátku svého jména specifikují datový typ, který vrací v návratové hodnotě. Tedy například u třídy <code>NSString</code> to může být <code>stringWithString:</code>, u třídy <code>NSDate</code> <code>date</code> u <code>NSArray</code> <code>arrayWithObjects:</code> a mnoho dalších. U těchto objektů nejsme vlastníky, třída je pro nás vytvoří a předá nám pouze referenci (odkaz na paměť), kde se tento objekt vyskytuje. Jelikož si ho třída vytvořila sama, tak se také sama postará o jeho správné uvolnění.</p>
<pre lang="objc">NSString *message = [NSString
                     stringWithString:@"Tento retezec nevlastnim ja."];
message = @"Ale ja chci svuj retezec...";

NSString *myOwnMessage = [message retain];
myOwnMessage = @"Jupi, ted mam svuj vlastni retezec";
message = @"A muzu si obsah sveho vlastniho retezce zmenit i v promenne message";

NSLog(message);
NSLog(myOwnMessage);

[myOwnMessage release];
// nikoliv [message release]</pre>
<p>Pro úplnost se ještě podíváme na následující ukázku kódu :</p>
<pre lang="objc">NSString *myString = [[NSString alloc] initWithString: @"tohle je muj retezec"];
NSString *mySecongString = [[NSString
                             stringWithString:@"tenhle je taky muj"] retain];

//naproti tomu
NSString *aString = [NSString stringWithString:@"tenhle retezec ale neni muj"];
NSString *aSecondString = [[[NSString alloc]
                            initWithString: @"a tenhle rovnez neni muj"] autorelease];

[myString release];
[mySecondString release];</pre>
<p>Z posledního ukázkového kódu by mělo být také zřejmé, jaký je význam použitých metod.</p>
<ul>
<li>Metoda <code>retain</code> zvyšuje čítač referencí u daného objektu (pro lepší použitelnost opět vrací <code>self</code>).</li>
<li>Metoda <code>autorelease</code> dělá velmi podobnou věc, jako metoda <code>release</code>, akorát s tím rozdílem, že čítač referencí sníží až někdy později, automaticky.</li>
</ul>
<p>Ddy se teda uvolní objekty, kterým jsme zaslali zprávu <code>autorelease</code>, to se dozvíme až, si budeme povídat o <code>NSAutoreleasePool</code>.</p>
<h2>Objective-C 2.0 Property to vyřeší za nás</h2>
<p>Možná znáte property z jiných programovacích jazyků, jako například z C#, či Javy. Možná netušíte, co to property jsou &#8211; jsou to prostě gettery a settery.</p>
<h3>Nastavení property nikdy nebylo jednodušší</h3>
<p>Objective-C 2.0 nám umožňuje definovat tyto metody, aniž bychom museli mít přímo jejich implementaci ve zdrojovém kódu. Můžeme si zvolit jakým způsobem tyto metody budou zacházet s pamětí privátních proměnných &#8211; jestli zvýší retain count nebo zkopírují celý objekt do nového, či jen přiřadí ukazatel na adresu. A jak na to?</p>
<h3>Retain, copy, assign, nonatomic nebo readonly &#8230;?</h3>
<p>Nejdůležitější <em>nastavení</em> je potřeba učinit při definici property v hlavičkovém souboru &#8211; klíčovým slovem <code>@property. S</code>yntaxe je následující:</p>
<pre lang="objc">@property [(attribute [, attribute2, ...])] type name;</pre>
<p>Pak už jen stačí v souboru s implementací říct kompilátoru slovíčkem <code>@synthesize,</code> ať se o vše postará sám.</p>
<p>Právě význam volitelných atributů je potřeba si pořádně vysvětlit &#8211; určitě jste se už setkali s definicí jako <code>@property (nonatomic, retain) ...</code> ale je nutno zdůraznit že toto není zdaleka jediný a ne vždy ten nejlepší způsob, jak bychom mohli své property definovat.</p>
<h4>Atributy a správa paměti</h4>
<p>Z hlediska správy paměti máme celkem 3 možnosti, jak se můžou vygenerované settery chovat:</p>
<ul>
<li><code>assign</code><br />
<em> obyčejné</em> přiřazení &#8211; tímto atributem říkáme, že do privátní proměnné se má přiřadit adresa objektu, kterým nastavujeme hodnotu (parametr setteru), ale retain count <strong>není</strong> zvýšen. Toto je defaultní typ, který se použije, když nespecifikujeme žádný atribut, a většinou  je toto chování pro nás nežádoucí, ale například property <code>dataSource</code> a <code>delegate</code> pro <code>UITableView</code> právě tento přístup k paměti používají.</li>
<li><code>retain</code><br />
říká, že setter přiřadí adresu objektu ke do privátní proměnné a zároveň zvýší její retain count pomocí metody <code>retain</code>. Díky tomu objekt může s proměnnou pracovat tak dlouho, dokud si ji sám neuvolní. Ale pozor, pracujeme pořád se stejnou adresou, takže pokud objekt, který jsme do proměnné přiřadili, někdy později změní svoji hodnotu, projeví se to i v instanční proměnné. Tento způsob používáme nejčastěji.</li>
<li><code>copy</code><br />
pokud potřebujeme zajistit, aby hodnotu privátní proměnné nebylo možné měnit <em>z vnějšku</em>, specifikujeme právě tento atribut. Který namísto metody <code>retain</code> zavolá na proměnnou metodu <code>copy</code>, čímž zkopíruje obsah přiřazovaného objektu na jiné paměťové místo a tím tak zajistí nezávislost na původním objektu.</li>
</ul>
<p><em>Vygenerované</em> settery mohou vypadat zhruba následovně:</p>
<pre lang="objc">// @property NSString *string;
-(void)setString:(NSString *)newString {
    if (string != newString) {
        string = newString;
    }
} 

// @property (retain) NSString *string;
-(void)setString:(NSString *)newString {
    if (string != newString) {
        [string release];
        string = [newString retain];
    }
} 

// @property (copy) NSString *string;
-(void)setString:(NSString *)newString {
    if (string != newString) {
        [string release];
        string = [newString copy];
    }
}</pre>
<p>Pokud od getterů, či setterů vyžadujeme, musíme si je už definovat sami.</p>
<p>Property umožňují definovat více atributů, než jen výše uvedené. Například <code>nonatomic</code>, či <code>readonly</code>. Ale jelikož tyto se přimo netýkají správy paměti, nebudu se o nich zde zmiňovat.</p>
<h2>Automatické uvolnění paměti</h2>
<p>Položili jste si někdy otázku jaký je rozdíl mezi <code>release</code> a <code>autorelease</code>? Cože tam má jedna metoda automatického a druhá ne? Odpovědí je <code>NSAutoreleasePool</code>.</p>
<h3>Hromádka odložených objektů</h3>
<p>Autorelease pool je vlastně jakýsi manažer paměti, který se stará právě o ty objekty, kterým zašleme <code>autorelease</code> namísto <code>release</code>. Všechny takovéto objeky se umístí do tohoto uložitě a fyzicky se uvolní až tehdy, když je uvolněn samotný objekt <code>NSAutoreleasePool</code>u. Všimli jste si, že v aplikaci používate <code>autorelease</code> ale přitom jste nikde instanci třídy <code>NSAutoreleasePool</code> nevytvářeli? Tak se podívejte do souboru <code>main.m</code> kteréhokoliv XCode projektu iPhonové aplikace. Autorelease poolů se ale vytváří bez našeho vědomí více. Application Kit automaticky vytváří pooly při začátku cyklu událostí (<em>event cycle</em>, či <em>event-loop</em>). Zde se zachytávají například události generované při kliknutí na prvek GUI a ostatní vnitřní záležitosti dějící se v aplikaci. Na konci tohoto <em>event-loop</em>u je pool zase automaticky uvolněn.</p>
<h3>Můžu si vytvořit své vlastní <em>samouvolňovací jezírko</em>?</h3>
<p>Samozřejmě, že ano. A v některých situacích je to dokonce velmi vhodné, až nezbytné. Při vývoji iPhonových aplikací je to typicky, když:</p>
<ol>
<li>používáme svá vlastní vlákna.<br />
Každé vlákno <strong>musí</strong> obsahovat autorelease pool. Nejčastěji si programátor vytvoří tento pool na začátku metody běžící ve vláknu a na konci metody pool zase uvolní. A pokud byste na to náhodou zapomněli nezoufejte, konzole vás na to upozorní hromadou krásných varování končících nějak podobně jako &#8222;object is just leaking&#8220;.</li>
<li>pokud v kódu máme cyklus vytvářející hodně pomocných objektů.<br />
Pokud máme cyklus a v každé iteraci potřebujeme vytvořit hodně pomocných objektů, může se hodit ušetřit paměť pomocí vytvoření autorelease poolu na začátku iterace cyklu a na konci iterace ho zase uvolnit. Docílíme tak uvolnění paměti hned jak ji skutečně nepotřebujeme, nikoliv akumulování a čekání až skončí event-loop případně jiný pool. Úplně ideální je uvolnit pool ne při každém průchodu, ale třeba jen v každé sté iteraci. To lze vyřešít jednoduchou <code>if</code> podmínkou.</li>
</ol>
<p>Při vytváření vlastních poolů platí pravidlo, že pool se uvolňuje ve stejné oblasti viditelnosti (<em>scope</em>) jako byl vytvořen, tedy vytvoříme-li ho na začátku metody, na konci ho uvolňíme, vytvoříme-li ho uvnitř cyklu, před koncem cyklu uvolníme atp.</p>
<h2>Doporučuji k přečtení</h2>
<p>Ačkoliv tento článek je docela obsáhlý, poskytuje jen tu nejnutnější množinu potřebných znalostí. Pokud chcete umět opravdu dobře zacházet s pamětí v Cocoa objective-c, doporučuji prostudovat si následující zdroje.</p>
<ul>
<li><a href="http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/ObjectiveC/Introduction/introObjectiveC.html">The Objective-C 2.0 Programming Language</a></li>
<li><a href="http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/MemoryMgmt/MemoryMgmt.html">Memory Management Programming Guide for Cocoa</a></li>
</ul>
<p></p>]]></content:encoded>
			<wfw:commentRss>http://blog.urbasek.cz/cocoa-objective-c-a-prace-s-pameti/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Automatické zálohování dat na Mac OS X</title>
		<link>http://blog.urbasek.cz/automaticke-zalohovani-dat-na-mac-os-x/</link>
		<comments>http://blog.urbasek.cz/automaticke-zalohovani-dat-na-mac-os-x/#comments</comments>
		<pubDate>Sun, 28 Mar 2010 17:25:34 +0000</pubDate>
		<dc:creator><![CDATA[JIří Urbášek]]></dc:creator>
				<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[Bash]]></category>
		<category><![CDATA[Programování]]></category>

		<guid isPermaLink="false">http://blog.urbasek.cz/?p=80</guid>
		<description><![CDATA[Zálohování dat je bezesporu velmi důležitá věc. Většina lidí pracujích hodně s počítačem, se dostane jednou do chvíle, že pro ně začnou být jejich data cenná a začnou přemýšlet o jejich zálohování. Nejlépe pravidelném. I já mezi ně patřím a jelikož jsem člověk docela líný, rozhodl jsem si tuto činnost co nejvíce usnadnit &#8211; napsal...<br /><a class="more-link" href="http://blog.urbasek.cz/automaticke-zalohovani-dat-na-mac-os-x/">Continue reading &#187;</a>]]></description>
				<content:encoded><![CDATA[<p>Zálohování dat je bezesporu velmi důležitá věc. Většina lidí pracujích hodně s počítačem, se dostane jednou do chvíle, že pro ně začnou být jejich data cenná a začnou přemýšlet o jejich zálohování. Nejlépe pravidelném. I já mezi ně patřím a jelikož jsem člověk docela líný, rozhodl jsem si tuto činnost co nejvíce usnadnit &#8211; napsal jsem si skritpt v bashi, který potřebnou rutinu vykoná za mě.<br />
<span id="more-80"></span></p>
<h2>Co je to Bash?</h2>
<p>Jsem uživatelem operačního systému Mac OS X a tudíž můžu s výhodou použít mocného nástroje zvaného Bash. K tomuto nástroji se dostaneme spuštěním aplikace Terminál. Vyskočí na vás sice jen černé nic neříkající okno, ale nenechte se odradit, v tuto chvíli se opravdu stáváte pánem (paní) svého počítače. Terminál totiž dokáže poslouchat příkazy, které mu zadáte, a podle nich udělat snad vše, na co si vzpomenete &#8211; a ještě mnohem víc. Stačí tedy jen vědět, co mu chcete přikázat.</p>
<h2>Zálohování souborů pomocí terminálu</h2>
<p>Jakožto bývalý uživatel Linuxu jsem stále ještě docela zběhlý v používání příkazové řádky (terminálu) a používám ji velmi rád. Je prostě rychlejší a mocnější.</p>
<p>Obvykle jsem zálohoval svá data vždy jednou za čas, když se mi prostě chtělo. Většinou jsem to dělal posloupností několika příkazů. Dejme tomu, že jsem si chtěl zálohovat složku se svými dokumenty do školy.</p>
<pre lang="bash">tar czf `date +"%Y-%d-%m"`.School.tar.gz School
mv [[datum]].School.tar.gz ~/Backup/</pre>
<p>A poté jsem si chtěl zálohovat další složku, například veškerou svoji práci.</p>
<pre lang="bash">tar czf `date +"%Y-%d-%m"`.School.tar.gz School
mv [[datum]].School.tar.gz ~/Backup/</pre>
<h3>Jde to i jednodušeji &#8211; skriptováním</h3>
<p>Skriptování zní jako něco velmi složitého, určeného pouze těm divným lidem, kteří rozumí jedničkám a nulám. Ale ve skutečnosti to vůbec složité není. Skript v Bashi je jen posloupnost příkazů &#8211; nemusíte je psát každý zvlášť, ale zapíšete si je všechny do jednoho souboru a ten si poté spustíte. Jak jednoduché&#8230;</p>
<h2>Konečně řešení</h2>
<p>Takže jsem nelenil, využil chvilky volnějšího času a pustil se do skriptování. Mým cílem bylo vytvořit skript, kterému pouze předám soubory, které chci zálohovat, a on se již o vše ostatní postará. Pojmenoval jsem si ho <code>backup.sh</code>.</p>
<pre lang="bash">#!/bin/bash

backupStorage=/Users/jirka/Backup/

# print usage info
usage() {
    echo -e "`basename $0` usage:"
    echo -e "`basename $0` backup_file [ backup_file, ... ]"
    echo -e "`basename $0` default backup storage is '$backupStorage'"
}

# do backup by creating tar.gz file and place it into desired folder
# arg1: path to file to backup
# arg2: path where to place backuped file
backup() {
    if [ $# -lt 2 ] &amp;&amp; ([ ! -f $1 ] || [ ! -d $i ]) || [ ! -d $2 ]; then
        echo -e "$@"
        usage $@
        exit 4
    fi
    date=`date +"%Y-%m-%d"`
    fileName=`basename $1`.tar.gz

    echo $fileName
    tar czf /tmp/$fileName $1

    if [ ! -d $2$date ]; then
        mkdir $2$date
    fi

    mv /tmp/$fileName $2$date
}

# run the script
if [ ! -d $backupStorage ]; then
    echo -e "`basename $0`: backuping storage '$backupStorage' does not exist"
    exit 2
fi

if [ $# -lt 1 ]; then
    usage $@
    exit 2
fi

for i in $@; do
    if [ -f $i ] || [ -d $i ]; then
        backup $i $backupStorage
    else
        echo -e "`basename $0`: file '$i' does not exist"
    fi
done</pre>
<p>Nyní si můžu jednoduše zálohovat své soubory jediným příkazem. Nesmím však zapomenout přidat soubor práva na spouštění.</p>
<pre lang="bash">chmod u+x backup.sh
./backup.sh School Work Photos Documents/ImportantFile.txt</pre>
<p>Ve skriptu je pro uložení mých zálohovaných soborů nadefinována složka <code>Backup</code> v mém domovském adresáři. Po úspěšném ukončení skriptu se v ní vytvoří podsložka pojmenovaná podle aktuálního data a v ní všechny zálohované soubory zabalené do archivu <code>tar.gz</code>.</p>
<h2>Zálohování skutečně automaticky</h2>
<p>Ti bystřejší pochopili, že tohle stále ještě není automatické zálohovaní. Pořád tu musí být někdo, kdo celý skript spustí. Ale i tento problém se dá snadno vyřešit. Mac OS X nám totiž nabízí automatické spouštění skriptů a to v podstatě kdykoliv si usmyslíte &#8211; buďto jen určitý den v měsíci v určitou hodinu nebo třeba v pravidelných intervalech. Řekněme, že budeme chtít spouštět náš zálohovací skript každý týden. K tomuto účelu nám slouží složka <code>/etc/periodic/weekly</code> (v linuxu známá jako <code>/etc/cron.weekly</code>) Zde se umisťují skripty, které chceme, aby se automaticky spustily každý týden. Bohužel takovýto automatický skript neumí přijmout žádné parametry, takže je potřeba ještě malé úpravy &#8211; vytvoření dalšího skriptíku.</p>
<p>Chci si každý týden zálohovat své pracovní dokumenty, fotky a školu. Svůj skript jsem si umístil v domovském adresáři ve složce <code>bin</code>.</p>
<pre lang="bash">#!/bin/bash
/Users/jirka/bin/backup.sh /Users/jirka/School /Users/jirka/Work /Users/jirka/Photos
chown -R jirka:jirka /Users/jirka/Backup/`date +"%Y-%m-%d"`</pre>
<p>Tento kód si uložíme do souboru a soubor umístíme do výše zmíněné složky (opět je nutné přidělit práva na spouštění pomocí příkazu <code>chmod</code>). Tohe už jsem ale netestoval, takže nemohu zaručit dokonalou funkčnost. Já si své zálohy budu spouštět kdy chci sám a hlavně si vyberu pokaždé různé soubory, které chci zálohovat.</p>
<h2>Závěrem</h2>
<p>Skript není dokonalý. Obsahuje pár nedostatků. Konkrétně, jméno zálohovaného souboru se zjišťuje podle posledního <em>názvu</em> v dané cestě k souboru. Například <code>/Users/jirka/documents/soubor.txt</code> bude zálohován jako <code>soubor.txt.tar.gz</code>. To tedy znamená, že pokud skriptu předáme dva různé soubory, které ale končí stejně, např. <code>School/predmet1/prednaska.pdf</code> a <code>School/predmet2/prednaska.pdf</code>, bude zálohován pouze jeden z nich &#8211; ten poslední.<br />
Druhá nevýhoda je, že skript nefunguje správně pro soubory obsahující ve svém názvu mezery (na tohle už mé skriptovací schopnosti zřejmě nestačí).</p>
<p>Také je nutné upozornit, že zálohovaná data samozřejmě musí být jinde, než na počítači, který je zálohován. Takže na úplný závěr je potřeba si všechny soubory z zálohovacího uložiště skopírovat na flash disk, vypálit na CD, nebo jako <code>backupStorage</code> ve skriptu nadefinovat cestu k připojenému externímu disku. Externí disky na Mac OS X jsou vždy připojeny do složky <code>/Volumes</code>.</p>
<p></p>]]></content:encoded>
			<wfw:commentRss>http://blog.urbasek.cz/automaticke-zalohovani-dat-na-mac-os-x/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
