Return codes & 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

# Try to list a directory that doesn't exist
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!

Last updated