bash3boilerplate/index.html
2020-06-08 08:28:42 +00:00

249 lines
15 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>BASH3 Boilerplate Template for writing better Bash scripts</title>
<meta name="keywords" content="bash, template, scripting, command-line">
<meta name="description" content="BASH3 Boilerplate">
<link href='https://fonts.googleapis.com/css?family=Open+Sans:400,300,600,700' rel='stylesheet' type='text/css'>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link rel="stylesheet" href="/assets/build/app.a6d50511e193d4224561.css" media="screen" charset="utf-8">
</head>
<body>
<header>
<div id="header-overlay"></div>
<a href="/">
<span id="logo"></span>
</a>
<div id="menu">
<i class="material-icons">menu</i>
<ul id="menu-items">
</ul>
</div>
<span id="more">
<i class="material-icons">expand_more</i>
</span>
</header>
<section id="content">
<div class="Social">
<iframe src="http://ghbtns.com/github-btn.html?user=kvz&repo=bash3boilerplate&type=watch&count=true" allowtransparency="true" frameborder="0" scrolling="0" width="100" height="20"></iframe>
<a href="https://travis-ci.org/kvz/bash3boilerplate"><img src="https://travis-ci.org/kvz/bash3boilerplate.svg" alt="Build Status"></a>
</div>
<p>When hacking up Bash scripts, there are often things such as logging or command-line argument parsing that:</p>
<ul>
<li>You need every time</li>
<li>Come with a number of pitfalls you want to avoid</li>
<li>Keep you from your actual work</li>
</ul>
<p>Heres an attempt to bundle those things in a generalized way so that
they are reusable as-is in most scripts.</p>
<p>We call it “BASH3 Boilerplate” or b3bp for short.</p>
<h2 id="goals">Goals</h2>
<p>Delete-Key-<strong>Friendly</strong>. Instead of introducing packages, includes, compilers, etc., we propose using <a href="http://bash3boilerplate.sh/main.sh"><code class="highlighter-rouge">main.sh</code></a> as a base and removing the parts you dont need.
While this may feel a bit archaic at first, it is exactly the strength of Bash scripts that we should want to embrace.</p>
<p><strong>Portable</strong>. We are targeting Bash 3 (OSX still ships
with 3, for instance). If you are going to ask people to install
Bash 4 first, you might as well pick a more advanced language as a
dependency.</p>
<h2 id="features">Features</h2>
<ul>
<li>Conventions that will make sure that all your scripts follow the same, battle-tested structure</li>
<li>Safe by default (break on error, pipefail, etc.)</li>
<li>Configuration by environment variables</li>
<li>Simple command-line argument parsing that requires no external dependencies. Definitions are parsed from help info, ensuring there will be no duplication</li>
<li>Helpful magic variables like <code class="highlighter-rouge">__file</code> and <code class="highlighter-rouge">__dir</code></li>
<li>Logging that supports colors and is compatible with <a href="http://en.wikipedia.org/wiki/Syslog#Severity_levels">Syslog Severity levels</a>, as well as the <a href="http://12factor.net/">twelve-factor</a> guidelines</li>
</ul>
<h2 id="installation">Installation</h2>
<p>There are three different ways to install b3bp:</p>
<h3 id="option-1-download-the-main-template">Option 1: Download the main template</h3>
<p>Use curl or wget to download the source and save it as your script. Then you can start deleting the unwanted bits, and adding your own logic.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>wget http://bash3boilerplate.sh/main.sh
vim main.sh
</code></pre></div></div>
<h3 id="option-2-clone-the-entire-project">Option 2: Clone the entire project</h3>
<p>Besides <code class="highlighter-rouge">main.sh</code>, this will also get you the entire b3bp repository. This includes a few extra functions that we keep in the <code class="highlighter-rouge">./src</code> directory.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git clone git@github.com:kvz/bash3boilerplate.git
</code></pre></div></div>
<h3 id="option-3-require-via-npm">Option 3: Require via npm</h3>
<p>As of <code class="highlighter-rouge">v1.0.3</code>, b3bp can also be installed as a Node module, meaning you can define it as a dependency in <code class="highlighter-rouge">package.json</code> via:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>npm init
npm <span class="nb">install</span> <span class="nt">--save</span> <span class="nt">--save-exact</span> bash3boilerplate
</code></pre></div></div>
<p>Even though this option introduces a Node.js dependency, it does allow for easy version pinning and distribution in environments that already have this prerequisite. This is, however, entirely optional and nothing prevents you from ignoring this possibility.</p>
<h2 id="changelog">Changelog</h2>
<p>Please see the <a href="./CHANGELOG.md">CHANGELOG.md</a> file.</p>
<h2 id="frequently-asked-questions">Frequently Asked Questions</h2>
<p>Please see the <a href="./FAQ.md">FAQ.md</a> file.</p>
<h2 id="best-practices">Best practices</h2>
<p>As of <code class="highlighter-rouge">v1.0.3</code>, b3bp offers some nice re-usable libraries in <code class="highlighter-rouge">./src</code>. In order to make the snippets in <code class="highlighter-rouge">./src</code> more useful, we recommend the following guidelines.</p>
<h3 id="function-packaging">Function packaging</h3>
<p>It is nice to have a Bash package that can not only be used in the terminal, but also invoked as a command line function. In order to achieve this, the exporting of your functionality <em>should</em> follow this pattern:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="o">[[</span> <span class="s2">"</span><span class="k">${</span><span class="nv">BASH_SOURCE</span><span class="p">[0]</span><span class="k">}</span><span class="s2">"</span> <span class="o">=</span> <span class="s2">"</span><span class="k">${</span><span class="nv">0</span><span class="k">}</span><span class="s2">"</span> <span class="o">]]</span><span class="p">;</span> <span class="k">then
</span>my_script <span class="s2">"</span><span class="k">${</span><span class="p">@</span><span class="k">}</span><span class="s2">"</span>
<span class="nb">exit</span> <span class="nv">$?</span>
<span class="k">fi
</span><span class="nb">export</span> <span class="nt">-f</span> my_script
</code></pre></div></div>
<p>This allows a user to <code class="highlighter-rouge">source</code> your script or invoke it as a script.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Running as a script</span>
<span class="nv">$ </span>./my_script.sh some args <span class="nt">--blah</span>
<span class="c"># Sourcing the script</span>
<span class="nv">$ </span><span class="nb">source </span>my_script.sh
<span class="nv">$ </span>my_script some more args <span class="nt">--blah</span>
</code></pre></div></div>
<p>(taken from the <a href="https://raw.githubusercontent.com/bpkg/bpkg/master/README.md">bpkg</a> project)</p>
<h3 id="scoping">Scoping</h3>
<ol>
<li>In functions, use <code class="highlighter-rouge">local</code> before every variable declaration.</li>
<li>Use <code class="highlighter-rouge">UPPERCASE_VARS</code> to indicate environment variables that can be controlled outside your script.</li>
<li>Use <code class="highlighter-rouge">__double_underscore_prefixed_vars</code> to indicate global variables that are solely controlled inside your script, with the exception of arguments that are already prefixed with <code class="highlighter-rouge">arg_</code>, as well as functions, over which b3bp poses no restrictions.</li>
</ol>
<h3 id="coding-style">Coding style</h3>
<ol>
<li>Use two spaces for tabs, do not use tab characters.</li>
<li>Do not introduce whitespace at the end of lines or on blank lines as they obfuscate version control diffs.</li>
<li>Use long options (<code class="highlighter-rouge">logger --priority</code> vs <code class="highlighter-rouge">logger -p</code>). If you are on the CLI, abbreviations make sense for efficiency. Nevertheless, when you are writing reusable scripts, a few extra keystrokes will pay off in readability and avoid ventures into man pages in the future, either by you or your collaborators. Similarly, we prefer <code class="highlighter-rouge">set -o nounset</code> over <code class="highlighter-rouge">set -u</code>.</li>
<li>Use a single equal sign when checking <code class="highlighter-rouge">if [[ "${NAME}" = "Kevin" ]]</code>; double or triple signs are not needed.</li>
<li>Use the new bash builtin test operator (<code class="highlighter-rouge">[[ ... ]]</code>) rather than the old single square bracket test operator or explicit call to <code class="highlighter-rouge">test</code>.</li>
</ol>
<h3 id="safety-and-portability">Safety and Portability</h3>
<ol>
<li>Use <code class="highlighter-rouge">{}</code> to enclose your variables. Otherwise, Bash will try to access the <code class="highlighter-rouge">$ENVIRONMENT_app</code> variable in <code class="highlighter-rouge">/srv/$ENVIRONMENT_app</code>, whereas you probably intended <code class="highlighter-rouge">/srv/${ENVIRONMENT}_app</code>. Since it is easy to miss cases like this, we recommend that you make enclosing a habit.</li>
<li>Use <code class="highlighter-rouge">set</code>, rather than relying on a shebang like <code class="highlighter-rouge"><span class="c">#!/usr/bin/env bash -e</span></code>, since that is neutralized when someone runs your script as <code class="highlighter-rouge">bash yourscript.sh</code>.</li>
<li>Use <code class="highlighter-rouge"><span class="c">#!/usr/bin/env bash</span></code>, as it is more portable than <code class="highlighter-rouge"><span class="c">#!/bin/bash</span></code>.</li>
<li>Use <code class="highlighter-rouge">${BASH_SOURCE[0]}</code> if you refer to current file, even if it is sourced by a parent script. In other cases, use <code class="highlighter-rouge">${0}</code>.</li>
<li>Use <code class="highlighter-rouge">:-</code> if you want to test variables that could be undeclared. For instance, with <code class="highlighter-rouge">if [[ "${NAME:-}" = "Kevin" ]]</code>, <code class="highlighter-rouge">$NAME</code> will evaluate to <code class="highlighter-rouge">Kevin</code> if the variable is empty. The variable itself will remain unchanged. The syntax to assign a default value is <code class="highlighter-rouge">${NAME:=Kevin}</code>.</li>
</ol>
<h2 id="who-uses-b3bp">Who uses b3bp?</h2>
<ul>
<li><a href="https://transloadit.com">Transloadit</a></li>
<li><a href="http://www.opencoarrays.org">OpenCoarrays</a></li>
<li><a href="http://www.sourceryinstitute.org">Sourcery Institute</a></li>
<li><a href="http://cobralab.ca/">Computational Brain Anatomy Laboratory</a></li>
<li><a href="https://genesiscloud.com/">Genesis Cloud</a></li>
</ul>
<p>We are looking for endorsements! Are you also using b3bp? <a href="https://github.com/kvz/bash3boilerplate/issues/new?title=I%20use%20b3bp">Let us know</a> and get listed.</p>
<h2 id="authors">Authors</h2>
<ul>
<li><a href="http://kvz.io">Kevin van Zonneveld</a></li>
<li><a href="https://izaakbeekman.com/">Izaak Beekman</a></li>
<li><a href="https://github.com/mstreuhofer">Manuel Streuhofer</a></li>
<li><a href="mailto:Alexander.Rathai@gmail.com">Alexander Rathai</a></li>
<li><a href="http://www.sourceryinstitute.org/">Dr. Damian Rouson</a> (documentation, feedback)</li>
<li><a href="https://github.com/jokajak">@jokajak</a> (documentation)</li>
<li><a href="http://staticwave.ca/">Gabriel A. Devenyi</a> (feedback)</li>
<li><a href="https://github.com/bravo-kernel">@bravo-kernel</a> (feedback)</li>
<li><a href="https://github.com/skanga">@skanga</a> (feedback)</li>
<li><a href="https://www.reddit.com/user/galaktos">galaktos</a> (feedback)</li>
<li><a href="https://github.com/moviuro">@moviuro</a> (feedback)</li>
<li><a href="https://github.com/gsaponaro">Giovanni Saponaro</a> (feedback)</li>
<li><a href="https://github.com/gmasse">Germain Masse</a></li>
<li><a href="https://github.com/warpengineer">A. G. Madi</a></li>
<li><a href="mailto:oss@genesiscloud.com">Lukas Stockner</a></li>
<li><a href="https://github.com/eval">Gert Goet</a></li>
<li><a href="https://github.com/rfuehrer">@rfuehrer</a></li>
</ul>
<h2 id="license">License</h2>
<p>Copyright (c) 2013 Kevin van Zonneveld and <a href="https://github.com/kvz/bash3boilerplate#authors">contributors</a>.
Licensed under <a href="https://raw.githubusercontent.com/kvz/bash3boilerplate/master/LICENSE">MIT</a>.
You are not obligated to bundle the LICENSE file with your b3bp projects as long
as you leave these references intact in the header comments of your source files.</p>
<h2 id="activity-feed">On GitHub</h2>
<p>
BASH3 Boilerplate is a friendly group of folks further developing our
re-usable templates as we go.
We'd love to hear what you think <a href="https://github.com/kvz/bash3boilerplate">on GitHub</a>.
Here's what's been going on recently.
</p>
<div class="on-the-githubs" data-event-source="repos/kvz/bash3boilerplate">Loading...</div>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="//kvz.github.io/on-the-githubs/js/jquery.on-the-githubs.min.js"></script>
<script type="text/javascript">
$('.on-the-githubs').onthegithubs();
</script>
<div class="Social">
<iframe src="http://ghbtns.com/github-btn.html?user=kvz&repo=bash3boilerplate&type=watch&count=true" allowtransparency="true" frameborder="0" scrolling="0" width="100" height="20"></iframe>
</div>
<p>
<small>
<hr />
Website design based on
the wonderful <a href="http://apex.run">apex.run</a>
with <a href="https://twitter.com/tjholowaychuk/status/744909762865696769">the author's consent</a>.
</small>
</p>
</section>
</body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.1.0/highlight.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.1.0/languages/bash.min.js"></script>
<script async src="/assets/build/app.a6d50511e193d4224561.js"></script>
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-63083-13', 'auto');
ga('send', 'pageview');
</script>
</html>