Ian Tait
Ian Tait

Reputation: 607

How to get error code from a subshell run within eval

I have tried looking for a questions similar to this that cover a solution for me, but none that I could find quite answer my exact question.

I would like to run a command within a subshell within an eval call and obtain the status code returned by the function called within the subshell.

For example, I call a command like this:

eval "$(some_command)"
if [ "${?}" -ne 0 ]
then
    # do stuff if `some_command` returned status code not equal to zero
fi

This some_command function returns a list of environment variables and their assignments like this:

$ some_command      # Execute some_command in a standard fashion without eval or subshell
some_env_variable='some_value'
another_env_variable='another value'

The goal is to run this single command to add these environment variable to the current environment. The only way to do that is to call some_command within a subshell, and have eval evaluate the resulting output. If I do this without the subshell, eval will simply run some_command but it will not evaluate it's output to add the environment variable to the current environment.

This works:

$ eval "some_command"
-bash: some_command: command not found
$ echo $?
127

This works:

$ $(some_command)
-bash: some_command: command not found
$ echo $?
127

But this does not work:

$ eval "$(some_command)"
-bash: some_command: command not found
$ echo $?
0

There must be some way of obtaining the resulting status code from some_command, but I have been unable to determine how. Any help is appreciated!

Upvotes: 1

Views: 3057

Answers (1)

chepner
chepner

Reputation: 531345

If you are actually concerned about the exit status, don't use eval immediately.

if envvars=$(some_command); then
    eval "$envvars"
else
    # do something else
fi

If you need the exact error code, instead of just distinguishing between 0 and non-zero:

envvars=$(some_command)
rv=$?  # save it for later if necessary
case $rv in
   0) eval "$envvars" ;;
   1) ... ;;
   2) ... ;;
   # etc
   *) printf 'Some other error %d\n' "$rv" >&2 ;;
esac

Upvotes: 5

Related Questions