Return Codes And Success
Checking command success
When commands exit, they set a hidden variable called the return code
.
Typically, a return code of 0
indicates success, while a return code of any other number indicates failure.
This mechanism is used by most command-line tools in Linux, not just the Ducky Script commands!
Some commands may use return code values to indicate the exact error, while others may simply return 0
or non-zero to indicate success or failure.
Running multiple commands
To run multiple commands, requiring each command succeeds, the &&
operator can be used.
Each of these commands will only run if the previous command completed successfully.
#!/bin/bash
BUTTON 5 && LED G SOLID
The LED
command will only be run if the user presses the button within 5 seconds.
Handling success and failure
To take actions based on success or failure of a command, you can combine the &&
and ||
options.
When a command succeeds, the code in the &&
block is executed. When a command fails, the code in the ||
block is executed.
To demonstrate this, we’ll use the BUTTON
Ducky Script command. BUTTON
takes an optional number of seconds to wait; if the user presses the button within that timeout, a successful return code is set, if the user does not press the button within that timeout, an error return code is set.
#!/bin/bash
BUTTON 5 && {
echo "The button was pressed!";
LED G SOLID;
} || {
echo "The button wasn't pressed!";
LED R SOLID;
}
Notice how we are able to chain &&
and ||
to handle both success and failure.
The {
and }
blocks allow us to group multiple commands.
Reading the return code
The return code of the last command run is stored in the Bash variable $?
#!/bin/bash
ls /i-dont-exist
# Echo the return code (which will be 1)
echo $?
# List a file that does exist
ls /root
# The return code is now 0
echo $?
Setting a return code
Return codes are set in scripts and functions via the exit
or return
codes. When creating your own helper scripts and functions, you can use this to propagate an error code up to the caller. When writing a script use the exit
call, but when writing a function use the return
call!
function do_something() {
if [ "$1" != "do-the-thing" ]; then
# Non-zero means error
return 1
else
# Do the things
return 0
fi
}
do_something && echo "This will never print"
do_something do-the-thing && echo "This will print now"
We’re now able to determine if a function succeeded or failed. We can also use error codes within the function itself to determine if a command we ran succeeded or failed, for example:
function check_dir() {
if [ ! -d "$1" ]; then
return 1
else
return 0
fi
}
check_dir "/usb/some_data_dir" || LED R SINGLE
Make sure to use return
in a function, otherwise the entire script will exit!