Bash is a command language interpreter for the gnu based linux operating systems. Name itself stands for 'Bourne-Again -SHell', which was given as an honorable mention to Stephen Bourne, the author of the direct ancestor of the current unix shell sh. Bash is largely compatible with sh and incorporates useful features from Korn shell ksh and the C shell csh, and while the gnu operating systems provides other shells, bash itself is quite portable and used as a default shell on nearly every version of Unix and Unix-like operating systems.
Unix shell is both programming language and command interpreter, as a command interpreter shell itself provides a lot of useful GNU utilities that can be used for everyday administration tasks. I allows system administrator to focus daily administrative daily work through it and it is even able t0 change how the operating system works. As a programming language it allows all of it's utilities and features to be combined, it allows incorporation of the existing utilities in order to create new ones so that those can become commands themselves. These would be the files to which we refer as scripts. A shell script is a file of executable commands, that have been stored into a text file, when the file itself is ran. Commands in it are executed. Shell scripts have access to all the commands, including logic, therefore a script can be used to test things like presence of file, if an output contains a specific string, value of a variable and based on those result change it's flow accordingly. Scripts are usually built in order to automate repetitive parts of your job, which in return frees your time and ensures your consistency each time that the script is used. Good administrator or programmer will always notice the things that are repetitive in such way and then turn them in script with ease. Let's say that you run same four commands each time you log in, you can put those commands into one script and instead of those four, just run the script and reduce your work. Scripts can be used to automatize tasks of different difficulties. For example script can be as simple as one command with arguments:
echo "Hello, World!"
In order to run hello_world.sh script, that should print a Hello World! string to the console, we need to do the following, either pass the script itself as an argument to your shell, or run it directly.
[bizzarec@localhost BashScripts]$ bash hello_world.sh Hello, world!
As files upon creating don't have the executable right, running a script directly, without it would end up in a permission denied error, in order to execute the script directly, without having to pass it as an argument we need to add executable right to it.
[bizzarec@localhost BashScripts]$ ./hello_world.sh bash: ./hello_world.sh: Permission denied [bizzarec@localhost BashScripts]$ chmod a+x hello_world.sh [bizzarec@localhost BashScripts]$ ./hello_world.sh Hello, world!
As scripts can be ran on various systems, which contain manny shells and on some of them bash might not be the default one, we need to indicate that which particular shell we want to use, we can do so by specifying absolute path to the interpreter, shell that we want to use, in the given manner:
#!/bin/sh #Script used for testing of the bash shell interpreter echo "Hello, World!"
Characters "#!", with pun intended called a shebang when used at the beginning of a script indicate which shell is going to be used, shebang is used in most of the other interpreted languages like Python, Ruby, Perl. Basically any text file as long as it's marked with a shebang on unix like operating systems will try to run under that specific shell, do notice if the script is directly passed to a shell, it doesn't matter what is stated under a shebang. On the other hand character # alone represents a special character inside a script, which serves as a comment, everything behind the # wouldn't get interpreted as a code of the script, it's rather important to use comments if the script itself isn't self explanatory, or if the code itself is large, to better explain what it's supposed to do. Think of it as guidelines for other people that might use your script, and also for yourself. In order to edit a shell script, you can use any text editor that doesn't do formatting of the input, as it could mess with how the text gets interpreted, when doing so via terminal, best ones to use would be nano, vim, vi. For beginners I would recommend nano as a go to text editor, it is rather easy to use, for people up to the task vim or vi would be preferred, as those two have a rather steep learning curve but can be rather powerful if used correctly.
Learning bash needs to start with learning about variables. Variable is a value that can change it's value, depending on conditions or information passed to the program, they are the key of every programming language,
#!/bin/bash FOOD="pizza" echo "I love eating $FOOD" [bizzarec@localhost BashScripts]$ ./variables.sh I love eating pizza
In the script above, = represents a directive used to assigning a value to a variable named FOOD, do note that it is important that there is no space between variable, = and value that we want to assign to the variable. Otherwise it would end up causing an error, as an example let's put a space between variable and value.
#!/bin/bash FOOD = "pizza" echo "I love eating $FOOD" [bizzarec@localhost BashScripts]$ ./variables.sh ./variables.sh: line 3: FOOD: command not found I love eating
Think of the variable as of an empty box which you can use for storing, in this case our box FOOD contains a stored string "pizza", in order to use a variable inside another command, a "$" sign needs to be prepended so that the shell actually interprets it as a variable and not just string. For example, same script from above ran without the prepended $ would result in the following:
[bizzarec@localhost BashScripts]$ ./variables.sh I love eating FOOD
Variables can also contain values of other variables, assigning a value of one variable to another, would go as follows : #!/bin/bash FOOD="pizza" DESERT=$FOOD echo "I love eating FOOD" echo "As a desert i love eating $DESERT" notice that when assing a value right side variable has to have the $ prepended. [bizzarec@localhost BashScripts]$ ./variables.sh I love eating FOOD As a desert i love eating pizza
Another way of assigning value to a variable would be using commands output, as a content of the variable, by simply enclosing the command in the back ticks and in that way passing it's output as a value to variable:
#!/bin/bash NAME=`whoami` echo "Hello $NAME, your home would be this way : $HOME"
In this case we passed the output to the variable NAME, and used it inside, the script, note that the variable $HOME wasn't defined in the script, a convenient thing that can be used inside the script would be system variables, or the ones that have been set inside the environment, you can check system variables via comand `printenv`. It is also possible to get input from the user of the script and assigning it to a variable trough the read command
#!/bin/bash echo -n "What's your name ? " read NAME echo " Hey $NAME, I'd tell you a joke about UDP, but you probably wouldn't get it."
[bizzarec@localhost BashScripts]$ ./readVariable.sh What's your name ? Bojan Hey Bojan, I'd tell you a joke about UDP, but you probably wouldn't get it.
Beside those, there are some special variables that can be passed as arguments when calling a script. $N variables, where N stands for a number of argument passed to the script, $0 is a name of the script itself:
#/bin/bash echo "Hello $1" echo "You've ran the $0"
[bizzarec@localhost BashScripts]$ ./passingVariables.sh Bojan Hello Bojan You've ran the ./passingVariables.sh
Another rather important special variable that is often used would be $?. It holds an exit code of previously ran command/script, and it can be used for testing to check if the command/script/program have finished successfully. Exit status codes have values between 0-255, and most of them have assigned meaning to them. Status code of value 0 means that the command was executed without errors, whilst 1 would be a catchall for general errors:
[bizzarec@localhost BashScripts]$ echo "Testing Status Code" Testing Status Code [bizzarec@localhost BashScripts]$ echo $? 0
A command executed successfully.
[bizzarec@localhost BashScripts]$ cat /etc/shadow cat: /etc/shadow: Permission denied [bizzarec@localhost BashScripts]$ echo $? 1
As we don't have root permission, the cat command didn't execute, and returned a status code of 1 We can also define a status code inside a script:
#!/bin/bash echo "Returning status code of 1" exit 1
[bizzarec@localhost BashScripts]$ ./badStatusCode.sh Returning status code of 1 [bizzarec@localhost BashScripts]$ echo $? 1
If not defined inside a script, and it rans without any command inside of it failing, it will by default return status code of 0, as an example we will use hello_world.sh that we wrote on the start.
[bizzarec@localhost BashScripts]$ ./hello_world.sh Hello, world! [bizzarec@localhost BashScripts]$ echo $? 0
Pretty useful ? There is more to come as we are facing new challenges in our own work environment and decide to share solutions with you.
Fill out the enquiry form and we'll get back to you as soon as possible.