shell process not exiting on `exit` inside `$()`

421 views Asked by At

I have a complicated bash script so I broke it down to the code that matters:

#!/bin/sh

foo()
{
    echo test
    # here I do some work and if it fails I want to stop execution
    exit 1
}

echo $(foo)
echo help

This is about my script and I would like it to print test and then exit but the output is:

test
help

This is also true for bash.

My temporary workaround at the moment is to replace the exit 1 with kill $$.

What do I have to do so it does really exit?

Update:

If someone has better suggestions, please speak out!

3

There are 3 answers

2
rici On BEST ANSWER

The exit builtin command causes the currently executing subshell to terminate. Since the command substitution syntax $(command) creates a subshell to execute command, the exit only terminates that subshell, not the shell which includes the result of the command substitution.

If you really need command substitution, you're not going to be able to trap exit from the substituted command. In fact, you cannot even trap failure. About the only option you have is to send the output of the command into a temporary file and then substitute the temporary file in a subsequent step.

In the simple case in the OP, you can just call foo directly instead of echo $(foo). But if you needed to capture the output of foo in a shell variable, for example, you could do it as follows

foo() {
  # ...
  exit
}

foo >/tmp/foo
v=$(</tmp/foo)
0
leu On

Looks like you have to call

foo

instead of echo $(foo)

0
Matthew Westrik On

When you call foo with $(foo), it creates a new subshell and that is what's being exited. You need to replace echo $(foo) with just foo