elif
is a portmanteau consisting of the words "else" and "if". In bash (and Python), it's a way to test multiple statements before closing a loop, as opposed to the single statement test provided by else
. If a typical if/then construct uses an if/then/else format, elif allows for if/then/elif/then/else.
Here is a simple example that will try to start mysql if mariadb is active on the system, psql if postgresql is active on the system. Below the example is a breakdown of what each line does:
[user@host ~]$ systemctl is-active mariadb > /dev/null 2>&1
MARIADB_ACTIVE=$?
[user@host ~]$ systemctl is-active postgresql > /dev/null 2>&1
POSTGRESQL_ACTIVE=$?
[user@host ~]$ if [ "$MARIADB_ACTIVE" -eq 0 ]; then
> mysql
> elif [ "$POSTGRESQL_ACTIVE" -eq 0 ]; then
> psql
> else
> echo "Nuts, all outta databases here!"
> fi
- This line asks
systemctl
to check if themariadb
serviceis-active
, and to send any output (error or otherwise) to/dev/null
, or nowhere.
Fun Fact:2>&1
Refers to something very basic about how Unix systems operate: standard input (stdin), standard output (stdout) and standard error (stderr).
stdin (0) is a keyboard - what you use to input information
stdout (1) is the terminal - where output is displayed
stderr (2) are errors.
So2>&1
is saying to send any errors (2) from this command to the same location as standard output (1), which in this case is /dev/null, the black hole of all Linux filesystems. - Set a variable called
MARIADB_ACTIVE
, the value of which is the result of$?
, which returns exit codes from the immediately previous command. Ifmariadb
was active, the exit code would be0
. If it's not running, or not installed, it would be another number, between 1 and 255. In this instance,mariadb
is not installed, so the exit code is3
.
Unfamiliar with exit codes? In bash, you can check the exit code of the previous command by typingecho $?
, which will output EITHER a 0 or any other number. If the previous command was successful, you always get a 0. Any other number is a fail. - Ask
systemctl
to check if thepostgresql
serviceis-active
and send any output (and errors) to/dev/null
. - Set a variable called
POSTGRESQL_ACTIVE
with the value of the exit code$?
for the command from the previous line. In this instance,postgresql
is also not installed, so the exit code is3
. - If/then loop using a
test
expression. This is saying thatif
the value of the variableMARIADB_ACTIVE
is equal (-eq
) to0
,then
- Run
mysql
if the previous line can be processed. In this instance, the value ofMARIADB_ACTIVE
is3
, so the test failed, and we go to the next line: elif
(else if) the previous command failed, try anothertest
expression - in this case,if
the value ofPOSTGRESQL_ACTIVE
is equal (-eq
) to0
, then- Run
psql
if thetest
expression succeeded - it didn't, because the value ofPOSTGRESQL_ACTIVE
is3
, so we go to the next line: else
- ifelif
failed and can't runpsql
on the previous line, go to the next line- Neither mariadb nor postgresql is installed, so we're just going to output text that says
"Nuts, all outta databases around here!"
. fi
- The inverse of if and closes out the if/then loop.
Just for super geeky funsies, let's write a bash script to cover Bilbo's thought processes about taking the ring back at Rivendell, using elif
:
systemctl is-active mordor-desire > /dev/null 2>&1
MORDOR_DESIRE=$?
systemctl is-active wanna-turn-into-a-gollum /dev/null 2>&1
GOLLUM_DESIRE=$?
if [ "$MORDOR_DESIRE" -eq 0 ]; then
> echo "I'm going on an adventure!"
> elif [ "$GOLLUM_DESIRE" -eq 0 ]; then
> echo "REEEEEEEEEEEEEE"
> else
> echo "I'm sorry that you must carry this burden"
> fi