Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unbound variable not causing exit from subshell when set -eu

Tags:

bash

shell

$ cat test.sh
set -eu
echo "`wc -l < $DNE`"
echo should not get here

$ /bin/bash test.sh
test.sh: line 2: DNE: unbound variable

should not get here

I'm running bash version 4.1.2. Is there a way to make sure all such usage of unbound variables in subshells cause the script to exit without having to modify each call involving a subshell?

like image 741
Jason Avatar asked Feb 09 '13 19:02

Jason


People also ask

How do you exit a subshell?

Use signals to exit process from subshell This is the mechanism that allows you to exit a command line process by pressing ctrl-c. When you press ctrl-c in your terminal, an interrupt signal (SIGINT) is sent to the current process.

What is Pipefail in bash?

pipefail. If set, the return value of a pipeline is the value of the last (rightmost) command to exit with a non-zero status, or zero if all commands in the pipeline exit successfully. This option is disabled by default.

Can be used to set environment variable in a shell which can be accessed from the sub shell?

Explanation: set command is used to display all the variables available in the current shell. set is a built-in command. env is an external command and runs in a child process. It thus displays only those variables that are inherited from its parent, the shell.

What is set in bash?

set allows you to change the values of shell options and set the positional parameters, or to display the names and values of shell variables.


2 Answers

The better solution to ensure variable sanitisation

#!/usr/bin/env bash

set -eu

if [[ ${1-} ]]; then
  DNE=$1
else
  echo "ERROR: Please enter a valid filename" 1>&2
  exit 1
fi

By putting a hyphen in to the variable name inside curly braces like this allows bash to sanely handle the variable being undefined. I also highly recommend looking at the Google shell style guide, it's a great reference https://google.github.io/styleguide/shell.xml

[[ -z ${variable-} ]] \
  && echo "ERROR: Unset variable \${variable}" \
  && exit 1 \
  || echo "INFO: Using variable (${variable})"
like image 67
Phil Avatar answered Nov 15 '22 15:11

Phil


Use a temporary variable so as to let test.sh process know about the failure of wc. You can change it to:

#!/bin/bash
set -eu
out=$(wc -l < $DNE)
echo $out
echo should not get here

Now, you won't see the should not get here if wc fails.

like image 24
P.P Avatar answered Nov 15 '22 17:11

P.P