1

I have a function that will execute a few commands.

function doSomething() {
    good or bad command || error "reason"
    good or bad command || error "other reason"
    good or bad command || error "some other reason"
}

If anyone of the commands fails, the error function will be called

# error exit function
function error() {
    echo -e "${RED} $1 ${NC}"
    exit 
}

whenever the error function is called, it is closing the current terminal.

Requirement:

  • the error function should exit from the function stack instead of closing the terminal.

Can anyone help me in achieving my requirement from the following two ways:

  • Using exit keyword
  • Using the return statement (chaining return from the error() to doSomething())

Edit: I just placed the above two functions in a utils.sh file and sourcing it(source utils.sh) in the current terminal.

3
  • 1
    How are you executing the script? Exit should not be able to close the terminal under normal circumstances Commented Aug 26, 2020 at 2:13
  • 2
    Maybe you want return instead of exit. Else are you sourcing your function files in the current terminal? Make it a script that sources all the functions, then when that exits, it will exit the sub-shell of the script you launched, and return to the cmd-line, ready to do more work. (If I understand your problem description). Good luck. Commented Aug 26, 2020 at 2:37
  • 2
    You can't really exit the whole function stack without terminating the current process. There's no try/catch stack unwinding in a shell. However, you can carefully create process boundaries using subshells and external commands, and terminate those. Commented Aug 26, 2020 at 2:55

3 Answers 3

1

exit won't exit your terminal unless you source it AFAIK.

The only way I know to exit a function stack is exit. If you want to source the script and don't want to exit the terminal, the simplest way I found to do it is wrap it with a subshell:

#!/bin/bash

doSomething() {
    # good is not a valid command
    (good || error "reason" $?
    good || error "other reason" $?
    good || error "some other reason" $?
    echo "Shouldn't be here")
}

# error exit function
error() {
    echo -e "${RED} $1 ${NC}"
    exit
}
doSomething

source it won't exit your terminal because the exit is executing in a subshell.

The limit of this approach is your env var change in subshell can't affect the outside environment.

Another way is call it in subshell:

#!/bin/bash

doSomething() {
    set -e
    good || error "reason" $?
    good || error "other reason" $?
    good || error "some other reason" $?
    echo "Shouldn't be here"
}

# error exit function
error() {
    echo -e "${RED} $1 ${NC}"
    exit
}

Call it by (doSomething). This avoid the limit mentioned above.

Sign up to request clarification or add additional context in comments.

Comments

1

1. Using exit keyword:

Just wrap all the commands in the doSomething function into parenthesis, so that all commands execute inside the subshell and when it encounters exit, the subshell will quit instead of quitting the current shell.

function doSomething() {
    (
        good or bad command || error "reason"
        good or bad command || error "other reason"
        good or bad command || error "some other reason"
    )
}
# error exit function
function error() {
    echo -e "${RED} $1 ${NC}"
    exit
}

2. Using return keyword:

Grouping error function along with the return statement: If any of the commands is failed then error function is called and then the return of that error function is returned to the doSomething function.

function doSomething() {
    good or bad command || { error "reason"; return $?; }
    good or bad command || { error "other reason"; return $?; }
    good or bad command || { error "some other reason"; return $?; }
}
# error function
function error() {
    echo -e "${RED} $1 ${NC}"
    return 0
}

By the use of the above 2 ways, we can achieve the error exit behavior.

Comments

0

This may help

doSomething() {
    good or bad command || { error "reason" $?; return; }
    good or bad command || { error "other reason" $?; return; }
    good or bad command || { error "some other reason" $?; return; }
}

# error exit function
error() {
    echo -e "${RED} $1 ${NC}"
    return $2 
}

$? it's an exit status of previous command, we send it to a error function as second arg to use in return command.

1 Comment

It is not working. Whenever the error function is called within the doSomething function, the error function should make the doSomething function to quit. But it is still executing the remaining commands instead of quitting.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.