From 5b2deaa0e51468a04a3c7c72ad8e5181a8e804e2 Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Sun, 28 May 2023 00:01:27 +0300 Subject: Update content for html --- gemfeed/2008-06-26-perl-poetry.html | 18 +- ...12-29-using-my-nokia-n95-for-fixing-my-mta.html | 2 +- ...010-05-07-lazy-evaluation-with-standarn-ml.html | 2 +- .../2010-05-09-the-fype-programming-language.html | 18 +- .../2011-05-07-perl-daemon-service-framework.html | 10 +- .../2014-03-24-the-fibonacci.pl.c-polyglot.html | 6 +- ...2-05-run-debian-on-your-phone-with-debroid.html | 2 +- gemfeed/2016-04-03-offsite-backup-with-zfs.html | 2 +- ...04-09-jails-and-zfs-on-freebsd-with-puppet.html | 78 +- ...inning-up-my-own-authoritative-dns-servers.html | 36 +- ...20-object-oriented-programming-with-ansi-c.html | 12 +- ...alistic-load-testing-with-ioriot-for-linux.html | 10 +- gemfeed/2021-04-24-welcome-to-the-geminispace.html | 28 +- ...021-05-16-personal-bash-coding-style-guide.html | 60 +- ...5-gemtexter-one-bash-script-to-rule-it-all.html | 60 +- gemfeed/2021-07-04-the-well-grounded-rubyist.html | 38 +- ...-08-01-on-being-pedantic-about-open-source.html | 64 +- gemfeed/2021-09-12-keep-it-simple-and-stupid.html | 28 +- gemfeed/2021-10-22-defensive-devops.html | 34 +- gemfeed/2021-11-29-bash-golf-part-1.html | 62 +- ...-12-26-how-to-stay-sane-as-a-devops-person.html | 50 +- gemfeed/2022-01-01-bash-golf-part-2.html | 90 +- gemfeed/2022-01-23-welcome-to-the-foo.zone.html | 16 +- ...022-02-04-computer-operating-systems-i-use.html | 50 +- gemfeed/2022-03-06-the-release-of-dtail-4.0.0.html | 38 +- gemfeed/2022-04-10-creative-universe.html | 46 +- .../2022-05-27-perl-is-still-a-great-choice.html | 50 +- gemfeed/2022-06-15-sweating-the-small-stuff.html | 66 +- ...22-07-30-lets-encrypt-with-openbsd-and-rex.html | 208 +- ...2-08-27-gemtexter-1.1.0-lets-gemtext-again.html | 24 +- gemfeed/2022-09-30-after-a-bad-nights-sleep.html | 50 +- .../2022-10-30-installing-dtail-on-openbsd.html | 108 +- ...-tried-emacs-but-i-switched-back-to-neovim.html | 40 +- ...22-12-24-ultrarelearning-java-my-takeaways.html | 42 +- gemfeed/2023-01-23-why-grapheneos-rox.html | 66 +- .../2023-02-26-how-to-shut-down-after-work.html | 22 +- ...-03-16-the-pragmatic-programmer-book-notes.html | 28 +- ...03-25-gemtexter-2.0.0-lets-gemtext-again-2.html | 10 +- ...4-01-never-split-the-difference-book-notes.html | 46 +- ...ithms-and-data-structures-in-golang-part-1.html | 8 +- ...iling-guprecords:-uptime-records-with-raku.html | 20 +- ...3-05-06-the-obstacle-is-the-way-book-notes.html | 36 +- .../DRAFT-kiss-server-monitoring-with-gogios.html | 26 +- gemfeed/atom.xml | 8151 -------------------- gemfeed/index.html | 14 +- 45 files changed, 862 insertions(+), 9013 deletions(-) delete mode 100644 gemfeed/atom.xml (limited to 'gemfeed') diff --git a/gemfeed/2008-06-26-perl-poetry.html b/gemfeed/2008-06-26-perl-poetry.html index d36cb205..ef395f4b 100644 --- a/gemfeed/2008-06-26-perl-poetry.html +++ b/gemfeed/2008-06-26-perl-poetry.html @@ -13,19 +13,19 @@ Published at 2008-06-26T21:43:51+01:00; Updated at 2021-05-04

- '\|/'                                  *
+ '\|/'                                  *
 -- * -----
   /|\      ____
- ' | '    {_   o^>       *
+ ' | '    {_   o^>       *
    :        -_  /)
-   :         (   (        .-''`'.
+   :         (   (        .-''`'.
    .          \   \      /       \
    .           \    \   /         \
-                \    `-'           `'.
-                 \    . '        /    `.
-                  \  ( \  )     (     .')
-   ,,   t          '. |  /       |     (
-  '|``_/^\___        '|  |`'-..-'|   ( ()
+                \    `-'           `'.
+                 \    . '        /    `.
+                  \  ( \  )     (     .')
+   ,,   t          '. |  /       |     (
+  '|``_/^\___        '|  |`'-..-'|   ( ()
 _~~|~/_|_|__/|~~~~~~~ |  / ~~~~~ |   | ~~~~~~~~
  -_  |L[|]L|/         | |\ MJP   )   )
                       ( |(       /  /|
@@ -35,7 +35,7 @@ _~~|~/_|_|__/|~~~~~~~ |  / ~~~~~ |   | ~~~~~~~~
                     (__)         (____)
 

-Here are some Perl Poems I wrote. They don't do anything useful when you run them, but they don't produce a compiler error either. They only exist for fun and demonstrate what you can do with Perl syntax.
+Here are some Perl Poems I wrote. They don't do anything useful when you run them, but they don't produce a compiler error either. They only exist for fun and demonstrate what you can do with Perl syntax.

Wikipedia: "Perl poetry is the practice of writing poems that can be compiled as legal Perl code, for example the piece known as Black Perl. Perl poetry is made possible by the large number of English words that are used in the Perl language. New poems are regularly submitted to the community at PerlMonks."

diff --git a/gemfeed/2008-12-29-using-my-nokia-n95-for-fixing-my-mta.html b/gemfeed/2008-12-29-using-my-nokia-n95-for-fixing-my-mta.html index 6a4a2e58..500d03ea 100644 --- a/gemfeed/2008-12-29-using-my-nokia-n95-for-fixing-my-mta.html +++ b/gemfeed/2008-12-29-using-my-nokia-n95-for-fixing-my-mta.html @@ -28,7 +28,7 @@ _jgs_\|//_\\|///_\V/_\|//__ Art by Joan Stark
-The last week I was in Vidin, Bulgaria with no internet access and I had to fix my MTA (Postfix) at host.0.buetow.org which serves E-Mail for all my customers at P. B. Labs. Good, that I do not guarantee high availability on my web services (I've to do a full time job somewhere else too).
+The last week I was in Vidin, Bulgaria with no internet access and I had to fix my MTA (Postfix) at host.0.buetow.org which serves E-Mail for all my customers at P. B. Labs. Good, that I do not guarantee high availability on my web services (I've to do a full time job somewhere else too).

My first attempt to find an internet café, which was working during Christmastime, failed. However, I found with my N95 phone lots of free WLAN hotspots. The hotspots refused me logging into my server using SSH as I have configured a non-standard port for SSH for security reasons. Without knowing the costs, I used the GPRS internet access of my German phone provider (yes, I had to pay roaming fees).

diff --git a/gemfeed/2010-05-07-lazy-evaluation-with-standarn-ml.html b/gemfeed/2010-05-07-lazy-evaluation-with-standarn-ml.html index 666db775..d92309d4 100644 --- a/gemfeed/2010-05-07-lazy-evaluation-with-standarn-ml.html +++ b/gemfeed/2010-05-07-lazy-evaluation-with-standarn-ml.html @@ -20,7 +20,7 @@ _- | ) / |--| | | __-_______________ /__/_______| |_________ ( |---- | | - `---------------'--\\\\ .`--' -Glyde- + `---------------'--\\\\ .`--' -Glyde- `||||
diff --git a/gemfeed/2010-05-09-the-fype-programming-language.html b/gemfeed/2010-05-09-the-fype-programming-language.html index 0a76ac6e..227081df 100644 --- a/gemfeed/2010-05-09-the-fype-programming-language.html +++ b/gemfeed/2010-05-09-the-fype-programming-language.html @@ -15,7 +15,7 @@
       ____                                      _        __       
      / / _|_   _ _ __   ___    _   _  ___  __ _| |__    / _|_   _ 
-    / / |_| | | | '_ \ / _ \  | | | |/ _ \/ _` | '_ \  | |_| | | |
+    / / |_| | | | '_ \ / _ \  | | | |/ _ \/ _` | '_ \  | |_| | | |
  _ / /|  _| |_| | |_) |  __/  | |_| |  __/ (_| | | | |_|  _| |_| |
 (_)_/ |_|  \__, | .__/ \___|   \__, |\___|\__,_|_| |_(_)_|  \__, |
            |___/|_|            |___/                        |___/ 
@@ -25,7 +25,7 @@
 
The Fype syntax is straightforward and uses a maximum look ahead of 1 and an effortless top-down parsing mechanism. Fype is parsing and interpreting its code simultaneously. This means that syntax errors are only detected during program runtime.

-Fype is a recursive acronym and means "Fype is For Your Program Execution" or "Fype is Free Yak Programmed for ELF". You could also say, "It's not a hype - it's Fype!".
+Fype is a recursive acronym and means "Fype is For Your Program Execution" or "Fype is Free Yak Programmed for ELF". You could also say, "It's not a hype - it's Fype!".

Object-oriented C style



@@ -102,7 +102,7 @@ http://www.gnu.org/software/src-highlite -->

Data types



-Fype uses auto type conversion. However, if you want to know what's going on, you may take a look at the following basic data types:
+Fype uses auto type conversion. However, if you want to know what's going on, you may take a look at the following basic data types:

There is no boolean type, but we can use the integer values 0 for false and 1 for true. There is support for explicit type casting too.

@@ -122,7 +122,7 @@ http://www.gnu.org/software/src-highlite -->

Variables



-Variables are defined with the "my" keyword (inspired by Perl :-). If you don't assign a value during declaration, it uses the default integer value 0. Variables may be changed during program runtime. Variables may be deleted using the "undef" keyword! Example:
+Variables are defined with the "my" keyword (inspired by Perl :-). If you don't assign a value during declaration, it uses the default integer value 0. Variables may be changed during program runtime. Variables may be deleted using the "undef" keyword! Example:

 my foo = 1 + 2;
@@ -164,7 +164,7 @@ foo = "bar";
 assert "bar" == bar;
 

-Synonyms can be used for all kind of identifiers. It's not limited to standard variables but can also be used for function and procedure names (more about functions and procedures later).
+Synonyms can be used for all kind of identifiers. It's not limited to standard variables but can also be used for function and procedure names (more about functions and procedures later).

 # Create a new procedure baz
@@ -419,7 +419,7 @@ if pid {
 

Procedures



-A procedure can be defined with the "proc" keyword and deleted with the "undef" keyword. A procedure does not return any value and does not support parameter passing. It's using already defined variables (e.g. global variables). A procedure does not have its own namespace. It's using the calling namespace. It is possible to define new variables inside of a procedure in the current namespace.
+A procedure can be defined with the "proc" keyword and deleted with the "undef" keyword. A procedure does not return any value and does not support parameter passing. It's using already defined variables (e.g. global variables). A procedure does not have its own namespace. It's using the calling namespace. It is possible to define new variables inside of a procedure in the current namespace.

 proc foo {
@@ -435,7 +435,7 @@ say c; # Print out "6\n";
 

Nested procedures



-It's possible to define procedures inside of procedures. Since procedures don't have their own scope, nested procedures will be available to the current scope as soon as the main procedure has run the first time. You may use the "defined" keyword to check if a procedure has been defined or not.
+It's possible to define procedures inside of procedures. Since procedures don't have their own scope, nested procedures will be available to the current scope as soon as the main procedure has run the first time. You may use the "defined" keyword to check if a procedure has been defined or not.

 proc foo {
@@ -458,7 +458,7 @@ foo; # Here the procedure foo will redefine bar again!
 

Functions



-A function can be defined with the "func" keyword and deleted with the "undef" keyword. Function do not yet return values and do not yet supports parameter passing. It's using local (lexical scoped) variables. If a certain variable does not exist, when It's using already defined variables (e.g. one scope above).
+A function can be defined with the "func" keyword and deleted with the "undef" keyword. Function do not yet return values and do not yet supports parameter passing. It's using local (lexical scoped) variables. If a certain variable does not exist, when It's using already defined variables (e.g. one scope above).

 func foo {
diff --git a/gemfeed/2011-05-07-perl-daemon-service-framework.html b/gemfeed/2011-05-07-perl-daemon-service-framework.html
index 7fef9c30..5c41d0b2 100644
--- a/gemfeed/2011-05-07-perl-daemon-service-framework.html
+++ b/gemfeed/2011-05-07-perl-daemon-service-framework.html
@@ -13,9 +13,9 @@
 Published at 2011-05-07T22:26:02+01:00; Updated at 2021-05-07

-   a'!   _,,_ a'!   _,,_     a'!   _,,_
+   a'!   _,,_ a'!   _,,_     a'!   _,,_
      \\_/    \  \\_/    \      \\_/    \.-,
-      \, /-( /'-,\, /-( /'-,    \, /-( /
+      \, /-( /'-,\, /-( /'-,    \, /-( /
       //\ //\\   //\ //\\       //\ //\\jrei
 

@@ -89,7 +89,7 @@ daemon.wd./bin/perldaemon restart (or shortcurt ./control restart)

-Now watch ./log/perldaemon.log closely. It is a good practice to test your modules in 'foreground mode' (see above how to do that).
+Now watch ./log/perldaemon.log closely. It is a good practice to test your modules in 'foreground mode' (see above how to do that).

BTW: You can install as many modules within the same instance as desired. But they are run in sequential order (in future, they can also run in parallel using several threads or processes).

diff --git a/gemfeed/2014-03-24-the-fibonacci.pl.c-polyglot.html b/gemfeed/2014-03-24-the-fibonacci.pl.c-polyglot.html index 59b3298a..93752d88 100644 --- a/gemfeed/2014-03-24-the-fibonacci.pl.c-polyglot.html +++ b/gemfeed/2014-03-24-the-fibonacci.pl.c-polyglot.html @@ -71,7 +71,7 @@ BEGIN {
https://codeberg.org/snonux/perl-c-fibonacci

-

Let's run it with C and C++


+

Let's run it with C and C++



printf("%s(%f, %f) => %f\n", div.name, a, b, div.calculate(a,b));

-However, that's just syntactic sugar for:
+However, that's just syntactic sugar for:


https://lwn.net/Articles/444910/

-C is a very old programming language with it's quirks. This might be one of the reasons why Linux will also let Rust code in.
+C is a very old programming language with it's quirks. This might be one of the reasons why Linux will also let Rust code in.

E-Mail your comments to hi@foo.zone :-)

diff --git a/gemfeed/2018-06-01-realistic-load-testing-with-ioriot-for-linux.html b/gemfeed/2018-06-01-realistic-load-testing-with-ioriot-for-linux.html index 9241e74e..4206c625 100644 --- a/gemfeed/2018-06-01-realistic-load-testing-with-ioriot-for-linux.html +++ b/gemfeed/2018-06-01-realistic-load-testing-with-ioriot-for-linux.html @@ -20,7 +20,7 @@ // _ \\ | \ )|_ /`\_`> <_/ \ -jgs\__/'---'\__/ +jgs\__/'---'\__/

Foreword


@@ -29,17 +29,17 @@ jgs\__/'---'\__/
https://www.admin-magazin.de/Das-Heft/2018/06/Realistische-Lasttests-mit-I-O-Riot

-I havn't worked on I/O Riot for some time now, but all what is written here is still valid. I am still using I/O Riot to debug I/O issues and pattern once in a while, so by all means the tool is not obsolete yet. The tool even helped to resolve a major production incident at work caused by disk I/O.
+I havn't worked on I/O Riot for some time now, but all what is written here is still valid. I am still using I/O Riot to debug I/O issues and pattern once in a while, so by all means the tool is not obsolete yet. The tool even helped to resolve a major production incident at work caused by disk I/O.

-I am eagerly looking forward to revamp I/O Riot so that it uses the new BPF Linux capabilities instead of plain old Systemtap (or alternatively: Newer versions of Systemtap can also use BPF as the backend I have learned). Also, when I wrote I/O Riot initially, I didn't have any experience with the Go programming language yet and therefore I wrote it in C. Once it gets revamped I might consider using Go instead of C as it would spare me from many segmentation faults and headaches during development ;-). I might also just stick to C for plain performance reasons and just refactor the code dealing with concurrency.
+I am eagerly looking forward to revamp I/O Riot so that it uses the new BPF Linux capabilities instead of plain old Systemtap (or alternatively: Newer versions of Systemtap can also use BPF as the backend I have learned). Also, when I wrote I/O Riot initially, I didn't have any experience with the Go programming language yet and therefore I wrote it in C. Once it gets revamped I might consider using Go instead of C as it would spare me from many segmentation faults and headaches during development ;-). I might also just stick to C for plain performance reasons and just refactor the code dealing with concurrency.

-Pleace notice that some of the screenshots show the command "ioreplay" instead of "ioriot". That's because the name has changed after taking those.
+Pleace notice that some of the screenshots show the command "ioreplay" instead of "ioriot". That's because the name has changed after taking those.

The article



With I/O Riot IT administrators can load test and optimize the I/O subsystem of Linux-based operating systems. The tool makes it possible to record I/O patterns and replay them at a later time as often as desired. This means bottlenecks can be reproduced and eradicated.

-When storing huge amounts of data, such as more than 200 billion archived emails at Mimecast, it's not only the available storage capacity that matters, but also the data throughput and latency. At the same time, operating costs must be kept as low as possible. The more systems involved, the more important it is to optimize the hardware, the operating system and the applications running on it.
+When storing huge amounts of data, such as more than 200 billion archived emails at Mimecast, it's not only the available storage capacity that matters, but also the data throughput and latency. At the same time, operating costs must be kept as low as possible. The more systems involved, the more important it is to optimize the hardware, the operating system and the applications running on it.

Background: Existing Techniques



diff --git a/gemfeed/2021-04-24-welcome-to-the-geminispace.html b/gemfeed/2021-04-24-welcome-to-the-geminispace.html index e325708d..88a34f13 100644 --- a/gemfeed/2021-04-24-welcome-to-the-geminispace.html +++ b/gemfeed/2021-04-24-welcome-to-the-geminispace.html @@ -14,7 +14,7 @@
ASCII Art by Andy Hood!

-Have you reached this article already via Gemini? It requires a Gemini client; web browsers such as Firefox, Chrome, Safari, etc., don't support the Gemini protocol. The Gemini address of this site (or the address of this capsule as people say in Geminispace) is:
+Have you reached this article already via Gemini? It requires a Gemini client; web browsers such as Firefox, Chrome, Safari, etc., don't support the Gemini protocol. The Gemini address of this site (or the address of this capsule as people say in Geminispace) is:

gemini://foo.zone

@@ -28,14 +28,14 @@ | | | | | | - ' ` + ' ` |Gemini| | | |______| - '-`'-` . - / . \'\ . .' - ''( .'\.' ' .;' -'.;.;' ;'.;' ..;;' AsH + '-`'-` . + / . \'\ . .' + ''( .'\.' ' .;' +'.;.;' ;'.;' ..;;' AsH

@@ -47,7 +47,7 @@

My still great Laptop running hot



-Earlier this year (2021), I noticed that my almost seven-year-old but still great Laptop started to become hot and slowed down while surfing the web. Also, the Laptop's fan became quite noisy. This was all due to the additional bloat such as JavaScript, excessive use of CSS, tracking cookies+pixels, ads, and so on there was on the website.
+Earlier this year (2021), I noticed that my almost seven-year-old but still great Laptop started to become hot and slowed down while surfing the web. Also, the Laptop's fan became quite noisy. This was all due to the additional bloat such as JavaScript, excessive use of CSS, tracking cookies+pixels, ads, and so on there was on the website.

All I wanted was to read an interesting article, but after a big advertising pop-up banner appeared and made everything worse, I gave up and closed the browser tab.

@@ -55,16 +55,16 @@
Around the same time, I discovered a relatively new, more lightweight protocol named Gemini, which does not support all these CPU-intensive features like HTML, JavaScript, and CSS. Also, tracking and ads are unsupported by the Gemini protocol.

-The "downside" is that due to the limited capabilities of the Gemini protocol, all sites look very old and spartan. But that is not a downside; that is, in fact, a design choice people made. It is up to the client software how your capsule looks. For example, you could use a graphical client, such as Lagrange, with nice font renderings and colours to improve the appearance. Or you could use a very minimalistic command line black-and-white Gemini client. It's your (the user's) choice.
+The "downside" is that due to the limited capabilities of the Gemini protocol, all sites look very old and spartan. But that is not a downside; that is, in fact, a design choice people made. It is up to the client software how your capsule looks. For example, you could use a graphical client, such as Lagrange, with nice font renderings and colours to improve the appearance. Or you could use a very minimalistic command line black-and-white Gemini client. It's your (the user's) choice.

Screenshot Amfora Gemini terminal client surfing this site
Screenshot graphical Lagrange Gemini client surfing this site

-Why is there a need for a new protocol? As the modern web is a superset of Gemini, can't we use simple HTML 1.0 instead? That's a good and valid question. It is not a technical problem but a human problem. We tend to abuse the features once they are available. You can ensure that things stay efficient and straightforward as long as you are using the Gemini protocol. On the other hand, you can't force every website on the modern web to only create plain and straightforward-looking HTML pages.
+Why is there a need for a new protocol? As the modern web is a superset of Gemini, can't we use simple HTML 1.0 instead? That's a good and valid question. It is not a technical problem but a human problem. We tend to abuse the features once they are available. You can ensure that things stay efficient and straightforward as long as you are using the Gemini protocol. On the other hand, you can't force every website on the modern web to only create plain and straightforward-looking HTML pages.

My own Gemini capsule



-As it is effortless to set up and maintain your own Gemini capsule (Gemini server + content composed via the Gemtext markup language), I decided to create my own. What I like about Gemini is that I can use my favourite text editor and get typing. I don't need to worry about the style and design of the presence, and I also don't have to test anything in ten different web browsers. I can only focus on the content! As a matter of fact, I am using the Vim editor + its spellchecker + auto word completion functionality to write this.
+As it is effortless to set up and maintain your own Gemini capsule (Gemini server + content composed via the Gemtext markup language), I decided to create my own. What I like about Gemini is that I can use my favourite text editor and get typing. I don't need to worry about the style and design of the presence, and I also don't have to test anything in ten different web browsers. I can only focus on the content! As a matter of fact, I am using the Vim editor + its spellchecker + auto word completion functionality to write this.

This site was generated with Gemtexter. You can read more about it here:

@@ -76,10 +76,10 @@
  • Supports an alternative to the modern bloated web
  • Easy to operate and easy to write content
  • No need to worry about various web browser compatibilities
  • -
  • It's the client's responsibility how the content is designed+presented
  • +
  • It's the client's responsibility how the content is designed+presented
  • Lightweight (although not as lightweight as the Gopher protocol)
  • Supports privacy (no cookies, no request header fingerprinting, TLS encryption)
  • -
  • Fun to play with (it's a bit geeky, yes, but a lot of fun!)
  • +
  • Fun to play with (it's a bit geeky, yes, but a lot of fun!)

  • Dive into deep Gemini space



    @@ -90,8 +90,8 @@
    Other related posts are:

    -2023-03-25 Gemtexter 2.0.0 - Let's Gemtext again²
    -2022-08-27 Gemtexter 1.1.0 - Let's Gemtext again
    +2023-03-25 Gemtexter 2.0.0 - Let's Gemtext again²
    +2022-08-27 Gemtexter 1.1.0 - Let's Gemtext again
    2021-06-05 Gemtexter - One Bash script to rule it all
    2021-04-24 Welcome to the Geminispace (You are currently reading this)

    diff --git a/gemfeed/2021-05-16-personal-bash-coding-style-guide.html b/gemfeed/2021-05-16-personal-bash-coding-style-guide.html index fe611b4c..7e3dd47a 100644 --- a/gemfeed/2021-05-16-personal-bash-coding-style-guide.html +++ b/gemfeed/2021-05-16-personal-bash-coding-style-guide.html @@ -22,7 +22,7 @@ /======"---""---""---""---"=| =|| |____ []* ____ | ==|| // \\ // \\ |===|| hjw -"\__/"---------------"\__/"-+---+' +"\__/"---------------"\__/"-+---+'

    Lately, I have been polishing and writing a lot of Bash code. Not that I never wrote a lot of Bash, but now as I also looked through the Google Shell Style Guide, I thought it is time also to write my thoughts on that. I agree with that guide in most, but not in all points.
    @@ -41,7 +41,7 @@ #!/bin/bash
    -... as the shebang line, but that does not work on all Unix and Unix-like operating systems (e.g., the *BSDs don't have Bash installed to /bin/bash). Better is:
    +... as the shebang line, but that does not work on all Unix and Unix-like operating systems (e.g., the *BSDs don't have Bash installed to /bin/bash). Better is:

     #!/usr/bin/env bash
    @@ -51,9 +51,9 @@
     
    I know there have been many tab- and soft-tab wars on this planet. Google recommends using two space soft-tabs for Bash scripts.

    -I don't care if I use two or four space indentations. I agree, however, that we should not use tabs. I tend to use four-space soft-tabs as that's how I currently configured Vim for any programming language. What matters most, though, is consistency within the same script/project.
    +I don't care if I use two or four space indentations. I agree, however, that we should not use tabs. I tend to use four-space soft-tabs as that's how I currently configured Vim for any programming language. What matters most, though, is consistency within the same script/project.

    -Google also recommends limiting the line length to 80 characters. For some people, that seems to be an old habit from the '80s, where all computer terminals couldn't display longer lines. But I think that the 80 character mark is still a good practice, at least for shell scripts. For example, I am often writing code on a Microsoft Go Tablet PC (running Linux, of course), and it comes in convenient if the lines are not too long due to the relatively small display on the device.
    +Google also recommends limiting the line length to 80 characters. For some people, that seems to be an old habit from the '80s, where all computer terminals couldn't display longer lines. But I think that the 80 character mark is still a good practice, at least for shell scripts. For example, I am often writing code on a Microsoft Go Tablet PC (running Linux, of course), and it comes in convenient if the lines are not too long due to the relatively small display on the device.

    I hit the 80 character line length quicker with the four spaces than with two spaces, but that makes me refactor the Bash code more aggressively, which is a good thing.

    @@ -94,7 +94,7 @@ greet () { }

    -In this particular example, I agree that you should quote them as you don't know the input (are there, for example, whitespace characters?). But if you are sure that you are only using simple bare words, then I think that the code looks much cleaner when you do this instead:
    +In this particular example, I agree that you should quote them as you don't know the input (are there, for example, whitespace characters?). But if you are sure that you are only using simple bare words, then I think that the code looks much cleaner when you do this instead:

     say_hello_to_paul () {
    @@ -112,7 +112,7 @@ declare FOO=bar
     echo "foo${FOO}baz"
     

    -A few more words on always quoting the variables: For the sake of consistency (and for making ShellCheck happy), I am not against quoting everything I encounter. I also think that the larger the Bash script becomes, the more critical it becomes always to quote variables. That's because it will be more likely that you might not remember that some of the functions don't work on values with spaces in them, for example. It's just that I won't quote everything in every small script I write.
    +A few more words on always quoting the variables: For the sake of consistency (and for making ShellCheck happy), I am not against quoting everything I encounter. I also think that the larger the Bash script becomes, the more critical it becomes always to quote variables. That's because it will be more likely that you might not remember that some of the functions don't work on values with spaces in them, for example. It's just that I won't quote everything in every small script I write.

    Prefer built-in commands over external commands



    @@ -125,22 +125,22 @@ substitution="${string/#foo/bar}" # Instead of this: addition="$(expr "${X}" + "${Y}")" -substitution="$(echo "${string}" | sed -e 's/^foo/bar/')" +substitution="$(echo "${string}" | sed -e 's/^foo/bar/')"
    -I can't entirely agree here. The external commands (especially sed) are much more sophisticated and powerful than the built-in Bash versions. Sed can do much more than the Bash can ever do by itself when it comes to text manipulation (the name "sed" stands for streaming editor, after all).
    +I can't entirely agree here. The external commands (especially sed) are much more sophisticated and powerful than the built-in Bash versions. Sed can do much more than the Bash can ever do by itself when it comes to text manipulation (the name "sed" stands for streaming editor, after all).

    I prefer to do light text processing with the Bash built-ins and more complicated text processing with external programs such as sed, grep, awk, cut, and tr. However, there is also medium-light text processing where I would want to use external programs. That is so because I remember using them better than the Bash built-ins. The Bash can get relatively obscure here (even Perl will be more readable then - Side note: I love Perl).

    Also, you would like to use an external command for floating-point calculation (e.g., bc) instead of using the Bash built-ins (worth noticing that ZSH supports built-in floating-points).

    -I even didn't get started with what you can do with awk (especially GNU Awk), a fully-fledged programming language. Tiny Awk snippets tend to be used quite often in Shell scripts without honouring the real power of Awk. But if you did everything in Perl or Awk or another scripting language, then it wouldn't be a Bash script anymore, wouldn't it? ;-)
    +I even didn't get started with what you can do with awk (especially GNU Awk), a fully-fledged programming language. Tiny Awk snippets tend to be used quite often in Shell scripts without honouring the real power of Awk. But if you did everything in Perl or Awk or another scripting language, then it wouldn't be a Bash script anymore, wouldn't it? ;-)

    My additions



    -

    Use of 'yes' and 'no'


    +

    Use of 'yes' and 'no'



    -Bash does not support a boolean type. I tend just to use the strings 'yes' and 'no' here. I used 0 for false and 1 for true for some time, but I think that the yes/no strings are easier to read. Yes, the Bash script would need to perform string comparisons on every check, but if performance is crucial to you, you wouldn't want to use a Bash script anyway, correct?
    +Bash does not support a boolean type. I tend just to use the strings 'yes' and 'no' here. I used 0 for false and 1 for true for some time, but I think that the yes/no strings are easier to read. Yes, the Bash script would need to perform string comparisons on every check, but if performance is crucial to you, you wouldn't want to use a Bash script anyway, correct?

     declare -r SUGAR_FREE=yes
    @@ -150,9 +150,9 @@ buy_soda () {
         local -r sugar_free=$1
     
         if [[ $sugar_free == yes ]]; then
    -        echo 'Diet Dr. Pepper'
    +        echo 'Diet Dr. Pepper'
         else
    -        echo 'Pepsi Coke'
    +        echo 'Pepsi Coke'
         fi
     }
     
    @@ -173,7 +173,7 @@ variable="$(eval some_function)"
     
     

    -However, if I want to read variables from another file, I don't have to use eval here. I only have to source the file:
    +However, if I want to read variables from another file, I don't have to use eval here. I only have to source the file:

     % cat vars.source.sh
    @@ -181,7 +181,7 @@ declare foo=bar
     declare bar=baz
     declare bay=foo
     
    -% bash -c 'source vars.source.sh; echo $foo $bar $baz'
    +% bash -c 'source vars.source.sh; echo $foo $bar $baz'
     bar baz foo
     

    @@ -195,11 +195,11 @@ declare date="$(date)" declare user=$USER END -% bash -c 'source <(./vars.sh); echo "Hello $user, it is $date"' +% bash -c 'source <(./vars.sh); echo "Hello $user, it is $date"' Hello paul, it is Sat 15 May 19:21:12 BST 2021
    -The downside is that ShellCheck won't be able to follow the dynamic sourcing anymore.
    +The downside is that ShellCheck won't be able to follow the dynamic sourcing anymore.

    Prefer pipes over arrays for list processing



    @@ -207,12 +207,12 @@ Hello paul, it is Sat 15 May 19:21:12 BST 2021
     filter_lines () {
    -    echo 'Start filtering lines in a fancy way!' >&2
    +    echo 'Start filtering lines in a fancy way!' >&2
         grep ... | sed ....
     }
     
     process_lines () {
    -    echo 'Start processing line by line!' >&2
    +    echo 'Start processing line by line!' >&2
         while read -r line; do
             ... do something and produce a result...
             echo "$result"
    @@ -221,12 +221,12 @@ process_lines () {
     
     # Do some post-processing of the data
     postprocess_lines () {
    -    echo 'Start removing duplicates!' >&2
    +    echo 'Start removing duplicates!' >&2
         sort -u
     }
     
     genreate_report () {
    -    echo 'My boss wants to have a report!' >&2
    +    echo 'My boss wants to have a report!' >&2
         tee outfile.txt
         wc -l outfile.txt
     }
    @@ -245,9 +245,9 @@ main
     

    Assign-then-shift



    -I often refactor existing Bash code. That leads me to add and removing function arguments quite often. It's pretty repetitive work changing the $1, $2.... function argument numbers every time you change the order or add/remove possible arguments.
    +I often refactor existing Bash code. That leads me to add and removing function arguments quite often. It's pretty repetitive work changing the $1, $2.... function argument numbers every time you change the order or add/remove possible arguments.

    -The solution is to use of the "assign-then-shift"-method, which goes like this: "local -r var1=$1; shift; local -r var2=$1; shift". The idea is that you only use "$1" to assign function arguments to named (better readable) local function variables. You will never have to bother about "$2" or above. That is very useful when you constantly refactor your code and remove or add function arguments. It's something that I picked up from a colleague (a pure Bash wizard) some time ago:
    +The solution is to use of the "assign-then-shift"-method, which goes like this: "local -r var1=$1; shift; local -r var2=$1; shift". The idea is that you only use "$1" to assign function arguments to named (better readable) local function variables. You will never have to bother about "$2" or above. That is very useful when you constantly refactor your code and remove or add function arguments. It's something that I picked up from a colleague (a pure Bash wizard) some time ago:

     some_function () {
    @@ -281,7 +281,7 @@ some_function () {
     }
     

    -As you can see, I didn't need to change any other assignments within the function. Of course, you would also need to change the function argument lists at every occasion where the function is invoked - you would do that within the same refactoring session.
    +As you can see, I didn't need to change any other assignments within the function. Of course, you would also need to change the function argument lists at every occasion where the function is invoked - you would do that within the same refactoring session.

    Paranoid mode



    @@ -293,7 +293,7 @@ grep -q foo <<< bar echo Jo

    -Here 'Jo' will never be printed out as the grep didn't find any match. It's unrealistic for most scripts to run in paranoid mode purely, so there must be a way to add exceptions. Critical Bash scripts of mine tend to look like this:
    +Here 'Jo' will never be printed out as the grep didn't find any match. It's unrealistic for most scripts to run in paranoid mode purely, so there must be a way to add exceptions. Critical Bash scripts of mine tend to look like this:

     #!/usr/bin/env bash
    @@ -305,7 +305,7 @@ some_function () {
         ...
     
         set +e
    -    # Grep might fail, but that's OK now
    +    # Grep might fail, but that's OK now
         grep ....
         local -i ec=$?
         set -e
    @@ -320,7 +320,7 @@ some_function () {
     

    Learned



    -There are also a couple of things I've learned from Google's guide.
    +There are also a couple of things I've learned from Google's guide.

    Unintended lexicographical comparison.



    @@ -351,9 +351,9 @@ fi

    PIPESTATUS



    -I have never used the PIPESTATUS variable before. I knew that it's there, but I never bothered to understand how it works until now thoroughly.
    +I have never used the PIPESTATUS variable before. I knew that it's there, but I never bothered to understand how it works until now thoroughly.

    -The PIPESTATUS variable in Bash allows checking of the return code from all parts of a pipe. If it's only necessary to check the success or failure of the whole pipe, then the following is acceptable:
    +The PIPESTATUS variable in Bash allows checking of the return code from all parts of a pipe. If it's only necessary to check the success or failure of the whole pipe, then the following is acceptable:

     tar -cf - ./* | ( cd "${dir}" && tar -xf - )
    @@ -362,7 +362,7 @@ if (( PIPESTATUS[0] != 0 || PIPESTATUS[1] != 0 )); then
     fi
     

    -However, as PIPESTATUS will be overwritten as soon as you do any other command, if you need to act differently on errors based on where it happened in the pipe, you'll need to assign PIPESTATUS to another variable immediately after running the command (don't forget that [ is a command and will wipe out PIPESTATUS).
    +However, as PIPESTATUS will be overwritten as soon as you do any other command, if you need to act differently on errors based on where it happened in the pipe, you'll need to assign PIPESTATUS to another variable immediately after running the command (don't forget that [ is a command and will wipe out PIPESTATUS).

     tar -cf - ./* | ( cd "${DIR}" && tar -xf - )
    diff --git a/gemfeed/2021-06-05-gemtexter-one-bash-script-to-rule-it-all.html b/gemfeed/2021-06-05-gemtexter-one-bash-script-to-rule-it-all.html
    index 5148d1e0..