3

Supposing someone invokes a non-existent command, the only way I know to retrieve its error status from a script I execute right after is by using source

I.e., let's say this script's name is dummy where its contents are simply

#!/bin/bash

echo $?

I know I will only get the exit status I'm looking for (127) if I invoke source dummy, but is there another way to facilitate getting the exit status (preferably without using alias) from the last command from within the script, without using source so I could simply call dummy to get my desired behaviour?

I am simply trying to make a script to check for a typo in the previous command. This requires detecting the previous exit status to make sure there was a potential typo in the first place, so I need to be able to get the exit status of the last command from within the script. I am also hoping to minimize the amount of setup a user would have to do, so that a user could simple invoke dummy, for example, and the rest would be taken care of. This is my reason for trying to avoid source or ., or alias.

My initial test for exit status of the last command was to use

#!/bin/bash
ESTATUS=$? # Saved exit status for later
echo $ESTATUS

but this required having to run that script with source. Is there a good way to replicate this without having to use source, or .?

  • Is your intended user someone writing a script or someone interactive at the terminal? Would a possible solution include modifying their prompt to include the exit status of the previous command? If so you might want to look at stackoverflow.com/questions/5946873/… – Eric Renouf Apr 24 '15 at 13:21
  • My intended user is someone interactive at the terminal. That would solve the problem, but ideally all the user would have to do is call the script without side-effects on their system that they might be unaware of. – Francesco Gramano Apr 24 '15 at 13:26
1

I'm not quite sure where that will lead to, but you can do:

alias dummy='sh dummy $?'
the_program_with_errors
dummy

and your dummy script would contain:

echo $1

An approach without alias is to use a shell function:

function dummy { sh dummy $? ;}

With that definition you can get the following behaviour (simulated with true, false, and a subshell process):

$ true 
$ dummy
0
$ false
$ dummy
1
$ (exit 42)
$ dummy    
42
  • I get that your solution is to give $? as a parameter but can this be avoided? And I am looking for a solution that preferably does not use an alias either. – Francesco Gramano Apr 24 '15 at 12:46
  • @Francesco; There must be some way how to pass the exit status; you have to bite the bullet and choose one. If you have any further restrictions, please explain which ones and also why; so that appropriate solutions can be proposed (or identified if it's not possible). Also please explain why, in the first place, you want that $? test in this convoluted way. - I've got the feeling that you may want something in a specific convoluted way where there's a more sophisticated standard. - To avoid aliases the usual answer is: use a shell function. – Janis Apr 24 '15 at 12:56
  • I'll edit my question to reflect the reason I need $? to behave this way. – Francesco Gramano Apr 24 '15 at 12:58
  • @Francesco; I added the function based approach to reflect your additional requirement. – Janis Apr 24 '15 at 13:04
  • 1
    @Francesco; Yes, with that comment it's fairly clear; you want a short setup like 'x', and a short invocation like 'y', and demand a couple other restrictions. - I dare to say that there's no such beast. - Good luck! – Janis Apr 25 '15 at 0:52
2

You could perhaps use the script at https://github.com/rcaloras/bash-preexec (as discussed at https://superuser.com/questions/175799/does-bash-have-a-hook-that-is-run-before-executing-a-command) and use the precmd() function to do your $? checking

  • I was hoping to stick to built-ins but I like the possibility of adding pre-execution hooks, so I upvoted this answer for now and I'll just wait in case there are any other answers. – Francesco Gramano Apr 25 '15 at 1:00
1

It sounds to me as if the scripts that you are calling should provide the responses that you desire. Here's a way to test for a command and use a specific exit code in those scripts.

#!/bin/bash

# Test for the existence of a command in the path.
command=typo_command
if [[ ! $(command -v $command) ]]; then
    echo "$command does not exist"
    exit 127 # or the code you choose
fi
  • The problem with this solution is that I need to set command to reflect the last executed command, but trying to use history from a script (without using source) is giving me undesired behaviour even after trying cominations of set -o history, shopt -s histappend, etc – Francesco Gramano Apr 24 '15 at 20:55
  • So is !! but my issue also involves the persistence of the history command or the ~/.bash_history between detached process. – Francesco Gramano Apr 24 '15 at 23:10
1

Write a function

Your shell is one process, and has a value for $?. Your script is a separate, child process, and has its own value for $?.

If you want to be able to check the $? belonging to your shell, you need your command to run in the shell process. source is one way to do that, but a simpler way is to write a function.

function dummy(){
  echo $?
}

If declared in the user's .bashrc or equivilant, this should be available and work as you expect.

(If you want, it could even call out to a script to do whatever else you want, and pass to the script the value of $?.)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.