mirror of
https://github.com/almet/notmyidea.git
synced 2025-04-28 19:42:37 +02:00
304 lines
No EOL
18 KiB
HTML
304 lines
No EOL
18 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
<meta http-equiv="content-type" content="text/html; charset=utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1">
|
|
<link rel="shortcut icon" type="image/x-icon" href="favicon.ico" />
|
|
|
|
<title>Working directly on your server? How to backup and sync your dev environment with unison - Alexis - Carnets en ligne</title>
|
|
|
|
<meta charset="utf-8" />
|
|
<link href="https://blog.notmyidea.org/feeds/all.atom.xml" type="application/atom+xml" rel="alternate" title="Alexis - Carnets en ligne Full Atom Feed" />
|
|
<link rel="stylesheet" href="https://blog.notmyidea.org/theme/css/poole.css"/>
|
|
<link rel="stylesheet" href="https://blog.notmyidea.org/theme/css/syntax.css"/>
|
|
<link rel="stylesheet" href="https://blog.notmyidea.org/theme/css/lanyon.css"/>
|
|
<link rel="stylesheet" href="//fonts.googleapis.com/css?family=PT+Serif:400,400italic,700%7CPT+Sans:400">
|
|
<link rel="stylesheet" href="https://blog.notmyidea.org/theme/css/styles.css"/>
|
|
|
|
|
|
|
|
<style>
|
|
|
|
h1 {
|
|
font-family: "Avant Garde", Avantgarde, "Century Gothic", CenturyGothic, "AppleGothic", sans-serif;
|
|
padding: 80px 50px;
|
|
text-align: center;
|
|
text-transform: uppercase;
|
|
text-rendering: optimizeLegibility;
|
|
color: #202020;
|
|
letter-spacing: .1em;
|
|
text-shadow:
|
|
-1px -1px 1px #111,
|
|
2px 2px 1px #eaeaea;
|
|
}
|
|
|
|
#main {
|
|
text-align: justify;
|
|
text-justify: inter-word;
|
|
}
|
|
#main h1 {
|
|
padding: 10px;
|
|
}
|
|
|
|
.post-headline {
|
|
padding: 15px;
|
|
}
|
|
</style>
|
|
</head>
|
|
|
|
<body>
|
|
<!-- Target for toggling the sidebar `.sidebar-checkbox` is for regular
|
|
styles, `#sidebar-checkbox` for behavior. -->
|
|
<input type="checkbox" class="sidebar-checkbox" id="sidebar-checkbox">
|
|
<!-- Toggleable sidebar -->
|
|
<div class="sidebar" id="sidebar">
|
|
<div class="sidebar-item">
|
|
<div class="profile">
|
|
<img src="https://blog.notmyidea.org/theme/img/profile.png"/>
|
|
</div>
|
|
</div>
|
|
|
|
<nav class="sidebar-nav">
|
|
<a class="sidebar-nav-item" href="/">Articles</a>
|
|
|
|
<a class="sidebar-nav-item" href="https://www.vieuxsinge.com">Brasserie du Vieux Singe</a>
|
|
<a class="sidebar-nav-item" href="http://blog.notmyidea.org/pages/about.html">A propos</a>
|
|
<a class="sidebar-nav-item" href="https://twitter.com/ametaireau">Messages courts</a>
|
|
<a class="sidebar-nav-item" href="https://github.com/almet">Code</a>
|
|
</nav>
|
|
</div> <div class="wrap">
|
|
<div class="masthead">
|
|
<div class="container">
|
|
<h3 class="masthead-title">
|
|
<a href="https://blog.notmyidea.org/" title="Home">Alexis - Carnets en ligne</a>
|
|
</h3>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="container content">
|
|
<div id="main" class="posts">
|
|
<h1 class="post-title">Working directly on your server? How to backup and sync your dev environment with unison</h1>
|
|
<span class="post-date">16 mars 2011, dans <a class="no-color" href="category/technologie.html">Technologie</a></span>
|
|
<img id="illustration" src="" />
|
|
|
|
<div class="post article">
|
|
<h1>🌟</h1>
|
|
|
|
<p>I have a server running freebsd since some time now, and was wondering
|
|
about the possibility to directly have a development environment ready
|
|
to use when I get a internet connexion, even if I'm not on my computer.</p>
|
|
<p>Since I use vim to code, and spend most of my time in a console while
|
|
developing, it's possible to work via ssh, from everywhere.</p>
|
|
<p>The only problem is the synchronisation of the source code, config files
|
|
etc. from my machine to the server.</p>
|
|
<p>Unison provides an interesting way to synchronise two folders, even over
|
|
a network. So let's do it !</p>
|
|
<h2 id="creating-the-jail">Creating the jail</h2>
|
|
<p>In case you don't use FreeBSD, you can skip this section.</p>
|
|
<div class="highlight"><pre><span></span><span class="o">#</span> <span class="n">I</span> <span class="n">have</span> <span class="n">a</span> <span class="n">flavour</span> <span class="n">jail</span> <span class="n">named</span> <span class="k">default</span>
|
|
<span class="err">$</span> <span class="n">ezjail</span><span class="o">-</span><span class="k">admin</span> <span class="o">-</span><span class="n">f</span> <span class="k">default</span> <span class="n">workspace</span><span class="p">.</span><span class="n">notmyidea</span><span class="p">.</span><span class="n">org</span> <span class="mi">172</span><span class="p">.</span><span class="mi">19</span><span class="p">.</span><span class="mi">1</span><span class="p">.</span><span class="mi">6</span>
|
|
<span class="err">$</span> <span class="n">ezjail</span><span class="o">-</span><span class="k">admin</span> <span class="k">start</span> <span class="n">workspace</span><span class="p">.</span><span class="n">notmyidea</span><span class="p">.</span><span class="n">org</span>
|
|
</pre></div>
|
|
|
|
|
|
<p>In my case, because the "default" flavour contains already a lot of
|
|
interesting things, my jail come already setup with ssh, bash and vim
|
|
for instance, but maybe you'll need it in your case.</p>
|
|
<p>I want to be redirected to the ssh of the jail when I connect to the
|
|
host with the 20006 port. Add lines in <code>/etc/pf.conf</code>:</p>
|
|
<div class="highlight"><pre><span></span> <span class="nv">workspace_jail</span><span class="o">=</span><span class="s2">"172.19.1.6"</span>
|
|
rdr on <span class="nv">$ext_if</span> proto tcp from any to <span class="nv">$ext_ip</span> port <span class="m">20006</span> -> <span class="nv">$workspace_jail</span> port <span class="m">22</span>
|
|
</pre></div>
|
|
|
|
|
|
<p>Reload packet filter rules</p>
|
|
<div class="highlight"><pre><span></span>$ /etc/rc.d/pf reload
|
|
</pre></div>
|
|
|
|
|
|
<h2 id="working-with-unison">Working with unison</h2>
|
|
<p>Now that we've set up the jail. Set up unison on the server and on your
|
|
client. Unison is available on the freebsd ports so just install it</p>
|
|
<div class="highlight"><pre><span></span>$ ssh notmyidea.org -p <span class="m">20006</span>
|
|
$ make -C /usr/ports/net/unison-nox11 config-recursive
|
|
$ make -C /usr/ports/net/unison-nox11 package-recursive
|
|
</pre></div>
|
|
|
|
|
|
<p>Install as well unison on your local machine. Double check to install
|
|
the same version on the client and on the server. Ubuntu contains the
|
|
2.27.57 as well as the 2.32.52.</p>
|
|
<p>Check that unison is installed and reachable via ssh from your machine</p>
|
|
<div class="highlight"><pre><span></span>$ ssh notmyidea.org -p <span class="m">20006</span> unison -version
|
|
unison version <span class="m">2</span>.27.157
|
|
$ unison -version
|
|
unison version <span class="m">2</span>.27.57
|
|
</pre></div>
|
|
|
|
|
|
<h2 id="let-sync-our-folders">Let sync our folders</h2>
|
|
<p>The first thing I want to sync is my vim configuration. Well, it's
|
|
already <a href="http://github.com/ametaireau/dotfiles/">in a git repository</a>
|
|
but let's try to use unison for it right now.</p>
|
|
<p>I have two machines then: workspace, the jail, and ecureuil my laptop.</p>
|
|
<div class="highlight"><pre><span></span>unison .vim ssh://notmyidea.org:20006/.vim
|
|
unison .vimrc ssh://notmyidea.org:20006/.vimrc
|
|
</pre></div>
|
|
|
|
|
|
<p>It is also possible to put all the informations in a config file, and
|
|
then to only run unison. (fire up vim \~/.unison/default.prf.</p>
|
|
<p>Here is my config:</p>
|
|
<div class="highlight"><pre><span></span> <span class="na">root</span> <span class="o">=</span> <span class="s">/home/alexis</span>
|
|
<span class="s"> root = ssh://notmyidea.org:20006</span>
|
|
|
|
<span class="na">path</span> <span class="o">=</span> <span class="s">.vimrc</span>
|
|
<span class="s"> path = dotfiles</span>
|
|
<span class="s"> path = dev</span>
|
|
|
|
<span class="na">follow</span> <span class="o">=</span> <span class="s">Name *</span>
|
|
</pre></div>
|
|
|
|
|
|
<p>My vimrc is in fact a symbolic link on my laptop, but I don't want to
|
|
specify each of the links to unison. That's why the follow = Name * is
|
|
for.</p>
|
|
<p>The folders you want to synchronize are maybe a bit large. If so,
|
|
considering others options such as rsync for the first import may be a
|
|
good idea (I enjoyed my university huge upload bandwith to upload 2GB in
|
|
20mn ;)</p>
|
|
<h2 id="run-the-script-frequently">Run the script frequently</h2>
|
|
<p>Once that done, you just need to run the unison command line some times
|
|
when you want to sync your two machines. I've wrote a tiny script to get
|
|
some feedback from the sync:</p>
|
|
<div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">os</span>
|
|
<span class="kn">from</span> <span class="nn">datetime</span> <span class="kn">import</span> <span class="n">datetime</span>
|
|
|
|
<span class="n">DEFAULT_LOGFILE</span> <span class="o">=</span> <span class="s2">"~/unison.log"</span>
|
|
<span class="n">PROGRAM_NAME</span> <span class="o">=</span> <span class="s2">"Unison syncer"</span>
|
|
|
|
<span class="k">def</span> <span class="nf">sync</span><span class="p">(</span><span class="n">logfile</span><span class="o">=</span><span class="n">DEFAULT_LOGFILE</span><span class="p">,</span> <span class="n">program_name</span><span class="o">=</span><span class="n">PROGRAM_NAME</span><span class="p">):</span>
|
|
<span class="c1"># init</span>
|
|
<span class="n">display_message</span> <span class="o">=</span> <span class="bp">True</span>
|
|
<span class="n">error</span> <span class="o">=</span> <span class="bp">False</span>
|
|
|
|
<span class="n">before</span> <span class="o">=</span> <span class="n">datetime</span><span class="o">.</span><span class="n">now</span><span class="p">()</span>
|
|
<span class="c1"># call unison to make the sync</span>
|
|
<span class="n">os</span><span class="o">.</span><span class="n">system</span><span class="p">(</span><span class="s1">'unison -batch > {0}'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">logfile</span><span class="p">))</span>
|
|
|
|
<span class="c1"># get the duration of the operation</span>
|
|
<span class="n">td</span> <span class="o">=</span> <span class="n">datetime</span><span class="o">.</span><span class="n">now</span><span class="p">()</span> <span class="o">-</span> <span class="n">before</span>
|
|
<span class="n">delta</span> <span class="o">=</span> <span class="p">(</span><span class="n">td</span><span class="o">.</span><span class="n">microseconds</span> <span class="o">+</span> <span class="p">(</span><span class="n">td</span><span class="o">.</span><span class="n">seconds</span> <span class="o">+</span> <span class="n">td</span><span class="o">.</span><span class="n">days</span> <span class="o">*</span> <span class="mi">24</span> <span class="o">*</span> <span class="mi">3600</span><span class="p">)</span> <span class="o">*</span> <span class="mi">10</span><span class="o">**</span><span class="mi">6</span><span class="p">)</span> <span class="o">/</span> <span class="mi">10</span><span class="o">**</span><span class="mi">6</span>
|
|
|
|
<span class="c1"># check what was the last entry in the log</span>
|
|
<span class="n">log</span> <span class="o">=</span> <span class="nb">open</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">expanduser</span><span class="p">(</span><span class="n">logfile</span><span class="p">))</span>
|
|
<span class="n">lines</span> <span class="o">=</span> <span class="n">log</span><span class="o">.</span><span class="n">readlines</span><span class="p">()</span>
|
|
<span class="k">if</span> <span class="s1">'No updates to propagate'</span> <span class="ow">in</span> <span class="n">lines</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]:</span>
|
|
<span class="n">display_message</span> <span class="o">=</span> <span class="bp">False</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">output</span> <span class="o">=</span> <span class="p">[</span><span class="n">l</span> <span class="k">for</span> <span class="n">l</span> <span class="ow">in</span> <span class="n">lines</span> <span class="k">if</span> <span class="s2">"Synchronization"</span> <span class="ow">in</span> <span class="n">l</span><span class="p">]</span>
|
|
|
|
<span class="n">message</span> <span class="o">=</span> <span class="n">output</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
|
|
<span class="n">message</span> <span class="o">+=</span> <span class="s2">" It took {0}s."</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">delta</span><span class="p">)</span>
|
|
|
|
<span class="k">if</span> <span class="n">display_message</span><span class="p">:</span>
|
|
<span class="n">os</span><span class="o">.</span><span class="n">system</span><span class="p">(</span><span class="s1">'notify-send -i {2} "{0}" "{1}"'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">program_name</span><span class="p">,</span> <span class="n">message</span><span class="p">,</span>
|
|
<span class="s1">'error'</span> <span class="k">if</span> <span class="n">error</span> <span class="k">else</span> <span class="s1">'info'</span><span class="p">))</span>
|
|
|
|
<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">"__main__"</span><span class="p">:</span>
|
|
<span class="n">sync</span><span class="p">()</span>
|
|
</pre></div>
|
|
|
|
|
|
<p>This is probably perfectible, but that does the job.</p>
|
|
<p>Last step is to tell you machine to run that frequently. That's what
|
|
crontab is made for, so let's <code>crontab -e</code>:</p>
|
|
<div class="highlight"><pre><span></span> <span class="err">$</span> <span class="o">*</span> <span class="o">*/</span><span class="mi">3</span> <span class="o">*</span> <span class="o">*</span> <span class="o">*</span> <span class="p">.</span> <span class="o">~/</span><span class="p">.</span><span class="n">Xdbus</span><span class="p">;</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">python</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">alexis</span><span class="o">/</span><span class="n">dev</span><span class="o">/</span><span class="n">python</span><span class="o">/</span><span class="n">unison</span><span class="o">-</span><span class="n">syncer</span><span class="o">/</span><span class="n">sync</span><span class="p">.</span><span class="n">py</span>
|
|
</pre></div>
|
|
|
|
|
|
<p>The \~/.Xdbus allows cron to communicate with your X11 session. Here is
|
|
its content.</p>
|
|
<div class="highlight"><pre><span></span><span class="ch">#!/bin/bash</span>
|
|
|
|
<span class="c1"># Get the pid of nautilus</span>
|
|
<span class="nv">nautilus_pid</span><span class="o">=</span><span class="k">$(</span>pgrep -u <span class="nv">$LOGNAME</span> -n nautilus<span class="k">)</span>
|
|
|
|
<span class="c1"># If nautilus isn't running, just exit silently</span>
|
|
<span class="k">if</span> <span class="o">[</span> -z <span class="s2">"</span><span class="nv">$nautilus_pid</span><span class="s2">"</span> <span class="o">]</span><span class="p">;</span> <span class="k">then</span>
|
|
<span class="nb">exit</span> <span class="m">0</span>
|
|
<span class="k">fi</span>
|
|
|
|
<span class="c1"># Grab the DBUS_SESSION_BUS_ADDRESS variable from nautilus's environment</span>
|
|
<span class="nb">eval</span> <span class="k">$(</span>tr <span class="s1">'\0'</span> <span class="s1">'\n'</span> < /proc/<span class="nv">$nautilus_pid</span>/environ <span class="p">|</span> grep <span class="s1">'^DBUS_SESSION_BUS_ADDRESS='</span><span class="k">)</span>
|
|
|
|
<span class="c1"># Check that we actually found it</span>
|
|
<span class="k">if</span> <span class="o">[</span> -z <span class="s2">"</span><span class="nv">$DBUS_SESSION_BUS_ADDRESS</span><span class="s2">"</span> <span class="o">]</span><span class="p">;</span> <span class="k">then</span>
|
|
<span class="nb">echo</span> <span class="s2">"Failed to find bus address"</span> ><span class="p">&</span><span class="m">2</span>
|
|
<span class="nb">exit</span> <span class="m">1</span>
|
|
<span class="k">fi</span>
|
|
|
|
<span class="c1"># export it so that child processes will inherit it</span>
|
|
<span class="nb">export</span> DBUS_SESSION_BUS_ADDRESS
|
|
</pre></div>
|
|
|
|
|
|
<p>And it comes from
|
|
<a href="http://ubuntuforums.org/showthread.php?p=10148738#post10148738">here</a>.</p>
|
|
<p>A sync takes about 20s + the upload time on my machine, which stay
|
|
acceptable for all of my developments.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<label for="sidebar-checkbox" class="sidebar-toggle"></label>
|
|
|
|
<script>
|
|
(function(document) {
|
|
var i = 0;
|
|
// snip empty header rows since markdown can't
|
|
var rows = document.querySelectorAll('tr');
|
|
for(i=0; i<rows.length; i++) {
|
|
var ths = rows[i].querySelectorAll('th');
|
|
var rowlen = rows[i].children.length;
|
|
if (ths.length > 0 && ths.length === rowlen) {
|
|
rows[i].remove();
|
|
}
|
|
}
|
|
})(document);
|
|
</script>
|
|
|
|
<script>
|
|
/* Lanyon & Poole are Copyright (c) 2014 Mark Otto. Adapted to Pelican 20141223 and extended a bit by @thomaswilley */
|
|
(function(document) {
|
|
var toggle = document.querySelector('.sidebar-toggle');
|
|
var sidebar = document.querySelector('#sidebar');
|
|
var checkbox = document.querySelector('#sidebar-checkbox');
|
|
document.addEventListener('click', function(e) {
|
|
var target = e.target;
|
|
if(!checkbox.checked ||
|
|
sidebar.contains(target) ||
|
|
(target === checkbox || target === toggle)) return;
|
|
checkbox.checked = false;
|
|
}, false);
|
|
})(document);
|
|
</script>
|
|
<!-- Piwik -->
|
|
<script type="text/javascript">
|
|
var _paq = _paq || [];
|
|
_paq.push(['trackPageView']);
|
|
_paq.push(['enableLinkTracking']);
|
|
(function() {
|
|
var u="//tracker.notmyidea.org/";
|
|
_paq.push(['setTrackerUrl', u+'piwik.php']);
|
|
_paq.push(['setSiteId', 3]);
|
|
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
|
|
g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'piwik.js'; s.parentNode.insertBefore(g,s);
|
|
})();
|
|
</script>
|
|
<noscript><p><img src="//tracker.notmyidea.org/piwik.php?idsite=3" style="border:0;" alt="" /></p></noscript>
|
|
<!-- End Piwik Code -->
|
|
</div>
|
|
</body>
|
|
</html> |