<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Jeremy</title>
    <description>The latest articles on DEV Community by Jeremy (@banks).</description>
    <link>https://dev.to/banks</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F186618%2F5f3de8f2-6eea-402f-8875-c95d2530cf28.png</url>
      <title>DEV Community: Jeremy</title>
      <link>https://dev.to/banks</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/banks"/>
    <language>en</language>
    <item>
      <title>Async and Generator Function Constructors in JavaScript</title>
      <dc:creator>Jeremy</dc:creator>
      <pubDate>Sun, 17 Sep 2023 04:43:05 +0000</pubDate>
      <link>https://dev.to/banks/async-and-generator-function-constructors-in-javascript-22bi</link>
      <guid>https://dev.to/banks/async-and-generator-function-constructors-in-javascript-22bi</guid>
      <description>&lt;p&gt;Sometimes I like to browse through the &lt;a href="https://tc39.es/ecma262/"&gt;ECMAScript/JavaScript specification&lt;/a&gt; or &lt;a href="https://html.spec.whatwg.org/"&gt;the HTML specification&lt;/a&gt; at random, to see if I come across anything interesting or unexpected. That's how I first became aware of &lt;a href="https://stackoverflow.com/a/10916838/1114"&gt;the "structured cloning" algorithm&lt;/a&gt; (back when it was still only for internal use), and today I found a new piece of JavaScript trivia that really tickled my interest.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Background
&lt;/h3&gt;

&lt;p&gt;In JavaScript, if you want to define a new function dynamically/at runtime, from source code, you can do so by using &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/Function"&gt;the &lt;code&gt;Function&lt;/code&gt; constructor&lt;/a&gt;. For example, if we want to define a function that adds two numbers, we could do so like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;add&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;b&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;return a + b;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This would create a function equivalent to as if we had written this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;add&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In practice, this is essentially &lt;strong&gt;never&lt;/strong&gt; a good idea. It's basically the same as using &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval"&gt;&lt;code&gt;eval&lt;/code&gt;&lt;/a&gt;, with an unreasonable risk of introducing security issues or negatively affecting the performance of your program, as well as preventing effective static analysis by tools like TypeScript. It has been widely discouraged for a very long time, and is entirely blocked by &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP"&gt;Content Security Policy&lt;/a&gt; configurations that are enabled by default by many modern web frameworks. But let's set these concerns aside for a moment.&lt;/p&gt;

&lt;p&gt;Later versions of ECMAScript added three new types of functions, which are declared using slightly different syntaxes. Here are contrived examples of each:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Async Functions:&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;add&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Generator Functions:&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;add&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Async Generator Functions:&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;add&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see that each different type of function requires a different syntax where the &lt;code&gt;function&lt;/code&gt; keyword appears. However, the &lt;code&gt;Function&lt;/code&gt; constructor only lets us specify the contents of the argument list and body; it doesn't provide any way to affect the &lt;code&gt;function&lt;/code&gt; keyword, so it can't be used to create these new types of functions. And if we try in the JavaScript console, we don't see any &lt;code&gt;AsyncFunction&lt;/code&gt;, &lt;code&gt;GeneratorFunction&lt;/code&gt;, or &lt;code&gt;AsyncGeneratorFunction&lt;/code&gt; constructors we can use instead: none of those identifiers are declared in the global namespace.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Uncaught ReferenceError: AsyncFunction is not defined
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This isn't really surprising. These types of functions were added to the language long after use of the &lt;code&gt;Function&lt;/code&gt; constructor was already widely discouraged. Although the existing constructor could never be removed from the language due to backwards-compatibility concerns, it's understandable that they wouldn't want to introduce new ones to allow these patterns to be continued in new code being written in the modern versions of the language.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Surprise
&lt;/h3&gt;

