11

Sometimes when I run commands it doesn't display an output, so I'm not sure if they've worked or not. Is it possible to make all commands have feedback if they've ran correctly or not? Or at the bare minimum to display feedback id they've ran (correcly or not)

2
  • 6
    The general idea is: no feedback means it worked.
    – Rinzwind
    Apr 1, 2014 at 11:07
  • 1
    This is not exactly true. For example, cryptsetup can by default skip some error messages. It's a good thing to have $? in your PS1. The next step is to add the current time as well, to always know the commands' timings ;)
    – d33tah
    Apr 1, 2014 at 23:57

4 Answers 4

13

To check if some command worked successfully or not you can check the return status, given by $?, of the previous command with:

echo $?

A return status of 0 means the command completed with successfully, while an non-zero output (error code) would mean some problems were encountered or there's an error and the category can be known from the error code. The Linux/C error codes are defined in /usr/include/asm-generic/errno-base.h and /usr/include/asm-generic/errno.h.

Also in bash, the .bashrc defines an alias alert which can be used to notify with the status of completion. You'd have to attach the alias with the command or command combo like this:

some_command --some-switch; alert

You can append the following line of code to your ~/.bashrc file to display the return status of the last command executed..

# show the return code of last command executed
PS1='${debian_chroot:+($debian_chroot)}\u@\h(lst ret. $(echo $?) ):\w\$ '

(open the file ~/.bashrc with text editor of your choice, and copy the above line, paste it in the file and save. Launch a new instance of the terminal, and you should have it in action. Or instead you could define some function and use it with PS1 like like illustrated below.)

a little demo:

