0

I am looking for a better version of set -e. That better version should just work™. I briefly read BashFaq/105 and tried this insane approach, but I still do not know how to fail on error.

My use case is that I would like to generate a text file from a template like this:

#!/usr/bin/env bash

none of these options helped to get the behavior I want: stop on first error

set -euo pipefail

shopt -s inherit_errexit

set -o errexit

trap ERR

cat <<< " MYAPP_DATABASE_PASSWORD=$(pwgen -1 32)

MYAPP_USER_PASSWORD=$(pwgen -1 8)

MYAPP_CONFIGURATION_DATE=$(date --utc --iso-8601=ns) "

Alternatively, this approach is also acceptable to me (where template.txt is a text file that contains the here string from above):

#!/usr/bin/env bash

none of these options helped to get the behavior I want: stop on first error

set -euo pipefail

shopt -s inherit_errexit

set -o errexit

trap ERR

while read line; do [ -z "$line" ] || echo "# $line" cmd="echo $line" outline=$(eval $cmd) exitstatus=$? echo "$outline" echo "# exit status was $exitstatus" done < "template.txt"

Unfortunately, neither of the above perfectly works for me because of the following requirement: I just want the whole thing to crash if a command substitution fails, e.g., due to pwgen not being found. There should be no more than one error.

With other techniques the desired behavior is the default:

# this is an erb file                    
<%
require 'securerandom'
require 'date'
%>

MYAPP_DATABASE_PASSWORD=<%= SecureRandom.alphanumeric(32) %>

MYAPP_USER_PASSWORD=<%= SecureRandom.alphanumeric(8) %>

MYAPP_CONFIGURATION_DATE=<%= DateTime.now.new_offset.iso8601(6) %>

if there is a typo in SecureRandom then erb immediately exits with a failure.

How to achieve this crash-on-failure behavior with bash?

Julius
  • 101

2 Answers2

1

Another option is to use a configuration tool like Ansible which allow you to use jinja2 templates, and also allow you to verify the resulting file if the application which consume the file have some sort of config check.

- name: Update sshd configuration safely, avoid locking yourself out
  template:
    src: etc/ssh/sshd_config.j2
    dest: /etc/ssh/sshd_config
    owner: root
    group: root
    mode: '0600'
    validate: /usr/sbin/sshd -t -f %s
    backup: yes
Rabin
  • 3,883
  • 1
  • 22
  • 23
0

After some more research I prefer an erb-like solution over the bash template. If there is a fail-fast solution for bash then it is too exotic to be useful (simplicity, clarity, maintainability, ...).

All my attempts on a simple fail-fast bash solution were negated by the following rule concerning bash's Simple Command Expansion:

If one of the expansions contained a command substitution, the exit status of the command is the exit status of the last command substitution performed.

TL;DR: Forget that bash-template idea because it is too complicated to be useful. Instead, choose a high-level tool that was designed for that job.

Julius
  • 101