&lt;p&gt;But much to my surprise, the ECMAScript specification &lt;em&gt;does&lt;/em&gt; define behavior for each of these constructors, even though &lt;em&gt;they're not directly exposed under any name&lt;/em&gt;. We can find these in the 2024 edition of the specification under &lt;a href="https://tc39.es/ecma262/#sec-async-function-constructor"&gt;section 27.7.1 for "The &lt;code&gt;AsyncFunction&lt;/code&gt; Constructor"&lt;/a&gt;, &lt;a href="https://tc39.es/ecma262/#sec-generatorfunction-constructor"&gt;section 27.3.1 for "The &lt;code&gt;GeneratorFunction&lt;/code&gt; Constructor"&lt;/a&gt;, and &lt;a href="https://tc39.es/ecma262/#sec-asyncgeneratorfunction-constructor"&gt;section 27.4.1 for "The &lt;code&gt;AsyncGeneratorFunction&lt;/code&gt; Constructor&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;However, as mentioned, these aren't directly exposed under any name; the corresponding identifiers are not declared in the global namespace. So are they just an irrelevant internal detail of the spec?&lt;/p&gt;

&lt;p&gt;Nope! For better or worse, we can actually use them. Although they're not exposed under any name, we can get references to these constructors through &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/constructor"&gt;the &lt;code&gt;.constructor&lt;/code&gt; property&lt;/a&gt; of existing functions of each type, with code like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;AsyncFunction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}).&lt;/span&gt;&lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;GeneratorFunction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}).&lt;/span&gt;&lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;AsyncGeneratorFunction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}).&lt;/span&gt;&lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With these definitions available, we can dynamically create functions of these new types just like we can create normal functions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;add&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;AsyncFunction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;b&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;return (await a) + (await b);&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;6
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Should you ever do this? Almost certainly not. This type of code is discouraged for good reasons. Frontend code should be using a &lt;code&gt;Content Security Policy&lt;/code&gt; that forbids &lt;code&gt;eval&lt;/code&gt;-style code like this from even running. I'm mostly just sharing this because I thought it was a fun piece of trivia, and I was surprised that it was included in the specification, even though it does make a certain kind of sense for consistency.&lt;/p&gt;

&lt;p&gt;But if you really do find yourself in a situation where you actually need this capability (maybe you're writing some kind of custom JavaScript REPL), now you know that it exists!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>programming</category>
    </item>
    <item>
      <title>Robust error handling in Bash</title>
      <dc:creator>Jeremy</dc:creator>
      <pubDate>Thu, 02 Jul 2020 04:05:12 +0000</pubDate>
      <link>https://dev.to/banks/stop-ignoring-errors-in-bash-3co5</link>
      <guid>https://dev.to/banks/stop-ignoring-errors-in-bash-3co5</guid>
      <description>&lt;p&gt;Errors happen. Even if we write a perfect program, it might be provided with invalid input, or unexpectedly disconnected from the network. The key to writing reliable software isn't to prevent all errors, but to ensure that all errors are handled in a predictable way.&lt;/p&gt;

&lt;p&gt;Bash does not enforce precise error handling. In fact, by default it simply ignores most errors. However, with a bit of care it is possible to write robust, reliable scripts that keep you and your users happy. Here are some error handling practices to keep in mind.&lt;/p&gt;

&lt;h2&gt;
  
  
  What do we mean by errors?
&lt;/h2&gt;

&lt;p&gt;Bash doesn't have exceptions or error types as we might be used to in other languages. However, every command, whether it's built-in to Bash or an external program, returns an "exit status code" between &lt;code&gt;0&lt;/code&gt; and &lt;code&gt;255&lt;/code&gt; when it finishes executing. Successful commands return &lt;code&gt;0&lt;/code&gt;, while commands that fail return a code between &lt;code&gt;1&lt;/code&gt; and &lt;code&gt;255&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When I talk about "errors" in Bash in this post, I'm referring to any command which exits with a non-zero exit code in a context where it isn't explicitly expected. For example, if you had a program that started with&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;example.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and &lt;code&gt;example.txt&lt;/code&gt; did not exist, that would be an error. Nothing is handling the failure, so the program would either crash or continue in an invalid state. However if you have an &lt;code&gt;if&lt;/code&gt; statement like&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; example.txt&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Example found"&lt;/span&gt;
&lt;span class="k"&gt;else
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Example not found"&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the command &lt;code&gt;test -e example.txt&lt;/code&gt; may fail, but the &lt;code&gt;if&lt;/code&gt; statement is expecting its condition to be a command that might fail, and it handles that case automatically. I do &lt;em&gt;not&lt;/em&gt; consider that an "error" for the purpose of this post. The same reasoning applies to cases like &lt;code&gt;while COMMAND; do ...&lt;/code&gt; and &lt;code&gt;COMMAND || return 0&lt;/code&gt;; see the Bash manual for the full list of exceptions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Simple errors
&lt;/h2&gt;

&lt;p&gt;By default, Bash scripts will ignore most errors and continue running. The first thing we need to do in our scripts is enable Bash's basic error handling options, as follows.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-euo&lt;/span&gt; pipefail
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we enabling three options at once. Let's break them down.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;set -e&lt;/code&gt; (aka &lt;code&gt;-o errexit&lt;/code&gt;) causes &lt;em&gt;most&lt;/em&gt; failing commands to immediately return from the enclosing function, propagating their error exit status code to the calling function. If the calling function also doesn't handle the error, it will continue up the stack, eventually exiting the script with that exit status code. (Note that there are still some cases where errors can be silently ignored, discussed below.)&lt;/p&gt;

&lt;p&gt;&lt;code&gt;set -u&lt;/code&gt; (aka &lt;code&gt;-o nounset&lt;/code&gt;) makes it an error to refer to a variable like &lt;code&gt;$X&lt;/code&gt; if it hasn't been defined, either in the script or as an environment variable, instead of treating it as an empty string. Often, this is a typo and a bug. There are certainly some cases where you'll need to handle possibly-undefined variables, but they should be indicated explicitly: you can use &lt;code&gt;${X-}&lt;/code&gt; instead of &lt;code&gt;$X&lt;/code&gt; to indicate where you'd like to use an empty string if a variable isn't defined.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;set -o pipefail&lt;/code&gt; prevents errors from being silently ignored in pipelines (when the output of one command is being piped to the input of another). For example, consider:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;example.txt | &lt;span class="nb"&gt;grep &lt;/span&gt;metadata | &lt;span class="nb"&gt;sort&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By default, the exit status of the entire pipeline will just be that of the last command, &lt;code&gt;sort&lt;/code&gt;. This can succeed even if &lt;code&gt;example.txt&lt;/code&gt; does not exist and an earlier command like &lt;code&gt;cat&lt;/code&gt; fails. &lt;code&gt;pipefail&lt;/code&gt; changes this behaviour so that the pipeline is marked as failed if &lt;em&gt;any&lt;/em&gt; of the commands fail. (Subsequent commands in the pipeline will still be executed. If multiple fail, the exit status of the last failing command will be used.)&lt;/p&gt;

&lt;p&gt;Setting &lt;code&gt;set -euo pipefail&lt;/code&gt; is a very common practice for many shells, but for Bash in particular there's one more option you should also be setting:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;shopt&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; inherit_errexit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By default, when you use command substitution in Bash, the &lt;code&gt;-e&lt;/code&gt; setting is not applied. For example, if we had&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Command output: &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;date&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the command would successfully output the result of &lt;code&gt;date&lt;/code&gt;, even though the failing &lt;code&gt;false&lt;/code&gt; command should have exited the script first. Enabling &lt;code&gt;inherit_errexit&lt;/code&gt; allows the command substitution to inherit our &lt;code&gt;-e&lt;/code&gt; setting, so &lt;code&gt;date&lt;/code&gt; will not be run. (However, please note that the error status of the command substitution is still ignored. Even though the parenthesized expression returned a nonzero exit status, &lt;code&gt;echo&lt;/code&gt; will still run successfully. This is discussed in more detail below.)&lt;/p&gt;

&lt;h2&gt;
  
  
  ShellCheck
&lt;/h2&gt;

&lt;p&gt;Adopting those settings made my scripts much more reliable, but I was still finding some bugs in them. Many came from me misunderstanding subtleties of Bash's syntax, where my code wasn't doing what I thought it was doing. I might forget which terms need quoting in a condition like &lt;code&gt;[[ $x -eq "$y" ]]&lt;/code&gt;, or where I can and can't omit the &lt;code&gt;$&lt;/code&gt; before a variable in an expression like &lt;code&gt;$(( x = y ))&lt;/code&gt;. I tried to keep the rules straight, but there were too many to absorb at once and it felt hopeless, until I discovered ShellCheck.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/koalaman/shellcheck"&gt;ShellCheck&lt;/a&gt; is a static analysis tool/linter for Bash scripts, and it is &lt;em&gt;invaluable&lt;/em&gt;. I use it in VS Code (&lt;a href="https://marketplace.visualstudio.com/items?itemName=timonwong.shellcheck"&gt;extension&lt;/a&gt;) and run it in CI. It flags &lt;a href="https://github.com/koalaman/shellcheck/blob/master/README.md#user-content-gallery-of-bad-code"&gt;cases where your code might not be doing what you expect&lt;/a&gt;, with links to &lt;a href="https://github.com/koalaman/shellcheck/wiki/SC2035"&gt;wiki pages explaining the problem and potential alternatives&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Most of my recent Bash learnings have started with a ShellCheck warning code making me aware of an edge case or capability that I hadn't considered. Like any linter, you may occasionally need to ignore its warnings with an annotation like &lt;code&gt;# shellcheck disable=SC2034&lt;/code&gt;, but I've found its advice is usually very good, even when it seemed counterintuitive at first.&lt;/p&gt;

&lt;p&gt;Even with ShellCheck, there are still some subtle cases where you can silence errors without realizing it, but not many.&lt;/p&gt;

&lt;h2&gt;
  
  
  Subshells
&lt;/h2&gt;

&lt;p&gt;A lot of things about Bash have surprised me, but this was the most shocking: when you use parentheses to group commands, Bash &lt;em&gt;forks the entire process&lt;/em&gt; to create a "subshell" child process running the parenthesized code!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;echo &lt;/span&gt;this is a subshell&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;ls

echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;ls &lt;/span&gt;also-this&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;ls &lt;/span&gt;this-too&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

my_function&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;
  &lt;span class="nb"&gt;echo &lt;/span&gt;this is a subshell
&lt;span class="o"&gt;)&lt;/span&gt;

other_function&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;echo &lt;/span&gt;but this is NOT, because I used curly braces instead of round parentheses
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is why if you try to set a global variable from inside of parentheses, the change won't be visible outside: you're only setting the value in the child process.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;declare &lt;/span&gt;&lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;first
&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;second&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;  &lt;span class="c"&gt;# echoes "first"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This usually doesn't cause a problem for error handling—our settings are propagated to the subshell, and the exit status of the subshell is propagated back. However, there is one major exception...&lt;/p&gt;

&lt;h3&gt;
  
  
  The unfortunate case of command substitution
&lt;/h3&gt;

&lt;p&gt;Even with every available setting enabled, failures in command substitution subshells are usually silenced/masked and do not cause a failure in the original shell process. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-euo&lt;/span&gt; pipefail
&lt;span class="nb"&gt;shopt&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; inherit_errexit

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&amp;amp;2 &lt;span class="s2"&gt;"error: everything is broken"&lt;/span&gt;
  &lt;span class="nb"&gt;exit &lt;/span&gt;66
&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"but this is still running"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;error: everything is broken
but this is still running
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As far as I can tell, there is no way to change this behaviour, &lt;em&gt;and&lt;/em&gt; ShellCheck can't warn about it. &lt;strong&gt;If there is some way I've missed, please let me know!&lt;/strong&gt; There are workarounds, but they're clunky.&lt;/p&gt;

&lt;p&gt;The exit status of these subshells &lt;em&gt;is&lt;/em&gt; returned to the parent shell, however, it's never checked before it is overwritten by the return status of the original command (&lt;code&gt;echo&lt;/code&gt; in the case above). If we put the command substitution in an assignment expression on its own, instead of as an argument to another command, the exit status won't be overwritten. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-euo&lt;/span&gt; pipefail
&lt;span class="nb"&gt;shopt&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; inherit_errexit

&lt;span class="nb"&gt;declare &lt;/span&gt;output
&lt;span class="nv"&gt;output&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&amp;amp;2 &lt;span class="s2"&gt;"error: everything is broken"&lt;/span&gt;
  &lt;span class="nb"&gt;exit &lt;/span&gt;66
&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$output&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;error: everything is broken
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will behave properly, with the failure in &lt;code&gt;output="$(...)"&lt;/code&gt; exiting the script.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bonus suggestions
&lt;/h2&gt;