hash@precise(lst ret. 0 ):~$ ls -sh someFileThatsNotThere
ls: cannot access someFileThatsNotThere: No such file or directory
hash@precise(lst ret. 2 ):~$ 
hash@precise(lst ret. 2 ):~$ aCommandThatsNot
aCommandThatsNot: command not found
hash@precise(lst ret. 127 ):~$ 
hash@precise(lst ret. 127 ):~$ echo "you should get a lst ret. 0, I believe the system has echo installed :)"
you should get a lst ret. 0, I believe the system has echo installed :)
hash@precise(lst ret. 0 ):~$
hash@precise(lst ret. 0 ):~$ sudo touch /tmp/someTestFile
[sudo] password for hash: 
hash@precise(lst ret. 1 ):~$
hash@precise(lst ret. 1 ):~$ chown $USER:$USER /tmp/someTestFile 
chown: changing ownership of `/tmp/someTestFile': Operation not permitted

Just playing with PS1 :) ..a little more,

function showRetStat {
## line1: initiliazing retStat with the return status of the previous command
retStat=$?
## line2: Left padding the return status with spaces. If you prefer the unpadded one, you can just replace
# $retStatFtd in the lines initializing noErrStr and errStr among other possible ways.
retStatFtd=$(sed -e :a -e 's/^.\{1,2\}$/ &/;ta' <<< $retStat)
## lines3&4: Setting the strings to display for a successful and unsuccessful run of previous command
# which we are going to display with the prompt string. Change the strings to display text of your
# choice like you may set noErrStr="yippie!" , errStr="oopsie!" in place of what they're now.
noErrStr="retStat "$retStatFtd" :: PASS ^_^"
errStr="retStat "$retStatFtd" :: FAIL x_x"
## line5: Applying the logic and display the proper string at the prompt. Space padded number i.e. retStatFtd, here,
# worked in the logic, originally I intended to use this for the display while retStat in the conditional
# check; you could make the function one statement less if you want to.
echo "$([ $retStatFtd = 0 ] && echo "$noErrStr" || echo "$errStr")"
}

## Combining the function showRetStat into the prompt string.
PS1='${debian_chroot:+($debian_chroot)}\u@\h($(showRetStat)):\w\$ '

(you can modify the function to make it more fancy, something like @gronostaj does in his post.)

8
  • 2
    I really like your expanded answer with examples. I'm pretty sure to OP wants xtrace but personally I would find this useful for debugging my own command-line programs as well as better understanding others.
    – Benjamin R
    Apr 1, 2014 at 6:03
  • 1
    I would suggest left-padding the return value, so that it's always the same length.
    – o0'.
    Apr 1, 2014 at 11:00
  • +1 for modifying PS1. This is the one I use, with red number in case of errors, nothing extra if last command succeeded: \[\033[01;41;37m\]${?#0}\[\033[00;01;36m\] \u@\h:\w\[\033[00m\]\$ Apr 1, 2014 at 11:05
  • 1
    @rusty is that no need to source ~/.bashrc file? Apr 1, 2014 at 16:26
  • 2
    Yes, modifying PS1 is helpful and very flexible. I display a happy ^_^ on success, and a red x_x on anything else.
    – Izkata
    Apr 1, 2014 at 18:52
11

(I think since you are posting inside Ask Ubuntu we can assume you are talking about the default shell, that is, Bash.)

There is a very good answer in Stack Overflow question In a shell script: echo shell commands as they are executed (this is not just a Ubuntu-specific solution).

What you need to do is use the set command to turn verbose or xtrace on.

set -o

will give you a list of which current parameters are switched to on or off.

set -v

or the longform version:

set -o verbose

will turn verbose ON.

I think what you want, though, is actually xtrace. This will not only echo every command you run, it will also expand the parameters and give you more feedback. So if I do something as silly as typing 'hi' at the terminal, I will get the echo of what I typed as well as a report/trace of what the shell did to attempt to execute the command 'hi' (see screenshot below):

Enter image description here

To enable xtrace:

set -x

or:

set -o xtrace

To disable these parameters, you (counter-intuitively) call the same commands except with a plus symbol + instead of a dash or minus symbol, so, for example:

set +v

will turn verbose OFF, similarly:

set +x

will turn xtrace OFF.


A detailed guide on shell options is in Chapter 33. Options, Advanced Bash-Scripting Guide.

3
  • 1
    But how does it work when command is correct? does it give any output? say for the command whoami >/dev/null. Apr 1, 2014 at 9:05
  • Yes, of course it does, it echoes what you typed plus any additional parameters involved in the command which were silently called when invoking your command. If you mean, does it print "SUCCESS", then sadly, no, Avinash Raj's answer will do that.
    – Benjamin R
    Apr 1, 2014 at 18:30
  • @PeterMortensen thanks for the nice subtle edits on my answer.
    – Benjamin R
    Apr 2, 2014 at 7:52
5

You can change your command prompt to display a green tick sign when previous command exits with 0 and red X otherwise. Arch Linux Wiki has some nice piece of code to add to your bash.rc:

set_prompt () {
    Last_Command=$? # Must come first!
    Blue='\[\e[01;34m\]'
    White='\[\e[01;37m\]'
    Red='\[\e[01;31m\]'
    Green='\[\e[01;32m\]'
    Reset='\[\e[00m\]'
    FancyX='\342\234\227'
    Checkmark='\342\234\223'

    # Add a bright white exit status for the last command
    #PS1="$White\$? "
    # If it was successful, print a green check mark. Otherwise, print
    # a red X.
    if [[ $Last_Command == 0 ]]; then
        PS1+="$Green$Checkmark "
    else
        PS1+="$Red$FancyX "
    fi
    # If root, just print the host in red. Otherwise, print the current user
    # and host in green.
    if [[ $EUID == 0 ]]; then
        PS1+="$Red\\h "
    else
        PS1+="$Green\\u@\\h "
    fi
    # Print the working directory and prompt marker in blue, and reset
    # the text color to the default.
    PS1+="$Blue\\w \\\$$Reset "
}
PROMPT_COMMAND='set_prompt'

(I have disabled the actual error code because I don't like it, if you'd like to see exact codes just remove # from this line: #PS1="$White\$? ")

Here's how it looks:

GUI Terminal screenshot

tty screenshot

2

Yes, it's possible to get feedback for every command you executed on the terminal.It works on the basis of echo $? which returns 0 for a successful completion of command and any other value other than 0 for failure.

To get the success or failure feedback, add the below line to ~/.bashrc file.

bind 'RETURN: ";if [[ $? == 0 ]]; then tput setaf 6 && echo SUCCESS; tput sgr0; else tput setaf 1 && echo FAILURE; tput sgr0; fi;\n"' 

And then source ~/.bashrc file to make it work.

source ~/.bashrc

Explanation:

For every command you executed on the terminal, this ;if [[ $? == 0 ]]; then tput setaf 6 && echo SUCCESS; tput sgr0; else tput setaf 1 && echo FAILURE; tput sgr0; fi; code will automatically get bind to it.

Example:

$ sudo apt-cache policy firefox;if [[ $? == 0 ]]; then tput setaf 6 && echo SUCCESS; tput sgr0; else tput setaf 1 && echo FAILURE; tput sgr0; fi;
firefox:
  Installed: 24.0+build1-0ubuntu1
  Candidate: 24.0+build1-0ubuntu1
  Version table:
 *** 24.0+build1-0ubuntu1 0
        500 http://ubuntu.inode.at/ubuntu/ saucy/main amd64 Packages
        100 /var/lib/dpkg/status
SUCCESS

$ suda apt-get update;if [[ $? == 0 ]]; then tput setaf 6 && echo SUCCESS; tput sgr0; else tput setaf 1 && echo FAILURE; tput sgr0; fi;
No command 'suda' found, did you mean:
 Command 'sudo' from package 'sudo-ldap' (universe)
 Command 'sudo' from package 'sudo' (main)
 suda: command not found
FAILURE

enter image description here

2
  • 1
    bind 'RETURN: " && echo SUCCESS || echo FAILED \n"' will also do the same, you do not need to check [[ $? == 0 ]] explicitly.
    – sourav c.
    Apr 1, 2014 at 15:37
  • However, the C/Linux standard and the English grammar standard counterpart to 'Success' would be FAILURE.
    – Benjamin R
    Apr 1, 2014 at 18:55

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .