joe di castrohttp://joedicastro.comWed, 13 Jul 2011 20:21:00 +0200Fabric & Rsync para realizar Backupshttp://joedicastro.com/fabric-rsync-para-realizar-backups.html<p>En el <a href="http://joedicastro.com/sincronizar-dos-directorios-con-fabric-y-rsync.html">anterior articulo</a> empleaba <a href="http://fabfile.org/">fabric</a> y <a href="http://es.wikipedia.org/wiki/Rsync">rsync</a> para sincronizar un directorio local y uno remoto en ambas direcciones. Además le añadía las funcionalidades de <a href="http://joedicastro.com/logger-informes-legibles-para-tus-scripts-python.html">logger</a> y <a href="http://joedicastro.com/notificaciones-de-escritorio-en-ubuntu-desde-python.html">notify</a> para proporcionar información sobre el proceso durante y después de su ejecución. Y comenzaba el articulo recordando a <a href="http://joedicastro.com/sincronizar-una-carpeta-local-y-una-remota-a-traves-de-ftp-lftp-mirror.html">lftp-mirror</a>, el script que había creado para realizar la sincronización a través de FTP. Pero <strong>lftp-mirror</strong> realiza algo más que la sincronización, pues también permite realizar el archivado del directorio local en ficheros comprimidos y lanzar varias tareas en una sola ejecución.</p> <p>Ahora he añadido esta funcionalidad al fichero <strong>fabric</strong> creado anteriormente. Así empleando este fichero podemos realizar el Backup periódico de varios servidores en una sola operación y de forma completamente automática (basta con programar su ejecución). Se sincronizan los dos directorios y se crea un archivo comprimido del directorio local por cada día de la semana. De este modo siempre tenemos una copia del estado del directorio remoto de los últimos siete días. Y al final del proceso en nuestro correo, un email con el informe del resultado por cada una de las tareas ejecutadas.</p> <p>En este fichero, <strong>rsync_fabric.py</strong>, disponemos de tres posibles tareas:</p> <div class="codehilite"><pre><span class="gp">$</span> fab -l <span class="go"> A Fabric file for sync two directories (remote ⇄ local) with rsync.</span> <span class="go">Available commands:</span> <span class="go"> backup Sync from remote to local &amp; archive the local directory.</span> <span class="go"> down Sync from remote to local.</span> <span class="go"> up Sync from local to remote.</span> </pre></div> <p>Con la primera realizamos el backup (sincronización + archivado) y con las siguientes solo la sincronización desde o hacia el servidor. Una de las ventajas de fabric es que nos permite concatenar tareas fácilmente desde la línea de comandos, así podemos lanzar varias sincronizaciones de forma simultanea. Para poder realizar esto, creo una configuración de sincronización por defecto y después creo una función para cada una las tareas adicionales que simplemente redefinen los valores de estas variables globales. Por ejemplo:</p> <div class="codehilite"><pre><span class="c"># Variables globales de sincronización predefenidas</span> <span class="n">env</span><span class="o">.</span><span class="n">host_string</span> <span class="o">=</span> <span class="s">&quot;username@example.com&quot;</span> <span class="n">env</span><span class="o">.</span><span class="n">remote</span> <span class="o">=</span> <span class="s">&quot;/my_directory&quot;</span> <span class="n">env</span><span class="o">.</span><span class="n">local</span> <span class="o">=</span> <span class="s">&quot;/home/my_user/backups/my_directory&quot;</span> <span class="c"># Redefinimos estas variables para otra configuración de sincronización. Por </span> <span class="c"># supuesto, pueden tratarse de servidores distintos.</span> <span class="k">def</span> <span class="nf">_databases</span><span class="p">():</span> <span class="k">global</span> <span class="n">env</span> <span class="n">env</span><span class="o">.</span><span class="n">host_string</span> <span class="o">=</span> <span class="s">&quot;username@example.com&quot;</span> <span class="n">env</span><span class="o">.</span><span class="n">remote</span> <span class="o">=</span> <span class="s">&quot;/databases&quot;</span> <span class="n">env</span><span class="o">.</span><span class="n">local</span> <span class="o">=</span> <span class="s">&quot;/home/my_user/backups/databases&quot;</span> </pre></div> <p>Veamos ejemplos de como podemos utilizar estas tareas:</p> <div class="codehilite"><pre><span class="gp">#</span> <span class="s2">&quot;Si queremos sincronizar el contenido local hacia el remoto, por ejemplo </span> <span class="gp">#</span><span class="s2"> para subir los ficheros al servidor por primera vez. Empleando los valores </span> <span class="gp">#</span><span class="s2"> por defecto. El modificador -w lo empleo para que no se detenga en los </span> <span class="gp">#</span><span class="s2"> errores, que de ocurrir, los veremos luego en el informe final.&quot;</span> <span class="gp">$</span> fab -w up <span class="go">[localhost] local: rsync -pthrvz --delete /home/my_user/backups/my_directory/ </span> <span class="go"> username@example.com:my_directory</span> <span class="go">Done.</span> <span class="gp">#</span> <span class="s2">&quot;Pero también podemos especificar una tarea distinta a la por defecto de </span> <span class="gp">#</span><span class="s2"> este modo. Sincronizando desde el servidor a nuestro directorio local las </span> <span class="gp">#</span><span class="s2"> bases de datos.&quot;</span> <span class="gp">$</span> fab -w down:databases <span class="go">[localhost] local: rsync -pthrvz --delete username@example.com:databases/ </span> <span class="go">/home/my_user/backups/databases</span> <span class="go">Done.</span> <span class="gp">#</span> <span class="s2">&quot;Y por supuesto, podemos realizar varias tareas a la vez.&quot;</span> <span class="gp">$</span> fab -w down backup:databases <span class="go">[localhost] local: rsync -pthrvz --delete username@example.com:my_directory/ </span> <span class="go">/home/my_user/backups/my_directory</span> <span class="go">[localhost] local: rsync -pthrvz --delete username@example.com:databases/ </span> <span class="go">/home/my_user/backups/databases</span> <span class="go">Done.</span> </pre></div> <p>No empleo contraseña alguna, ni en el fichero ni en la línea de comandos, podría hacerse perfectamente, pero prefiero emplear una clave <a href="http://es.wikipedia.org/wiki/RSA">RSA</a> <a href="http://es.wikipedia.org/wiki/Criptograf%C3%ADa_asim%C3%A9trica">pública</a> autorizada para las sesiones SSH en el servidor. Es bastante más seguro y cómodo. En los ejemplos no se ve la salida de <em>rsync</em>, pues es capturada (así como los erores) para ser mostrada a posteriori en los informes. </p> <p>Un ejemplo de informe sería el siguiente:</p> <div class="codehilite"><pre>START TIME ===================================================================== miércoles 13/07/11, 19:48:55 ================================================================================ SCRIPT ========================================================================= fab (ver. Unknown) Fabric Rsync http://joedicastro.com Syncing username@example.com:databases to /home/my_user/backups/databases ================================================================================ RSYNC OUTPUT ___________________________________________________________________ receiving file list ... done sent 20 bytes received 825 bytes 153.64 bytes/sec total size is 827.76M speedup is 979595.42 ROTATE COMPRESSED COPIES _______________________________________________________ Created file: /home/my_user/backups/databases_13jul2011_19:49_mié.tar.gz Deleted old file: databases_13jul2011_19:37_mié.tar.gz DISK SPACE USED ================================================================ 1.60 GiB ================================================================================ END TIME ======================================================================= miércoles 13/07/11, 19:50:02 ================================================================================ </pre></div> <p>Que como podemos ver, ha tardado poco más de un minuto en sincronizar 827.56 Megabytes y el total de espacio ocupado por el directorio y los siete archivos comprimidos es de 1.60 Gibibytes (1,72 Gigabytes). </p> <h2 id="ventajas">Ventajas</h2> <p>Las ventajas de sincronizarlo con <strong>rsync + ssh</strong> vs <strong>ftp</strong>, como ya comenté en el anterior articulo son enormes. Se ahorra muchísimo tiempo y ancho de banda, lo que ayuda a no saturar la red y no tener que planificar con tanto cuidado las ventanas de backup. Por ejemplo he realizado unas pruebas y para las mismas condiciones: <strong>mismo servidor, mismo directorio, mismo horario y condiciones de red; la sincronización remoto → local a través de FTP emplea entre 35 y 45 minutos y cuando lo hacemos a través de rsync emplea entre 2 y 4 minutos</strong>. Ahí es nada, estamos hablando de un proceso ~13 veces más rápido. </p> <h2 id="c+digo">Código</h2> <p>El código del fichero fabric es el siguiente:</p> <div class="codehilite"><pre><span class="c">#!/usr/bin/env python</span> <span class="c"># -*- coding: utf8 -*-</span> <span class="kn">import</span> <span class="nn">os</span> <span class="kn">import</span> <span class="nn">glob</span> <span class="kn">import</span> <span class="nn">tarfile</span> <span class="kn">import</span> <span class="nn">time</span> <span class="kn">from</span> <span class="nn">get_size</span> <span class="kn">import</span> <span class="n">get_size</span> <span class="k">as</span> <span class="n">_get_size</span> <span class="kn">from</span> <span class="nn">get_size</span> <span class="kn">import</span> <span class="n">best_unit_size</span> <span class="k">as</span> <span class="n">_best_unit_size</span> <span class="kn">from</span> <span class="nn">logger</span> <span class="kn">import</span> <span class="n">Logger</span> <span class="k">as</span> <span class="n">_logger</span> <span class="kn">from</span> <span class="nn">notify</span> <span class="kn">import</span> <span class="n">notify</span> <span class="k">as</span> <span class="n">_notify</span> <span class="kn">from</span> <span class="nn">fabric.api</span> <span class="kn">import</span> <span class="n">env</span><span class="p">,</span> <span class="n">local</span> <span class="n">LOG</span> <span class="o">=</span> <span class="n">_logger</span><span class="p">()</span> <span class="c">#===============================================================================</span> <span class="c"># RSYNC HOSTS</span> <span class="c">#===============================================================================</span> <span class="c"># Your default host. No need any more if only wants a host.</span> <span class="n">env</span><span class="o">.</span><span class="n">host_string</span> <span class="o">=</span> <span class="s">&quot;username@host&quot;</span> <span class="n">env</span><span class="o">.</span><span class="n">remote</span> <span class="o">=</span> <span class="s">&quot;/your/remote/path&quot;</span> <span class="n">env</span><span class="o">.</span><span class="n">local</span> <span class="o">=</span> <span class="s">&quot;/your/local/path&quot;</span> <span class="c"># If wants to use various hosts, then define the previous variables like this, </span> <span class="c"># one function per host. </span> <span class="k">def</span> <span class="nf">_host_1</span><span class="p">():</span> <span class="sd">&quot;&quot;&quot;Host variables for host_1.&quot;&quot;&quot;</span> <span class="k">global</span> <span class="n">env</span> <span class="n">env</span><span class="o">.</span><span class="n">host_string</span> <span class="o">=</span> <span class="s">&quot;username@host_1&quot;</span> <span class="n">env</span><span class="o">.</span><span class="n">remote</span> <span class="o">=</span> <span class="s">&quot;/your/remote/path/in/host_1&quot;</span> <span class="n">env</span><span class="o">.</span><span class="n">local</span> <span class="o">=</span> <span class="s">&quot;/your/local/path/for/host_1&quot;</span> <span class="k">def</span> <span class="nf">_host_2</span><span class="p">():</span> <span class="sd">&quot;&quot;&quot;Host variables for host_2.&quot;&quot;&quot;</span> <span class="k">global</span> <span class="n">env</span> <span class="n">env</span><span class="o">.</span><span class="n">host_string</span> <span class="o">=</span> <span class="s">&quot;username@host_2&quot;</span> <span class="n">env</span><span class="o">.</span><span class="n">remote</span> <span class="o">=</span> <span class="s">&quot;/your/remote/path/in/host_2&quot;</span> <span class="n">env</span><span class="o">.</span><span class="n">local</span> <span class="o">=</span> <span class="s">&quot;/your/local/path/for/host_2&quot;</span> <span class="c"># ...</span> <span class="c">#</span> <span class="c"># def _host_n():</span> <span class="c"># &quot;&quot;&quot;Host variables for host_n.&quot;&quot;&quot;</span> <span class="c"># global env</span> <span class="c"># env.host_string = &quot;username@host_n&quot;</span> <span class="c"># env.remote = &quot;/your/remote/path/in/host_n&quot;</span> <span class="c"># env.local = &quot;/your/local/path/for/host_n&quot;</span> <span class="c">#===============================================================================</span> <span class="c"># END RSYNC HOSTS</span> <span class="c">#===============================================================================</span> <span class="k">def</span> <span class="nf">_log_start</span><span class="p">():</span> <span class="sd">&quot;&quot;&quot;Create the Start time info block for the log.&quot;&quot;&quot;</span> <span class="c"># Init the log for multiple hosts. Do not repeat the previous logs.</span> <span class="k">if</span> <span class="n">LOG</span><span class="o">.</span><span class="n">get</span><span class="p">():</span> <span class="n">LOG</span><span class="o">.</span><span class="n">__init__</span><span class="p">()</span> <span class="n">LOG</span><span class="o">.</span><span class="n">time</span><span class="p">(</span><span class="s">&quot;Start time&quot;</span><span class="p">)</span> <span class="k">def</span> <span class="nf">_log_end</span><span class="p">(</span><span class="n">task</span><span class="p">):</span> <span class="sd">&quot;&quot;&quot;Create the End time info block and send &amp; write the log.&quot;&quot;&quot;</span> <span class="n">_notify</span><span class="p">(</span><span class="s">&quot;Rsync&quot;</span><span class="p">,</span> <span class="s">&quot;Ended&quot;</span> <span class="p">,</span> <span class="s">&quot;ok&quot;</span><span class="p">)</span> <span class="n">LOG</span><span class="o">.</span><span class="n">time</span><span class="p">(</span><span class="s">&quot;End time&quot;</span><span class="p">)</span> <span class="n">LOG</span><span class="o">.</span><span class="n">free</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">linesep</span> <span class="o">*</span> <span class="mi">2</span><span class="p">)</span> <span class="n">LOG</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="bp">True</span><span class="p">)</span> <span class="n">LOG</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="s">&quot;Fabric Rsync ({0})&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">task</span><span class="p">))</span> <span class="k">def</span> <span class="nf">_check_local</span><span class="p">():</span> <span class="sd">&quot;&quot;&quot;Create local directory if no exists.&quot;&quot;&quot;</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">env</span><span class="o">.</span><span class="n">local</span><span class="p">):</span> <span class="n">os</span><span class="o">.</span><span class="n">mkdir</span><span class="p">(</span><span class="n">env</span><span class="o">.</span><span class="n">local</span><span class="p">)</span> <span class="k">def</span> <span class="nf">_rsync</span><span class="p">(</span><span class="n">source</span><span class="p">,</span> <span class="n">target</span><span class="p">,</span> <span class="n">delete</span><span class="p">):</span> <span class="sd">&quot;&quot;&quot;Process the _rsync command.&quot;&quot;&quot;</span> <span class="n">_log_start</span><span class="p">()</span> <span class="n">LOG</span><span class="o">.</span><span class="n">header</span><span class="p">(</span><span class="s">&quot;Fabric Rsync</span><span class="se">\n</span><span class="s">http://joedicastro.com&quot;</span><span class="p">,</span> <span class="s">&quot;Syncing {0} to {1}&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">source</span><span class="p">,</span> <span class="n">target</span><span class="p">))</span> <span class="n">_notify</span><span class="p">(</span><span class="s">&quot;Rsync&quot;</span><span class="p">,</span> <span class="s">&quot;Start syncing {0} to {1}&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">source</span><span class="p">,</span> <span class="n">target</span><span class="p">),</span> <span class="s">&quot;info&quot;</span><span class="p">)</span> <span class="n">out</span> <span class="o">=</span> <span class="n">local</span><span class="p">(</span><span class="s">&quot;rsync -pthrvz {2} {0}/ {1}&quot;</span><span class="o">.</span> <span class="n">format</span><span class="p">(</span><span class="n">source</span><span class="p">,</span> <span class="n">target</span><span class="p">,</span> <span class="s">&quot;--delete&quot;</span> <span class="k">if</span> <span class="n">delete</span> <span class="o">==</span> <span class="s">&quot;yes&quot;</span> <span class="k">else</span> <span class="s">&quot;&quot;</span><span class="p">),</span> <span class="n">capture</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span> <span class="n">_notify</span><span class="p">(</span><span class="s">&quot;Rsync&quot;</span><span class="p">,</span> <span class="s">&quot;Finished synchronization&quot;</span><span class="p">,</span> <span class="s">&quot;ok&quot;</span><span class="p">)</span> <span class="n">LOG</span><span class="o">.</span><span class="n">list</span><span class="p">(</span><span class="s">&quot;Rsync Output&quot;</span><span class="p">,</span> <span class="n">out</span><span class="p">)</span> <span class="k">if</span> <span class="n">out</span><span class="o">.</span><span class="n">failed</span><span class="p">:</span> <span class="n">LOG</span><span class="o">.</span><span class="n">list</span><span class="p">(</span><span class="s">&quot;Rsync Errors&quot;</span><span class="p">,</span> <span class="n">out</span><span class="o">.</span><span class="n">stderr</span><span class="p">)</span> <span class="k">def</span> <span class="nf">_compress</span><span class="p">(</span><span class="n">path</span><span class="p">):</span> <span class="sd">&quot;&quot;&quot;Compress a local directory into a gz file.</span> <span class="sd"> Creates a file for each weekday, an removes the old files if exists&quot;&quot;&quot;</span> <span class="n">os</span><span class="o">.</span><span class="n">chdir</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="n">os</span><span class="o">.</span><span class="n">pardir</span><span class="p">))</span> <span class="n">dir2gz</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">basename</span><span class="p">(</span><span class="n">path</span><span class="p">)</span> <span class="n">old_gzs</span> <span class="o">=</span> <span class="n">glob</span><span class="o">.</span><span class="n">glob</span><span class="p">(</span><span class="s">&#39;{0}*{1}.tar.gz&#39;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">dir2gz</span><span class="p">,</span> <span class="n">time</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s">&#39;%a&#39;</span><span class="p">)))</span> <span class="n">gz_name</span> <span class="o">=</span> <span class="s">&quot;{0}_{1}.tar.gz&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">dir2gz</span><span class="p">,</span> <span class="n">time</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s">&#39;</span><span class="si">%d</span><span class="s">%b%Y_%H:%M_%a&#39;</span><span class="p">))</span> <span class="n">gz_file</span> <span class="o">=</span> <span class="n">tarfile</span><span class="o">.</span><span class="n">open</span><span class="p">(</span><span class="n">gz_name</span><span class="p">,</span> <span class="s">&quot;w:gz&quot;</span><span class="p">)</span> <span class="n">gz_file</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="n">arcname</span><span class="o">=</span><span class="n">dir2gz</span><span class="p">)</span> <span class="n">gz_file</span><span class="o">.</span><span class="n">close</span><span class="p">()</span> <span class="n">output</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">linesep</span><span class="o">.</span><span class="n">join</span><span class="p">([</span><span class="s">&#39;Created file:&#39;</span><span class="p">,</span> <span class="s">&#39;&#39;</span><span class="p">,</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">getcwd</span><span class="p">(),</span> <span class="n">gz_name</span><span class="p">)])</span> <span class="k">for</span> <span class="n">old_gz</span> <span class="ow">in</span> <span class="n">old_gzs</span><span class="p">:</span> <span class="n">os</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">old_gz</span><span class="p">)</span> <span class="n">output</span> <span class="o">+=</span> <span class="n">os</span><span class="o">.</span><span class="n">linesep</span><span class="o">.</span><span class="n">join</span><span class="p">([</span><span class="n">os</span><span class="o">.</span><span class="n">linesep</span><span class="p">,</span> <span class="s">&#39;Deleted old file:&#39;</span><span class="p">,</span> <span class="s">&#39;&#39;</span><span class="p">,</span> <span class="n">old_gz</span><span class="p">])</span> <span class="k">return</span> <span class="n">output</span> <span class="k">def</span> <span class="nf">_archive</span><span class="p">():</span> <span class="sd">&quot;&quot;&quot;Archive the local directory in a gz file for each weekday.&quot;&quot;&quot;</span> <span class="n">_notify</span><span class="p">(</span><span class="s">&#39;Rsync&#39;</span><span class="p">,</span> <span class="s">&#39;Compressing folder...&#39;</span><span class="p">,</span> <span class="s">&#39;info&#39;</span><span class="p">)</span> <span class="n">LOG</span><span class="o">.</span><span class="n">list</span><span class="p">(</span><span class="s">&#39;Rotate compressed copies&#39;</span><span class="p">,</span> <span class="n">_compress</span><span class="p">(</span><span class="n">env</span><span class="o">.</span><span class="n">local</span><span class="p">))</span> <span class="n">_notify</span><span class="p">(</span><span class="s">&quot;Rsync&quot;</span><span class="p">,</span> <span class="s">&quot;Finished compression&quot;</span><span class="p">,</span> <span class="s">&quot;ok&quot;</span><span class="p">)</span> <span class="k">def</span> <span class="nf">_get_diskspace</span><span class="p">():</span> <span class="sd">&quot;&quot;&quot;Get the disk space used by the local directory and archives.&quot;&quot;&quot;</span> <span class="n">gz_size</span> <span class="o">=</span> <span class="nb">sum</span><span class="p">([</span><span class="n">_get_size</span><span class="p">(</span><span class="n">gz</span><span class="p">)</span> <span class="k">for</span> <span class="n">gz</span> <span class="ow">in</span> <span class="n">glob</span><span class="o">.</span><span class="n">glob</span><span class="p">(</span><span class="s">&#39;{0}*.gz&#39;</span><span class="o">.</span> <span class="n">format</span><span class="p">(</span><span class="n">env</span><span class="o">.</span><span class="n">local</span><span class="p">))])</span> <span class="n">log_size</span> <span class="o">=</span> <span class="n">_get_size</span><span class="p">(</span><span class="n">LOG</span><span class="o">.</span><span class="n">filename</span><span class="p">)</span> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">LOG</span><span class="o">.</span><span class="n">filename</span><span class="p">)</span> <span class="k">else</span> <span class="mi">0</span> <span class="n">local_size</span> <span class="o">=</span> <span class="n">_get_size</span><span class="p">(</span><span class="n">env</span><span class="o">.</span><span class="n">local</span><span class="p">)</span> <span class="n">size</span> <span class="o">=</span> <span class="n">_best_unit_size</span><span class="p">(</span><span class="n">local_size</span> <span class="o">+</span> <span class="n">gz_size</span> <span class="o">+</span> <span class="n">log_size</span><span class="p">)</span> <span class="n">LOG</span><span class="o">.</span><span class="n">block</span><span class="p">(</span><span class="s">&#39;Disk space used&#39;</span><span class="p">,</span> <span class="s">&#39;{0:&gt;76.2f} {1}&#39;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">size</span><span class="p">[</span><span class="s">&#39;s&#39;</span><span class="p">],</span> <span class="n">size</span><span class="p">[</span><span class="s">&#39;u&#39;</span><span class="p">]))</span> <span class="k">def</span> <span class="nf">up</span><span class="p">(</span><span class="n">server</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">dlt</span><span class="o">=</span><span class="s">&#39;yes&#39;</span><span class="p">):</span> <span class="sd">&quot;&quot;&quot;Sync from local to remote.&quot;&quot;&quot;</span> <span class="nb">globals</span><span class="p">()[</span><span class="s">&quot;_&quot;</span> <span class="o">+</span> <span class="n">server</span><span class="p">]()</span> <span class="k">if</span> <span class="n">server</span> <span class="k">else</span> <span class="bp">None</span> <span class="n">_rsync</span><span class="p">(</span><span class="n">env</span><span class="o">.</span><span class="n">local</span><span class="p">,</span> <span class="s">&quot;:&quot;</span><span class="o">.</span><span class="n">join</span><span class="p">([</span><span class="n">env</span><span class="o">.</span><span class="n">host_string</span><span class="p">,</span> <span class="n">env</span><span class="o">.</span><span class="n">remote</span><span class="p">]),</span> <span class="n">dlt</span><span class="p">)</span> <span class="n">_log_end</span><span class="p">(</span><span class="n">server</span><span class="p">)</span> <span class="k">def</span> <span class="nf">down</span><span class="p">(</span><span class="n">server</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">dlt</span><span class="o">=</span><span class="s">&#39;yes&#39;</span><span class="p">,</span> <span class="n">archive</span><span class="o">=</span><span class="bp">False</span><span class="p">):</span> <span class="sd">&quot;&quot;&quot;Sync from remote to local.&quot;&quot;&quot;</span> <span class="nb">globals</span><span class="p">()[</span><span class="s">&quot;_&quot;</span> <span class="o">+</span> <span class="n">server</span><span class="p">]()</span> <span class="k">if</span> <span class="n">server</span> <span class="k">else</span> <span class="bp">None</span> <span class="n">_check_local</span><span class="p">()</span> <span class="n">_rsync</span><span class="p">(</span><span class="s">&quot;:&quot;</span><span class="o">.</span><span class="n">join</span><span class="p">([</span><span class="n">env</span><span class="o">.</span><span class="n">host_string</span><span class="p">,</span> <span class="n">env</span><span class="o">.</span><span class="n">remote</span><span class="p">]),</span> <span class="n">env</span><span class="o">.</span><span class="n">local</span><span class="p">,</span> <span class="n">dlt</span><span class="p">)</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">archive</span><span class="p">:</span> <span class="n">_log_end</span><span class="p">(</span><span class="n">server</span><span class="p">)</span> <span class="k">def</span> <span class="nf">backup</span><span class="p">(</span><span class="n">server</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span> <span class="sd">&quot;&quot;&quot;Sync from remote to local &amp; archive the local directory.&quot;&quot;&quot;</span> <span class="n">down</span><span class="p">(</span><span class="n">server</span><span class="p">,</span> <span class="n">archive</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span> <span class="n">_archive</span><span class="p">()</span> <span class="n">_get_diskspace</span><span class="p">()</span> <span class="n">_log_end</span><span class="p">(</span><span class="n">server</span><span class="p">)</span> </pre></div> <p>El fichero siempre actualizado puede ser encontrado en el repositorio <em>Python Recipes</em> que está alojado en <a href="http://github.com/joedicastro/python-recipes">github</a> con el nombre <code>rsync_fabfile.py</code> </p>joe di castroWed, 13 Jul 2011 20:21:00 +0200http://joedicastro.com/fabric-rsync-para-realizar-backups.htmlpythonfabricrsyncbackupsincronizar