&lt;p&gt;The default handling of glob expressions in Bash is confusing. Consider the command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; ./builds/bin-&lt;span class="k"&gt;*&lt;/span&gt;/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If &lt;code&gt;builds&lt;/code&gt; contains one or more directories whose names start with &lt;code&gt;bin-&lt;/code&gt;, you'll get an argument for each, expanding to something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; ./builds/bin-windows/ ./builds/bin-linux/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, if there's no match, the glob expression isn't replaced, it's just passed to the command as-is, typically producing an error or unexpected behaviour:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ls: cannot access './builds/bin-*/': No such file or directory
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are two more-reasonable alternative behaviours, and I strongly suggest you set one of them: &lt;code&gt;shopt -s nullglob&lt;/code&gt; will replace the glob expression with the empty string if it doesn't match, and &lt;code&gt;shopt -s failglob&lt;/code&gt; will raise an error.&lt;/p&gt;

&lt;p&gt;Finally, you should set &lt;code&gt;shopt -s compat"${BASH_COMPAT=42}"&lt;/code&gt; with the minimum Bash version you want to support, to reduce the chance of breakage in later versions. For Linux I usually target &lt;code&gt;42&lt;/code&gt; (February 2011) but macOS only ships with &lt;code&gt;32&lt;/code&gt; (October 2006).&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Writing robust Bash scripts is tricky, but not impossible. Start your scripts with &lt;code&gt;set -euo pipefail; shopt -s inherit_errexit nullglob compat"${BASH_COMPAT=42}"&lt;/code&gt; and use &lt;a href="https://github.com/koalaman/shellcheck"&gt;ShellCheck&lt;/a&gt;, and you'll be 90% of the way there!&lt;/p&gt;

&lt;h2&gt;
  
  
  Appendix 1: Bash manual description of the &lt;code&gt;-e&lt;/code&gt;/&lt;code&gt;-o errexit&lt;/code&gt; setting
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Exit immediately if a pipeline (which may consist of a single simple command), a list, or a compound command (see SHELL GRAMMAR above), exits with a non-zero status. The shell does not exit if the command that fails is part of the command list immediately following a &lt;code&gt;while&lt;/code&gt; or &lt;code&gt;until&lt;/code&gt; keyword, part of the test following the &lt;code&gt;if&lt;/code&gt; or &lt;code&gt;elif&lt;/code&gt; reserved words, part of any command executed in a &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt; or &lt;code&gt;||&lt;/code&gt; list except the command following the final &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt; or &lt;code&gt;||&lt;/code&gt;, any command in a pipeline but the last, or if the command's return value is being inverted with &lt;code&gt;!&lt;/code&gt;. If a compound command other than a subshell returns a non-zero status because a command failed while &lt;code&gt;-e&lt;/code&gt; was being ignored, the shell does not exit. A trap on &lt;code&gt;ERR&lt;/code&gt;, if set, is executed before the shell exits. This option applies to the shell environment and each subshell environment separately (see COMMAND EXECUTION ENVIRONMENT above), and may cause subshells to exit before executing all the commands in the subshell.&lt;/p&gt;

&lt;p&gt;If a compound command or shell function executes in a context where &lt;code&gt;-e&lt;/code&gt; is being ignored, none of the commands  executed  within the compound command or function body will be affected by the &lt;code&gt;-e&lt;/code&gt; setting, even if &lt;code&gt;-e&lt;/code&gt; is set and a command returns a failure status. If a compound command or shell function sets &lt;code&gt;-e&lt;/code&gt; while executing in a context where &lt;code&gt;-e&lt;/code&gt; is ignored, that setting will not have any effect until the compound command or the command containing the function call completes.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;source:&lt;/em&gt; &lt;code&gt;{ COLUMNS=2048 man bash | grep -Em1 -A32 '^\s+set \[' | grep -Em1 -A32 '^\s+-e\s{4}' | grep -Em2 -B32 '^\s+-.\s{4}' | sed '$d' | grep -EoA32 '\s{4}(\S\s{0,4})+$' | grep -Eo '\S.*$' | fmt -tw$COLUMNS; }&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>bash</category>
      <category>linux</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
