11

I have this in a bash script:

exit 3; exit_code="$?" if [[ "$exit_code" != "0" ]]; then echo -e "${r2g_magenta}Your r2g process is exiting with code $exit_code.${r2g_no_color}"; exit "$exit_code"; fi 

It looks like it will exit right after the exit command, which makes sense. I was wondering is there some simple command that can provide an exit code without exiting right away?

I was going to guess:

exec exit 3 

but it gives an error message: exec: exit: not found.  What can I do? :)

6
  • 1
    Yeah exec exit 3 is no bueno, I get "exec: exit: not found"
    – user287203
    CommentedDec 9, 2018 at 8:34
  • 8
    I don't understand the question. Why not set exit_code=3 and eliminate the exit 3 line altogether?
    – wjandrea
    CommentedDec 9, 2018 at 18:25
  • @wjandrea is more a conceptual question than practical
    – user287203
    CommentedDec 10, 2018 at 1:03
  • 3
    It still makes no sense to me. Why would there be an exit code if you don't actually exit?
    – Barmar
    CommentedDec 10, 2018 at 5:09
  • 1
    @Barmar every process has an exit code. Most of the people trying to answer the question are interpreting the question to mean "what can I replace the 'exit 3' with in the script so it sets the $? variable but doesn't exit this script"?
    – icarus
    CommentedDec 10, 2018 at 18:32

5 Answers 5

32

If you have a script that runs some program and looks at the program's exit status (with $?), and you want to test that script by doing something that causes $? to be set to some known value (e.g., 3), just do

(exit 3) 

The parentheses create a sub-shell.  Then the exit command causes that sub-shell to exit with the specified exit status.

2
12

exit is a bash built-in, so you can't exec it. Per bash's manual:

Bash's exit status is the exit status of the last command executed in the script. If no commands are executed, the exit status is 0.

Putting all this together, I'd say your only option is to store your desired exit status in a variable and then exit $MY_EXIT_STATUS when appropriate.

2
  • hmmm what do you think about @G-man's idea?
    – user287203
    CommentedDec 9, 2018 at 8:52
  • 2
    Maybe I misunderstood what you're trying to accomplish. If you're just trying to set $? (though I'm not really sure why you would), that does seem like a solid answer. If you just want to set it to some unsuccessful value, false is another option.CommentedDec 9, 2018 at 9:04
10

You can write a function that returns the status given as argument, or 255 if none given. (I call it ret as it "returns" its value.)

ret() { return "${1:-255}"; } 

and use ret in place of your call to exit. This is avoids the inefficiency of creating the sub-shell in the currently accepted answer.

Some measurements.

time bash -c 'for i in {1..10000} ; do (exit 3) ; done ; echo $?' 

on my machine takes about 3.5 seconds.

 time bash -c 'ret(){ return $1 ; } ; for i in {1..10000} ; do ret 3 ; done ; echo $?' 

on my machine takes about 0.051 seconds, 70 times faster. Putting in the default handling still leaves it 60 times faster. Obviously the loop has some overhead. If I change the body of the loop to just be : or true then the time is halved to 0.025, a completely empty loop is invalid syntax. Adding ;: to the loop shows that this minimal command takes 0.007 seconds, so the loop overhead is about 0.018. Subtracting this overhead from the two tests shows that the ret solution is over 100 times faster.

Obviously this is a synthetic measurement, but things add up. If you make everything 100 times slower than they need to be then you end up with slow systems. 0.0

2
  • 2
    @iBug The extra space is not needed.
    – icarus
    CommentedDec 9, 2018 at 13:15
  • Good point about the inefficiency of creating the sub-shell.  I've read that some shells might be smart enough to optimize the fork out in cases like this, but that bash isn't one of them.CommentedDec 9, 2018 at 19:38
3

About exec exit 3... it would try to run an external command called exit, but there isn't one, so you get the error. It has to be an external command instead of one built in to the shell, since execreplaces the shell completely. Which also means that even if you had an external command called exit, exec exit 3 would not return to continue your shell script, since the shell wouldn't be there any more.

2
  • 1
    I guess you could do exec bash -c "exit 3", but at the moment I can't think of any reason to do that as opposed to just exit 3.
    – David Z
    CommentedDec 9, 2018 at 15:45
  • 1
    @DavidZ, in any case, exec'ing or just exit'ing will stop the script, which didn't seem like what the question wanted.
    – ilkkachu
    CommentedDec 9, 2018 at 17:16
3

You can do this with Awk:

awk 'BEGIN{exit 9}' 

Or Sed:

sed Q9 /proc/stat 
2
  • ...or with a shell: sh -c 'exit 9'
    – ilkkachu
    CommentedDec 9, 2018 at 17:27
  • 1
    @ilkkachu if youre going to do that you might as well do the (exit 9) in the accepted answer
    – Zombo
    CommentedDec 9, 2018 at 18:44

You must log in to answer this question.