2

According to this post:

The exit status of the if command shall be the exit status of the then or else compound-list that was executed, or zero, if none was executed.

This leads to a bug in my bash script where:

  • I have set -euo pipefail set in the script and expect it to stop executing if any errors arise
  • I have an if statement with a condition that errors, but execution continues because -e doesn't care about the condition in if statements

Specifically, I have an if function1; then and I want to shield from the case where function1 doesn't exist.

The scenario is that someone modifies function1, it no longer exists, but the script runs fine and the user doesn't realize that the script failed.

This is meant to be for every if statement in a bash file, so it's not a matter of making sure function1 exists, I'm looking for a blanket solution for a file, like set -euo pipefail that requires as little refactoring as possible.

I've looked in the set documentation, and nothing seems to be suitable there.

Summary:

function1 does not exist

run if function1; then ...

Expected:

script exits

Actual:

whatever.sh: line ##: function1: command not found

script continues

4
  • I do not understand. You seem to know and researched how it works. You know what to expect. You know that your script has a bug. So go and fix your script - why ask here? Commented Dec 2, 2021 at 0:12
  • I am writing redundancy into a script that other developers might touch - if someone makes a similar mistake, it'll trigger a pipeline and cause lots of headaches. I'm looking to prevent that. Commented Dec 2, 2021 at 0:17
  • This is just how set -e operates. If the error occurs within a logical test (if, &&, or ||), it does not trigger exit. Commented Dec 2, 2021 at 2:42
  • @dan I know. I want something that will make it exit. This is not a bug report. Commented Dec 2, 2021 at 5:48

3 Answers 3

1

Specifically, I have an if function1; then and I want to shield from the case where function1 doesn't exist.

So implement that.

fn_exists() { [[ "$(LC_ALL=C type -t -- "$1" 2>/dev/null)" = function ]]; }

call_fn_or_fail() {
   if ! fn_exists "$1"; then
      echo "hatever.sh: line ##: function1: command not found" >&2
      exit 1
   fi
   "$@"
}

if call_fn_or_fail function1; then
Sign up to request clarification or add additional context in comments.

2 Comments

Sorry, this looks like sorcery to me. Is this more or less a wrapper function/decorator to function1 that could be applied to other functions?
Yes. It's a wrapper function to do exactly what you want - call the function given as argument, or exit non zero if the function doesn't exist. It won't exit if the function does exist, but fails (inside if).
0

I don't think i get your problem. Heres a script i wrote for testing purposes

#!/bin/bash
set -euo pipefail


somefunc(){
 echo 'ok'
}


echo first if 
if somefunc; then 
    echo yea it was there alright 
    grep "gimme exit code 1" /etc/passwd
    echo $?
fi

echo second if
#type somefunk

if somefunk; then
    echo this should not happen
fi

echo end of script

if errors out after the exit code 1 for grep fails to find that string in my /etc/passwd file.

bash -x sotest.sh 
+ set -euo pipefail
+ echo first if
first if
+ somefunc
+ echo ok
ok
+ echo yea it was there alright
yea it was there alright
+ grep 'gimme exit code 1' /etc/passwd

This is basically exactly what you want.

comment that grep out and we get this

./sotest.sh 
first if
ok
yea it was there alright
0
second if
./sotest.sh: line 20: somefunk: command not found
end of script

Of course the second if fails and the script carries on, thats why you have an if statement, you are recognizing the possibility that you get an error and only running the "then" if that doesn't happen.

You have two options. Check that the functions exist. Don't call them with if. If you attempt to call a function that doesn't exist it will error and your script will exit.

Comments

0

I ended up choosing a solution that is outside the bash script. I output the result of this bash script, and then use grep to check if that output has any "command not found" lines in it, and error if so. Not really part of the original scope, but just what I ended up doing.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.