Jekyll2019-02-19T20:16:47+00:00https://devarcs.com/Dev ArcsBlog about IT Development and Architecture whith just thoughts about trends and hypes and practical things that keep me busy.{"name"=>nil, "job_title"=>nil, "location"=>nil, "email"=>"info@devarcs.com", "social_links"=>[{"name"=>"twitter", "url"=>"https://twitter.com/ArchitectViews"}, {"name"=>"vk", "url"=>nil}]}info@devarcs.comGreat ansible error message2018-12-11T20:21:00+00:002018-12-11T20:21:00+00:00https://devarcs.com/blog/ui/ux/great-ansible-error-message<p>This error message of <em>ansible</em> is one example of excellent ui design.</p>
<div class="language-bash highlighter-rouge"><pre class="highlight"><code><span class="o">[</span>DEPRECATION WARNING]: Invoking <span class="s2">"homebrew"</span> only once <span class="k">while </span>using a loop via
squash_actions is deprecated. Instead of using a loop to supply multiple items
and specifying <span class="sb">`</span>name: <span class="sb">`</span>, please use <span class="sb">`</span>name: <span class="o">[</span><span class="s1">'zsh'</span>, <span class="s1">'zsh-completions'</span>,
<span class="s1">'zsh-syntax-highlighting'</span><span class="o">]</span><span class="sb">`</span> and remove the loop. This feature will be removed
<span class="k">in </span>version 2.11.
</code></pre>
</div>
<p>The nice thing about it is that the error message not only tells me in abstract words what to do. The following part is the exact one to copy / paste for fixing the deprecated feature:</p>
<div class="language-bash highlighter-rouge"><pre class="highlight"><code>name: <span class="o">[</span><span class="s1">'zsh'</span>, <span class="s1">'zsh-completions'</span>, <span class="s1">'zsh-syntax-highlighting'</span><span class="o">]</span>
</code></pre>
</div>
<p>Nice <em>ansible</em>. Very nice!</p>timThis error message of ansible is one example of excellent ui design. [DEPRECATION WARNING]: Invoking "homebrew" only once while using a loop viaOpDevs2018-04-07T08:51:00+00:002018-04-07T08:51:00+00:00https://devarcs.com/blog/meta/opdevs<p>So what is <em>operations</em>? And what does a developer or architect has to do with operations?</p>
<p>Usually the answer to the question is all about running shipped software products under quality aspects as availability, performance or safety and it comes to monitoring stuff and doing all that with a high professionality. And it’s all about the question if it is a good idea to strictly separate development and operations or instead letting the same people do both. And as for the most questions that are more complex than 1, 2, 3 there are pro’s and con’s for both sides. So I instead will write about a thought that might be perfectly obvious: Every developer is also an operator.</p>
<p>When I was thinking about a structure for the blog it came to setting categories and since this blog is intended to be about <em>development</em> and <em>architecture</em> in the past there is a lot of stuff I wouldn’t call it either, but I would categorize it as <em>operations</em>.</p>
<h2 id="heading-operations-during-development">Operations during Development</h2>
<p>Operations is all about connecting everything together and keep it running - right? So as soon as you are using your computer you are doing operations - just remember that you are using an operational system. As soon as you do house keeping on your computer, as soon as you update software or delete old files you do operations. You can’t develop without setting up things, keeping things running, maintaining your tools and data or building up chains and processes. That’s all operations. So there is a huge percentage of operation in the daily business of a developer. Especially at a single developers project. That sometimes is kind of frustrating when you want to start and write code and instead you have to deal with setting up a lot of tools and tool chains instead.</p>
<p><img src="/assets/posts/2018-04-07-opdevs/operating-time-1.png" alt="" title="Time share of operation tasks for a single developer in a project" /></p>
<p>On bigger teams often one ore even better two persons keep up running the tool chains and maintaining the infrastructure so that the time share on operations for each single developer sinks. But it may also raise with bigger teams if they rely on shared resources that no one really manages. The image above is a static view of the time a developer spends on operations in relation to the total number of developers on the project. Of course there are also dynamic views. Over the time of a project usually the time a developer does operations sinks because the tool chain is set and a lot of automation was built for recurring tasks. If that’s not happening I assume the tool chain is bad or automation is too low. Usually developers hate it to do repetitive stuff so they will optimize and automate it. Most of the <em>operations</em> tasks are only needed during the development process and have nothing to do with operating a shipped application - which is exactly what the <em>DevOps</em> movement is all about. But it is <em>operations</em> and therefore operations is a big part in software development.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Developers do <em>operations</em> all the time - as almost all people do using computers intensely. This of course differs on many aspects from what operators do. The thing operators usually deal with is the huge number of applications they supervise and therefore they have totally different requirements to operations than developers do. But operations totally is also a huge aspect during development or using computers at all. For that reason it is legit to bring focus to it and discuss it. To sum up, one can say talking about <em>DevOps</em> is the big controversial thing while being an <em>OpDev</em> is totally usual and nobody talks about it.</p>timSo what is operations? And what does a developer or architect has to do with operations?Strict Transport Security2018-03-28T20:05:00+00:002018-03-28T20:05:00+00:00https://devarcs.com/blog/web/security/strict-transport-security<p><img src="/assets/posts/2018-03-28-strict-transport-security/strict-transport-security.png" alt="" /></p>
<p>Have you ever wondered why your Webbrowser keeps changing your explicitly entered <em>http</em> URLs to <em>https</em> after removing forwarding rules to enforce HTTPS?</p>
<p>Then maybe your server is configured with <em>HTTP Strict Transport Security (HSTS)</em> which is a server side web security feature that tells calling web agents always to use HTTPS and remap every HTTP request to HTTPS.</p>
<p>You can simply check a HTTP response for any HTTPS request to your server. Watch out for <code class="highlighter-rouge">Strict-Transport-Security</code> and maybe you will find a header maybe that might look similar to the following example:</p>
<div class="language-http highlighter-rouge"><pre class="highlight"><code><span class="err">Strict-Transport-Security: max-age=31536000; includeSubdomains
</span></code></pre>
</div>
<p>It tells web agents to remember for 3153600 seconds (1 year) that they must send requests to the current domain (including it’s subdomains) as HTTPS requests. Web agents then will rewrite each HTTP requests to HTTPS requests.</p>
<p>As a general rule you can fix the problem during your server reconfiguration sessions by cleaning your browser history for the concerned domain.</p>
<p>Sources:</p>
<ul>
<li><a href="https://tools.ietf.org/html/rfc6797" title="RFC 6797">RFC 6797</a></li>
<li><a href="https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security" title="Wikipedia">Wikipedia</a></li>
</ul>{"name"=>nil, "job_title"=>nil, "location"=>nil, "email"=>"info@devarcs.com", "social_links"=>[{"name"=>"twitter", "url"=>"https://twitter.com/ArchitectViews"}, {"name"=>"vk", "url"=>nil}]}info@devarcs.comMake your Shell more comfortable2018-03-14T23:30:53+00:002018-03-14T23:30:53+00:00https://devarcs.com/blog/shell/linux/make-your-shell-more-comfortable<p>My checklist for being more comfortable when dealing with new shells on new systems.</p>
<h2 id="heading-that-annoying-bell">That annoying bell</h2>
<p>If you want to disable the annoying bell sound in the shell or vi but cannot disable it via the terminal program than it is possible to disable it in the shell of the system.</p>
<p>Disable shell bell sounds in <code class="highlighter-rouge">~/.inputrc</code>:</p>
<div class="language-shell highlighter-rouge"><pre class="highlight"><code><span class="nb">set </span>bell-style none
</code></pre>
</div>
<p>Disable vi bell sounds in <code class="highlighter-rouge">~/.vimrc</code>:</p>
<div class="language-shell highlighter-rouge"><pre class="highlight"><code><span class="nb">set </span>visualbell
<span class="nb">set </span><span class="nv">t_vb</span><span class="o">=</span>
</code></pre>
</div>
<p>Disable zsh bell sound in <code class="highlighter-rouge">.zshrc</code>:</p>
<div class="language-shell highlighter-rouge"><pre class="highlight"><code>unsetopt beep
</code></pre>
</div>
<h2 id="heading-vi">vi</h2>
<h3 id="heading-better-vi-colors">Better vi colors</h3>
<p>Often the colors in vi are too dark for a black background. You can change the colorset. Here is the one which I like most of the default sets.</p>
<p>Change vi colorset in <code class="highlighter-rouge">~/.vimrc</code>:</p>
<div class="language-vim highlighter-rouge"><pre class="highlight"><code><span class="k">colorscheme</span> elflord
</code></pre>
</div>
<h3 id="heading-the-undiscovered-filetype">The undiscovered filetype</h3>
<p>Sometimes you have a file with a wrong or without an extension. You can manually set the filetype within vi. Let’s assume you have a conf file:</p>
<div class="language-vim highlighter-rouge"><pre class="highlight"><code><span class="p">:</span><span class="k">set</span> syntax<span class="p">=</span><span class="k">conf</span>
</code></pre>
</div>
<p>or</p>
<div class="language-vim highlighter-rouge"><pre class="highlight"><code><span class="p">:</span><span class="k">set</span> <span class="k">filetype</span><span class="p">=</span><span class="k">conf</span>
</code></pre>
</div>
<h3 id="heading-copy--paste-stairs">Copy / Paste stairs</h3>
<p>You possible had the situation where pasting something into <em>vi</em> results in nasty <em>indent stairs</em> because vi indents each line more than the last?
You can get rid of this if you set vi to <em>paste mode</em> before:</p>
<div class="language-vim highlighter-rouge"><pre class="highlight"><code><span class="p">:</span><span class="k">set</span> paste
</code></pre>
</div>{"name"=>nil, "job_title"=>nil, "location"=>nil, "email"=>"info@devarcs.com", "social_links"=>[{"name"=>"twitter", "url"=>"https://twitter.com/ArchitectViews"}, {"name"=>"vk", "url"=>nil}]}info@devarcs.comMy checklist for being more comfortable when dealing with new shells on new systems.Duply with Dropbox2016-09-19T23:30:53+00:002016-09-19T23:30:53+00:00https://devarcs.com/blog/shell/linux/backup/duply-with-dropbox<p><img src="/assets/posts/2016-09-20-duply-with-dropbox/title.png" alt="" /></p>
<p><strong>Update 2017-10-20: Because Dropbox resigned their API v1</strong></p>
<p>It is possible to use dropbox as a cloud backend for duplicity or duply for backing up data. While I use duply for server backups this is also possible on linux clients. I am using:</p>
<ul>
<li><em>Ubuntu</em> 16.04 LTS</li>
<li>with its default version of duply</li>
<li>a newer version of <em>duplicity</em> (see BackendException: Could not initialize backend: cannot import name client)</li>
<li>and with python <em>dropbox</em> client (v8.4.0)</li>
</ul>
<h2 id="heading-needed-packages-to-install">Needed packages to install</h2>
<p><strong>duply</strong> and <strong>duplicity</strong> must both be installed to proceed. duplicity needs the python dropbox backend. On Debian systems you can install it this way:</p>
<div class="language-shell highlighter-rouge"><pre class="highlight"><code>sudo apt-get install python-pip
sudo pip install dropbox
</code></pre>
</div>
<p>Some tutorials say to use python library dropbox2 instead. But for me this led to an error while backing up.</p>
<h2 id="heading-configuration">Configuration</h2>
<p>For dropbox access in <code class="highlighter-rouge">.duply/<name>/conf</code> you only need the following lines:</p>
<div class="language-conf highlighter-rouge"><pre class="highlight"><code><span class="n">TARGET</span>=<span class="s1">'dpbx:///<name>'</span>
<span class="n">TARGET_PASS</span>=<span class="s1">''</span>
<span class="n">export</span> <span class="n">DPBX_ACCESS_TOKEN</span>=<span class="s1">'<app-token-generated-in-dropbox>'</span>
</code></pre>
</div>
<p><code class="highlighter-rouge">TARGET</code> sets dropbox as protocol and <code class="highlighter-rouge"><name></code> is the folder in dropbox: <code class="highlighter-rouge">/Apps/duplicity/<name></code>. For Dropbox as cloud backend <code class="highlighter-rouge">TARGET_USER</code> must not be set. <code class="highlighter-rouge">TARGET_PASS</code> must be set empty. Without it <em>duply</em> will not run. <code class="highlighter-rouge">DPBX_ACCESS_TOKEN</code> must contain a valid dropbox access token for a Dropbox App. This parameter must be exported because duplicity not for duply and duplicity reads it that way.</p>
<p>The config file must of course contain the other parameters used by <em>duply</em> like <code class="highlighter-rouge">PGP_PW</code> , <code class="highlighter-rouge">SOURCE</code> as for any other backup cloud backend as well. And as for any other backup cloud backend I strongly recommend to <strong>only load up encrypted backup files.</strong>
Create a new <a href="https://www.dropbox.com/developers/apps">Dropbox App</a> using <em>Dropbox API</em> and an <em>App folder</em>. The <em>App name</em> you chose is the name of the dropbox folder under <code class="highlighter-rouge">/Apps</code>. After you created your app <em>generate</em> your <em>access token</em> and paste it to your <em>duply</em> config file and replace <code class="highlighter-rouge"><app-token-generated-in-dropbox></code>.
Now <em>duply</em> can access Dropbox via duplicity with your created dropbox access token.</p>
<h2 id="heading-help-with-possible-errors">Help with possible Errors</h2>
<h3 id="heading-error-dpbx-error-404-upath-name-not-found">Error: dpbx error: [404] u"Path '<name>' not found"</h3>
<p>You are using the <code class="highlighter-rouge"><name></code> in your <em>duply</em> configuration within the <code class="highlighter-rouge">TARGET</code> parameter but the Dropbox folder <code class="highlighter-rouge">/App/duplicity/<name></code> is missing. Just add it.</p>
<h3 id="heading-error-backendexception-could-not-initialize-backend-no-module-named-dropbox">Error: BackendException: Could not initialize backend: No module named dropbox</h3>
<p>The <em>dropbox</em> python library is missing. Try</p>
<div class="language-shell highlighter-rouge"><pre class="highlight"><code>pip install dropbox
</code></pre>
</div>
<h3 id="heading-error-dpbx-error-200-error-parsing-response-body-or-headers-body---x8crx0-">Error: dpbx error: [200] 'Error parsing response body or headers: Body - x8crx0 …</h3>
<p>The problem did not occur with the first backup but with the following ones if I was using <code class="highlighter-rouge">dropbox2</code> python library instead of <code class="highlighter-rouge">dropbox</code>.</p>
<div class="language-shell highlighter-rouge"><pre class="highlight"><code>pip uninstall dropbox2
pip install dropbox
</code></pre>
</div>
<h3 id="heading-dpbx-error-400-uv1_retired">dpbx error: [400] u'v1_retired'</h3>
<p>Since the End of September 2017 Dropbox retired their API v1. So you have to update your python dropbox client.</p>
<div class="highlighter-rouge"><pre class="highlight"><code>pip search dropbox
# Output:
# dropbox (8.4.0) - Official Dropbox API Client
# INSTALLED: 6.9.0
# LATEST: 8.4.0
pip uninstall dropbox
pip install dropbox
</code></pre>
</div>
<h3 id="heading-backendexception-could-not-initialize-backend-cannot-import-name-client">BackendException: Could not initialize backend: cannot import name client</h3>
<p><code class="highlighter-rouge">07:25:27.701 Task 'BKP' failed with exit code '23'.</code>
This will occur if your python dropbox backend is not compatible with duplicity <code class="highlighter-rouge">dpbxbackend.py</code> under <code class="highlighter-rouge">/usr/lib/python2.7/dist-packages/duplicity/backends</code>.
For me it occured after fixing the error <em>dpbx error: [400] u'v1_retired' with updating dropbox python client.</em>
For Ubuntu 16.04 I updated duplicity to higher version from ppa source to fix it with the following commands:</p>
<div class="highlighter-rouge"><pre class="highlight"><code>apt install software-properties-common
add-apt-repository ppa:duplicity-team/ppa
apt-get update
apt-get install duplicity
</code></pre>
</div>
<h2 id="heading-help-with-possible-errors-outdated">Help with possible Errors (outdated)</h2>
<p>These are common errors with older versions of the duplicity dropbox backend that is not compatible with dropbox API v2.</p>
<h3 id="heading-error-nameerror-global-name-rest-is-not-defined">Error: NameError: global name ‘rest’ is not defined</h3>
<p>This is a known bug in the python dropbox backend script. If you have this error you can simply fix it adding the following highlighted line into the file <code class="highlighter-rouge">/usr/lib/python2.7/dist-packages/duplicity/backends/dpbxbackend.py</code> to this position. The bug description is <a href="http://bazaar.launchpad.net/~ed.so/duplicity/fix.dpbx/revision/965#duplicity/backends/dpbxbackend.py">here</a>.</p>
<div class="language-python highlighter-rouge"><pre class="highlight"><code><span class="k">def</span> <span class="nf">command</span><span class="p">(</span><span class="n">login_required</span><span class="o">=</span><span class="bp">True</span><span class="p">):</span>
<span class="s">"""a decorator for handling authentication and exceptions"""</span>
<span class="k">def</span> <span class="nf">decorate</span><span class="p">(</span><span class="n">f</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">wrapper</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">):</span>
<span class="kn">from</span> <span class="nn">dropbox</span> <span class="kn">import</span> <span class="n">rest</span>
<span class="k">if</span> <span class="n">login_required</span> <span class="ow">and</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">sess</span><span class="o">.</span><span class="n">is_linked</span><span class="p">():</span>
<span class="n">log</span><span class="o">.</span><span class="n">FatalError</span><span class="p">(</span><span class="s">"dpbx Cannot login: check your credentials"</span><span class="p">,</span><span class="n">log</span><span class="o">.</span><span class="n">ErrorCode</span><span class="o">.</span><span class="n">dpbx_nologin</span><span class="p">)</span>
<span class="k">return</span>
</code></pre>
</div>
<h3 id="heading-error-dpbx-error-400-uunauthorized">Error: dpbx error: [400] u'Unauthorized'</h3>
<p>Something went wrong with the authorization. Removing (or better moving) the file <code class="highlighter-rouge">~/.dropbox.token_store.txt</code> should help. The next time you are using <em>duply</em> you have to confirm the access of the duplicity backend in your browser again and the file will be recreated.</p>{"name"=>nil, "job_title"=>nil, "location"=>nil, "email"=>"info@devarcs.com", "social_links"=>[{"name"=>"twitter", "url"=>"https://twitter.com/ArchitectViews"}, {"name"=>"vk", "url"=>nil}]}info@devarcs.comFlush DNS cache2015-01-09T22:35:42+00:002015-01-09T22:35:42+00:00https://devarcs.com/blog/network/flush-dns-cache<h4 id="heading-windows">Windows</h4>
<p>The following command flushes the DNS cache.</p>
<div class="language-shell highlighter-rouge"><pre class="highlight"><code>IPCONFIG /FLUSHDNS
</code></pre>
</div>
<p> </p>
<h4 id="heading-mac-osx-1010-yosemite">Mac OSX 10.10 (Yosemite)</h4>
<p>The following commands flushes multicast- and unicast DNS cache.</p>
<div class="language-shell highlighter-rouge"><pre class="highlight"><code>sudo discoveryutil mdnsflushcache
sudo discoveryutil udnsflushcaches
</code></pre>
</div>
<p> </p>
<h4 id="heading-max-osx-10789-lion-mountain-lion-mavericks">Max OSX 10.7/8/9/ (Lion, Mountain Lion, Mavericks)</h4>
<p>The following command flushes the DNS cache.</p>
<div class="language-shell highlighter-rouge"><pre class="highlight"><code>sudo killall -HUP mDNSResponder
</code></pre>
</div>
<p> </p>timWindowsIntelliJ IDEA and TextExpander2014-10-26T10:17:15+00:002014-10-26T10:17:15+00:00https://devarcs.com/blog/development/tool/intellij-idea-textexpander<p><a href="http://smilesoftware.com/TextExpander/index.html">TextExpander</a> is a tool that can replace shortcuts with text snippets or even forms in any application. I for example use it to automatically close opened brackets and move the cursor between them.</p>
<p><img src="/assets/posts/2014-10-26-intellij-idea-textexpander/Screenshot-2014-10-26-11.09.53.png" alt="TextExpander Snippets grouped" title="TextExpander snippets grouped" /></p>
<p>When using<a href="https://www.jetbrains.com/idea/">IntelliJ IDEA</a>
13 I noticed that clipboard conflicts occur here. If the
clipboard is filled, <em>IDEA</em> inserts the contents of the clipboard,
as soon as I open a parentheses.</p>
<p>Since <em>IDEA</em> takes care of closing parentheses anyway there is no need te let <em>TextExpander</em> do that.
I first tried to deactivate these kinds of rules in <em>TextExpander</em> for <em>IDEA</em>. That's possible and since I have grouped my rules of all bracket types that would be a easy solution. However, <em>TextExpander</em> does not care that
I disabled <em>IDEA</em> for these rules. Only after stopping
<em>TextExpander</em>, I was able to write parentheses again. I suspect
TextExpander* cannot exclude Java programs, because they
are no real executables. Maybe I had to exclude the <code class="highlighter-rouge">java</code> binary completely. That's not what I wanted and so I didn't try it.</p>
<h3 id="heading-the-following-solution-helped-me">The following solution helped me</h3>
<p>In the IDEA properties under <code class="highlighter-rouge">/Applications/IntelliJ IDEA
13.app/Contents/bin/idea.properties</code> I added the following line:</p>
<div class="language-conf highlighter-rouge"><pre class="highlight"><code><span class="n">ide</span>.<span class="n">mac</span>.<span class="n">useNativeClipboard</span>=<span class="n">true</span>
</code></pre>
</div>
<p>The clipboard problem did not occur afterwards.</p>
<p> </p>
<h4 id="heading-source">Source</h4>
<ul>
<li><a href="https://youtrack.jetbrains.com/issue/IDEA-69480">https://youtrack.jetbrains.com/issue/IDEA-69480</a></li>
</ul>timTextExpander is a tool that can replace shortcuts with text snippets or even forms in any application. I for example use it to automatically close opened brackets and move the cursor between them.Bittorrent Sync Debian Start Script2014-10-12T09:58:28+00:002014-10-12T09:58:28+00:00https://devarcs.com/blog/operations/data/sync/bittorrent-sync-debian-start-script<p><a href="http://www.bittorrent.com/intl/de/sync">Bittorrent Sync</a> is a
Dropbox alternative for the private cloud. Files can be synced
between clients in the local network or to your own server.</p>
<p>The following start script starts or stops the <em>btsync</em> daemon
in Linux.</p>
<div class="language-shell highlighter-rouge"><pre class="highlight"><code><span class="c">#! /bin/sh</span>
<span class="c">### BEGIN INIT INFO</span>
<span class="c"># Provides: Bittorrent Sync </span>
<span class="c"># Required-Start: $local_fs $network</span>
<span class="c"># Required-Stop: $local_fs </span>
<span class="c"># Default-Start: 3 4 5</span>
<span class="c"># Default-Stop: 0 1 6</span>
<span class="c"># Short-Description: Startskript for btsync daemon.</span>
<span class="c"># Description: Starts the btsync daemon. </span>
<span class="c">### END INIT INFO</span>
<span class="c"># Author: Tim Pommerening <admin@tyranus.de></span>
<span class="c"># Do NOT "set -e"</span>
<span class="nv">DESC</span><span class="o">=</span><span class="s2">"Bittorrent Sync"</span>
<span class="nv">NAME</span><span class="o">=</span>btsync
<span class="nv">DAEMON</span><span class="o">=</span>/opt/btsync/<span class="k">${</span><span class="nv">NAME</span><span class="k">}</span>
<span class="nv">CONFIG</span><span class="o">=</span>/opt/btsync/<span class="k">${</span><span class="nv">NAME</span><span class="k">}</span>.config
<span class="nv">PIDFILE</span><span class="o">=</span>/var/run/btsync/btsync.pid
<span class="nv">SCRIPTNAME</span><span class="o">=</span>/etc/init.d/btsync
<span class="c"># Exit if the package is not installed</span>
<span class="o">[</span> -x <span class="s2">"</span><span class="nv">$DAEMON</span><span class="s2">"</span> <span class="o">]</span> <span class="o">||</span> <span class="o">(</span><span class="nb">printf</span> <span class="s2">"</span><span class="nv">$DAEMON</span><span class="s2"> not found."</span>; <span class="nb">exit </span>0<span class="o">)</span>
<span class="c"># Exit if config file is missing</span>
<span class="o">[</span> -f <span class="s2">"</span><span class="nv">$CONFIG</span><span class="s2">"</span> <span class="o">]</span> <span class="o">||</span> <span class="o">(</span><span class="nb">printf</span> <span class="s2">"</span><span class="nv">$CONFIG</span><span class="s2"> not found."</span>; <span class="nb">exit </span>0<span class="o">)</span>
<span class="c"># Read configuration variable file if it is present</span>
<span class="o">[</span> -r /etc/default/<span class="nv">$NAME</span> <span class="o">]</span> <span class="o">&&</span> . /etc/default/<span class="nv">$NAME</span>
<span class="c"># Load the VERBOSE setting and other rcS variables</span>
. /lib/init/vars.sh
<span class="c"># Define LSB log_* functions.</span>
<span class="c"># Depend on lsb-base (>= 3.0-6) to ensure that this file is present.</span>
. /lib/lsb/init-functions
<span class="c">#</span>
<span class="c"># Function that starts the daemon/service</span>
<span class="c">#</span>
do_start<span class="o">()</span>
<span class="o">{</span>
<span class="c"># Return</span>
<span class="c"># 0 if daemon has been started - proofed</span>
<span class="c"># 1 if daemon was already running - proofed</span>
<span class="c"># 2 if daemon could not be started - TODO: NOT PROOFED YET</span>
<span class="k">if</span> <span class="o">[</span> -f <span class="s2">"</span><span class="k">${</span><span class="nv">PIDFILE</span><span class="k">}</span><span class="s2">"</span> <span class="o">]</span>; <span class="k">then
</span><span class="nb">printf</span> <span class="s2">"pid file exists. Is btsync already running?</span><span class="se">\n\n</span><span class="s2">"</span>
<span class="k">return</span> <span class="s2">"1"</span>
<span class="k">fi
</span>su btsync -c <span class="s2">"</span><span class="k">${</span><span class="nv">DAEMON</span><span class="k">}</span><span class="s2"> --config </span><span class="k">${</span><span class="nv">CONFIG</span><span class="k">}</span><span class="s2"> >/dev/null"</span>
<span class="nv">RVAL</span><span class="o">=</span><span class="nv">$?</span>
<span class="k">if</span> <span class="o">[</span> <span class="s2">"x</span><span class="k">${</span><span class="nv">RVAL</span><span class="k">}</span><span class="s2">"</span> <span class="o">=</span> <span class="s2">"x0"</span> <span class="o">]</span>; <span class="k">then
</span><span class="nv">PID</span><span class="o">=</span><span class="sb">`</span>head -1 <span class="k">${</span><span class="nv">PIDFILE</span><span class="k">}</span> 2>/dev/null<span class="sb">`</span>
<span class="nb">printf</span> <span class="s2">"btsync started (pid=</span><span class="k">${</span><span class="nv">PID</span><span class="k">}</span><span class="s2">).</span><span class="se">\n\n</span><span class="s2">"</span>
<span class="k">else
</span><span class="nb">printf</span> <span class="s2">"Unable to start btsync (return code=</span><span class="k">${</span><span class="nv">RVAL</span><span class="k">}</span><span class="s2">).</span><span class="se">\n\n</span><span class="s2">"</span>
<span class="k">fi
return</span> <span class="s2">"</span><span class="k">${</span><span class="nv">RVAL</span><span class="k">}</span><span class="s2">"</span>
<span class="c"># Add code here, if necessary, that waits for the process to be ready</span>
<span class="c"># to handle requests from services started subsequently which depend</span>
<span class="c"># on this one. As a last resort, sleep for some time.</span>
<span class="o">}</span>
<span class="c">#</span>
<span class="c"># Function that stops the daemon/service</span>
<span class="c">#</span>
do_stop<span class="o">()</span>
<span class="o">{</span>
<span class="c"># Return</span>
<span class="c"># 0 if daemon has been stopped</span>
<span class="c"># 1 if daemon was already stopped</span>
<span class="c"># 2 if daemon could not be stopped</span>
<span class="c"># other if a failure occurred</span>
<span class="nv">PID</span><span class="o">=</span><span class="sb">`</span>head -1 <span class="k">${</span><span class="nv">PIDFILE</span><span class="k">}</span> 2>/dev/null<span class="sb">`</span>
<span class="nv">RVAL</span><span class="o">=</span><span class="nv">$?</span>
<span class="k">if</span> <span class="o">[</span> <span class="s2">"x</span><span class="k">${</span><span class="nv">RVAL</span><span class="k">}</span><span class="s2">"</span> <span class="o">=</span> <span class="s2">"x1"</span> <span class="o">]</span>; <span class="k">then
</span><span class="nb">printf</span> <span class="s2">"Could not find pid file. btsync is not running?</span><span class="se">\n\n</span><span class="s2">"</span>
<span class="k">return</span> <span class="s2">"</span><span class="k">${</span><span class="nv">RVAL</span><span class="k">}</span><span class="s2">"</span>
<span class="k">fi
</span><span class="nb">kill</span> -15 <span class="k">${</span><span class="nv">PID</span><span class="k">}</span>
<span class="nv">RVAL</span><span class="o">=</span><span class="nv">$?</span>
<span class="k">if</span> <span class="o">[</span> <span class="s2">"x</span><span class="k">${</span><span class="nv">RVAL</span><span class="k">}</span><span class="s2">"</span> <span class="o">=</span> <span class="s2">"x0"</span> <span class="o">]</span>; <span class="k">then
</span>su btsync -c <span class="s2">"rm </span><span class="k">${</span><span class="nv">PIDFILE</span><span class="k">}</span><span class="s2">"</span>
<span class="nb">printf</span> <span class="s2">"Stopped btsync (pid=</span><span class="k">${</span><span class="nv">PID</span><span class="k">}</span><span class="s2">) and removed pid file.</span><span class="se">\n\n</span><span class="s2">"</span>
<span class="k">else
</span><span class="nb">printf</span> <span class="s2">"Error stopping btsync (pid=</span><span class="k">${</span><span class="nv">PID</span><span class="k">}</span><span class="s2">)."</span>
<span class="k">fi
return</span> <span class="s2">"</span><span class="nv">$RVAL</span><span class="s2">"</span>
<span class="o">}</span>
<span class="c">#</span>
<span class="c"># Function that sends a SIGHUP to the daemon/service</span>
<span class="c">#</span>
do_reload<span class="o">()</span> <span class="o">{</span>
<span class="c">#</span>
<span class="c"># If the daemon can reload its configuration without</span>
<span class="c"># restarting (for example, when it is sent a SIGHUP),</span>
<span class="c"># then implement that here.</span>
<span class="c">#</span>
<span class="c"># TODO: Is btsync reloadable with HUP?</span>
<span class="k">return</span> <span class="s2">"0"</span>
<span class="o">}</span>
<span class="k">case</span> <span class="s2">"</span><span class="nv">$1</span><span class="s2">"</span> <span class="k">in
</span>start<span class="p">)</span>
<span class="o">[</span> <span class="s2">"</span><span class="nv">$VERBOSE</span><span class="s2">"</span> !<span class="o">=</span> no <span class="o">]</span> <span class="o">&&</span> log_daemon_msg <span class="s2">"Starting </span><span class="nv">$DESC</span><span class="s2">"</span> <span class="s2">"</span><span class="nv">$NAME</span><span class="s2">"</span>
do_start
<span class="k">case</span> <span class="s2">"</span><span class="nv">$?</span><span class="s2">"</span> <span class="k">in
</span>0|1<span class="p">)</span> <span class="o">[</span> <span class="s2">"</span><span class="nv">$VERBOSE</span><span class="s2">"</span> !<span class="o">=</span> no <span class="o">]</span> <span class="o">&&</span> log_end_msg 0 <span class="p">;;</span>
2<span class="p">)</span> <span class="o">[</span> <span class="s2">"</span><span class="nv">$VERBOSE</span><span class="s2">"</span> !<span class="o">=</span> no <span class="o">]</span> <span class="o">&&</span> log_end_msg 1 <span class="p">;;</span>
<span class="k">esac</span>
<span class="p">;;</span>
stop<span class="p">)</span>
<span class="o">[</span> <span class="s2">"</span><span class="nv">$VERBOSE</span><span class="s2">"</span> !<span class="o">=</span> no <span class="o">]</span> <span class="o">&&</span> log_daemon_msg <span class="s2">"Stopping </span><span class="nv">$DESC</span><span class="s2">"</span> <span class="s2">"</span><span class="nv">$NAME</span><span class="s2">"</span>
do_stop
<span class="k">case</span> <span class="s2">"</span><span class="nv">$?</span><span class="s2">"</span> <span class="k">in
</span>0|1<span class="p">)</span> <span class="o">[</span> <span class="s2">"</span><span class="nv">$VERBOSE</span><span class="s2">"</span> !<span class="o">=</span> no <span class="o">]</span> <span class="o">&&</span> log_end_msg 0 <span class="p">;;</span>
2<span class="p">)</span> <span class="o">[</span> <span class="s2">"</span><span class="nv">$VERBOSE</span><span class="s2">"</span> !<span class="o">=</span> no <span class="o">]</span> <span class="o">&&</span> log_end_msg 1 <span class="p">;;</span>
<span class="k">esac</span>
<span class="p">;;</span>
<span class="c">#reload|force-reload)</span>
<span class="c">#</span>
<span class="c"># If do_reload() is not implemented then leave this commented out</span>
<span class="c"># and leave 'force-reload' as an alias for 'restart'.</span>
<span class="c">#</span>
<span class="c">#log_daemon_msg "Reloading $DESC" "$NAME"</span>
<span class="c">#do_reload</span>
<span class="c">#log_end_msg $?</span>
<span class="c">#;;</span>
restart|force-reload<span class="p">)</span>
<span class="c">#</span>
<span class="c"># If the "reload" option is implemented then remove the</span>
<span class="c"># 'force-reload' alias</span>
<span class="c">#</span>
log_daemon_msg <span class="s2">"Restarting </span><span class="nv">$DESC</span><span class="s2">"</span> <span class="s2">"</span><span class="nv">$NAME</span><span class="s2">"</span>
do_stop
<span class="k">case</span> <span class="s2">"</span><span class="nv">$?</span><span class="s2">"</span> <span class="k">in
</span>0|1<span class="p">)</span>
do_start
<span class="k">case</span> <span class="s2">"</span><span class="nv">$?</span><span class="s2">"</span> <span class="k">in
</span>0<span class="p">)</span> log_end_msg 0 <span class="p">;;</span>
1<span class="p">)</span> log_end_msg 1 <span class="p">;;</span> <span class="c"># Old process is still running</span>
<span class="k">*</span><span class="p">)</span> log_end_msg 1 <span class="p">;;</span> <span class="c"># Failed to start</span>
<span class="k">esac</span>
<span class="p">;;</span>
<span class="k">*</span><span class="p">)</span>
<span class="c"># Failed to stop</span>
log_end_msg 1
<span class="p">;;</span>
<span class="k">esac</span>
<span class="p">;;</span>
<span class="k">*</span><span class="p">)</span>
<span class="c">#echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2</span>
<span class="nb">echo</span> <span class="s2">"Usage: </span><span class="nv">$SCRIPTNAME</span><span class="s2"> {start|stop|restart}"</span> >&2
<span class="nb">exit </span>3
<span class="p">;;</span>
<span class="k">esac</span>
:
</code></pre>
</div>
<p> </p>timBittorrent Sync is a Dropbox alternative for the private cloud. Files can be synced between clients in the local network or to your own server.Nine is right out2014-10-07T17:59:41+00:002014-10-07T17:59:41+00:00https://devarcs.com/blog/fun/nine-is-right-out<p>… or why Windows 9 is Windows 10.</p>
<p>Besides the fact that the naming of Windows versions never followed any recognizable logic outside of marketing departments there are rumors that the naming decicion at Microsoft to skip the nine has a quite banal, technical reason.</p>
<p>Rumor says that Microsoft is afraid that old programs when they check the operating system they could only check the first character in version strings to see if the operation system is Windows 95 / 98 and then make the wrong decisions on Windows 9.</p>
<div class="language-java highlighter-rouge"><pre class="highlight"><code><span class="k">if</span> <span class="o">(</span><span class="n">name</span><span class="o">.</span><span class="na">startsWith</span><span class="o">(</span><span class="s">"windows 9"</span><span class="o">))</span> <span class="o">{</span>
</code></pre>
</div>
<p>
Sources:</p>
<ul>
<li><a href="http://www.pcworld.com/article/2690724/why-windows-10-isnt-named-9-windows-95-legacy-code.html">http://www.pcworld.com/article/2690724/why-windows-10-isnt-named-9-windows-95-legacy-code.html</a></li>
<li><a href="https://issues.jenkins-ci.org/secure/attachment/18777/PlatformDetailsTask.java">https://issues.jenkins-ci.org/secure/attachment/18777/PlatformDetailsTask.java</a></li>
</ul>
<p> </p>tim… or why Windows 9 is Windows 10.Build zsh without Root access2014-10-01T10:10:42+00:002014-10-01T10:10:42+00:00https://devarcs.com/blog/development/tool/build-zsh-without-root-access<p>How you can use <em>zsh</em> as your shell even if you do not have root access on your computer.</p>
<p><em>zsh</em> needs the library <em>ncurses</em> for build time. Download the latest
versions of the <em>source tgz</em> of <code class="highlighter-rouge">zsh</code> and <code class="highlighter-rouge">ncurses</code>.
In the following example, I have used the versions <code class="highlighter-rouge">ncurses-5.9.tgz</code>
and <code class="highlighter-rouge">zsh-5.0.6.tgz</code>.</p>
<p><em>Assumption</em>: I want to install <em>zsh</em> to <code class="highlighter-rouge">~/opt/zsh-5.0.6</code>.</p>
<p>First build <em>ncurses</em> and put it into <code class="highlighter-rouge">~/opt/ncurses-5.9</code>:</p>
<div class="language-shell highlighter-rouge"><pre class="highlight"><code><span class="gp">$ </span>tar xvzf ncurses-5.9.tgz
<span class="gp">$ </span><span class="nb">cd </span>ncurses-5.9
configure --prefix<span class="o">=</span><span class="nv">$HOME</span>/opt/ncurses-5.9
make
<span class="gp">$ </span>make install
</code></pre>
</div>
<p>Then build <em>zsh</em> and put it into <code class="highlighter-rouge">~/opt/zsh-5.0.6</code>:</p>
<div class="language-shell highlighter-rouge"><pre class="highlight"><code><span class="gp">$ </span>tar xvzf zsh-5.0.6.tgz
<span class="gp">$ </span><span class="nb">cd </span>zsh-5.0.6
<span class="gp">$ </span><span class="nv">CPPFLAGS</span><span class="o">=</span><span class="s2">"-I</span><span class="nv">$HOME</span><span class="s2">/opt/ncurses-5.9/include"</span> <span class="nv">LDFLAGS</span><span class="o">=</span><span class="s2">"-L</span><span class="nv">$HOME</span><span class="s2">/opt/ncurses-5.9/lib"</span>
<span class="nv">$.</span>/configure --prefix<span class="o">=</span><span class="nv">$HOME</span>/opt/zsh-5.0.6
make
<span class="gp">$ </span>make install
</code></pre>
</div>
<p> </p>timHow you can use zsh as your shell even if you do not have root access on your computer.