To write an effective script in shell, it is very important to know about the different utilities that shell provides. Similar to other programming languages, shell programming also requires a way to specify skipping or running certain commands under certain conditions. To perform a certain task on the list of elements, looping constructs are needed in shell as well.
In this chapter, we will cover topics such as if
, else
, case
, and select
that can be used to run a certain block of commands according to the condition. We will see the for
, while
, and until
constructs, which are used to loop over a certain block of commands in a script. We will see how the exit code, after the execution of a command or script, plays an important role in knowing whether a command was executed successfully or not. We will also see how a function can be defined in shell, which will allow us to write modular and reusable code from now on.
This chapter will cover the following topics in detail:
if
and else
for
select
, while
, and until
loopsstdout
as a parameter using xargs
pushd
and popd
We are now well familiar with shell script files, commands, and running them in bash
to get the desired output. Until now, whatever shell script examples we have seen, they run line by line until the end of the file. While writing real-world shell scripts, it may not always be the case. We may need to exit a script in between, for example, when some error occurs, doesn't satisfy a certain condition, and so on. To exit from the script, the exit
shell builtin is used with an optional return value. The return value tells the exit code, which is also known as return status or exit status.
Every command returns an exit code when it gets executed. Exit code is one of the ways to know whether a command is executed successfully or if some error has occurred. As per the
POSIX (Portable Operating System Interface) standard convention, a command or program with successful execution returns 0
, and 1
or a higher value for failed execution.
In bash, to see the exit status of the last command executed, we can use "$?
".
The following example shows the exit code of the successful command execution:
$ ls /home # viewing Content of directory /home foo
Now, to see the exit code of the last executed command, that is, ls /home
, we will run the following command:
$ echo $? 0
We see that the exit status of the ls
command execution is 0
, which means it has executed successfully.
Another example showing the exit code of the unsuccessful command execution is as follows:
$ ls /root/ ls: cannot open directory /root/: Permission deniedWe see that the ls command execution was unsuccessful with the Permission denied error. To see the exit status, run the following command:
$ echo $? 2
The exit status code is 2
, which is higher than 0
, representing unsuccessful execution.
In different situations, a different exit code is returned by a script or command. Knowing the meaning of the exit code is useful while debugging a script or command. The following table explains which exit code is conventionally returned in different conditions of command or script execution:
Exit code |
Description |
---|---|
0 |
Successful execution |
1 |
General error |
2 |
Error when using shell builtin commands |
126 |
Permission issues while executing a command; we can't invoke the requested command |
127 |
Could not invoke requested command |
128 |
Specifying invalid argument to exit in script. Only value from 0 to 255 is valid exit code |
128+n |
Fatal error with the signal 'n' |
130 |
Terminating script using Ctl + C |
255* |
Out of the range exit code |
Exit codes 0, 1, 126-165, and 255 are reserved and we should use other than these numbers when we return the exit code in script files.
The following examples show the different exit codes returned by commands:
echo
command:$ echo "Successful Exit code check" Successful Exit code check $ echo $? 0
/root
have no permissions as shown:$ cp -r /root/ . cp: cannot access '/root/': Permission denied $ echo $? 1
$ echo ;; bash: syntax error near unexpected token ';;' $ echo $? 2
/usr/bin
directory as a command that is actually not a command:$ /usr/bin bash: /usr/bin: Is a directory $ echo $? 126
foo
that is not actually present in the system:$ foo bash: foo: command not found $ echo $? 127
$ read ^C $ echo $? 130
Here, Ctrl + C sends the SIGQUIT
signal whose value is 2
. So, the exit code is 130
(128 + 2).
We can also exit shell builtin along with an exit code to know whether a script ran successfully or it encountered any error. Different error codes can be used to know the actual reason of an error while debugging your own script.
When we don't provide any exit code in a script, the exit code of the script is determined by the last executed command:
#!/bin/bash # Filename: without_exit_code.sh # Description: Exit code of script when no exit code is mentioned in script var="Without exit code in script" echo $var cd /root
The preceding script doesn't specify any exit code; running this script will give the following output:
$ sh without_exit_code.sh Without exit code in script without_exit_code.sh: line 8: cd: /root: Permission denied $ echo $? # checking exit code of script 1
The exit code of this script is 1
because we didn't specify any exit code and the last executed command was cd /root
, which failed due to a permission issue.
Taking the next example that returns the exit code 0
, irrespective of any error that occurs—that is, script ran successfully:
#!/bin/bash # Filename: with_exit_code.sh # Description: Exit code of script when exit code is mentioned in scr# ipt var="Without exit code in script" echo $var cd /root exit 0
Running this script will give the following result:
$ sh with_exit_code.sh Without exit code in script with_exit_code.sh: line 8: cd: /root: Permission denied echo $? 0
Now, the script file returns the exit code as 0
. We now know what a difference adding an exit code in script can make.
Another example with the exit status code is as follows:
#!/bin/bash # Filename: exit_code.sh # Description: Exit code of script cmd_foo # running command not installed in system echo $? cd /root # Permission problem echo $? echo "Hello World!" # Successful echo print echo $? exit 200 # Returning script's exit code as 200
The output after running this script is as follows:
$ sh exit_status.sh exit_code.sh: line 5: cmd_foo: command not found 127 exit_code.sh: line 8: cd: /root: Permission denied 1 Hello World! 0 $ echo $? # Exit code of script 200
If no exit code is specified in a script, the exit code will be the exit status of the last command ran in the script.
18.218.153.50