summaryrefslogtreecommitdiff
path: root/stupid_templating_with_shell_cat_and_envsubst.html
diff options
context:
space:
mode:
Diffstat (limited to 'stupid_templating_with_shell_cat_and_envsubst.html')
-rw-r--r--stupid_templating_with_shell_cat_and_envsubst.html72
1 files changed, 72 insertions, 0 deletions
diff --git a/stupid_templating_with_shell_cat_and_envsubst.html b/stupid_templating_with_shell_cat_and_envsubst.html
new file mode 100644
index 0000000..7a84554
--- /dev/null
+++ b/stupid_templating_with_shell_cat_and_envsubst.html
@@ -0,0 +1,72 @@
+<!doctype html>
+<html lang="en">
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1">
+<meta name="author" content="aki">
+<meta name="tags" content="template, bash, cat, shell, envsubst">
+<link rel="icon" type="image/png" href="cylo.png">
+<link rel="stylesheet" type="text/css" href="style.css">
+
+<title>Stupid Templating With Shell, cat and envsubst</title>
+
+<nav><p><a href="https://ignore.pl">ignore.pl</a></p></nav>
+
+<article>
+<h1>Stupid Templating With Shell, cat and envsubst</h1>
+<p class="subtitle">Published on 2020-07-14 20:26:00+02:00
+<p>Now something trivial and fun. Creating templates of documents or configurations in shell. There are two reasons why
+I considered doing that instead of using some more verbose utilities. First off, availability - I have POSIX compliant
+shell pretty much everywhere I go. It's a big part of my usual environment and because of that I'm used to it. That's
+the second reason - frequency I use it with. It's good to mention that it's one of more verbose utilities out there.
+<p>Let's start with plain shell. I actually use this method to serve the blog posts via fcgiwrap. I use it with a single
+file, but it can accept external files. However those files won't have their content expanded in any way. If you keep it
+in a one script file then it's possible. Basically, I'm talking about <code>cat</code>:</p>
+<pre>
+#!/bin/sh
+cat /dev/fd/3 $@ /dev/fd/4 3&lt;&lt;BEFORE 4&lt;&lt;AFTER
+&lt;!doctype html&gt;
+&lt;html lang="en"&gt;
+BEFORE
+&lt;script src=""&gt;&lt;/script&gt;
+AFTER
+</pre>
+<img src="stupid_templating_with_shell_cat_and_envsubst-1.png" alt="actual cat">
+<p>What you see here is a combination of
+<a href="https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_07_04">heredoc</a> and plain
+redirection. It's done like this to avoid calling <code>cat</code> more than once. The script simply concatenates BEFORE
+heredoc with any arguments passed to the script, and finally with AFTER heredoc. The output is similar to what you see
+in source of this page. The template is trimmed for the sake of the example.
+<p>Now, now. Heredoc can easily expand variables but if we were to <code>cat before.inl $@ after.inl</code> it wouldn't
+work. For that I use
+<code><a href="https://www.gnu.org/software/gettext/manual/html_node/envsubst-Invocation.html">envsubst</a></code>.
+Consider file called <i>template.conf</i>:
+<pre>
+server {
+ listen 80;
+ server_name $DOMAIN$ALIASES;
+ root /srv/http/$DOMAIN/public;
+}
+</pre>
+<p>It could be wrapped in cat and heredoc, but for me it's not desired. Let's say I want my configuration templates to
+be exactly that not executable scripts. There are three different solutions that I've heard: <code>eval</code>,
+<code>sed</code> and <code>envsubst</code>. <code>Eval</code> can lead to dangerous situations and minor problems with
+whitespace. <code>Sed</code> is what I believe is the most typical and straight-forward solution. As for the last one,
+it goes like this:</p>
+<pre>
+$ export DOMAIN=example.tld
+$ export ALIASES=' www.example.tld'
+$ envsubst '$DOMAIN$ALIASES' &lt;template.conf
+server {
+ listen 80;
+ server_name example.tld www.example.tld;
+ root /srv/http/example.tld/public;
+}
+</pre>
+<p>First, you set the variables (if they are not yet there). Then call the <code>envsubst</code> with a single variable
+and redirect the template file into it. This single variable is called <em>SHELL-FORMAT</em>. It restricts the variables
+that will be substituted in the input. It's completely optional, but if you have some <code>$server_name</code> you
+don't want to substitute, then it's kind of useful. It actually doesn't have any format, you just need to reference the
+variables in it: <code>'$DOMAIN$ALIASES'</code>, <code>'$DOMAIN $ALIASES'</code>, and <code>'$DOMAIN,$ALIASES'</code>
+all work the same.
+</article>
+<script src="https://stats.ignore.pl/track.js"></script>