- Classic SysAdmin: Writing a Simple Bash Script
- Starting Off
- Variables
- Taking Input
- How to write simple shell scripts in Linux
- Table of contents
- Introduction to Shell
- Use different interpreter in script file
- How to provide permission to run script file
- Variables
- Loop statements in bash script
- Condition statements in bash script
- Functions
- Some necessary operators
- Installing packages in Ubuntu
- Wrapping up
Classic SysAdmin: Writing a Simple Bash Script
This is a classic article written by Joe “Zonker” Brockmeier from the Linux.com archives. For more great SysAdmin tips and techniques check out our free intro to Linux course.
The first step is often the hardest, but don’t let that stop you. If you’ve ever wanted to learn how to write a shell script but didn’t know where to start, this is your lucky day.
If this is your first time writing a script, don’t worry — shell scripting is not that complicated. That is, you can do some complicated things with shell scripts, but you can get there over time. If you know how to run commands at the command line, you can learn to write simple scripts in just 10 minutes. All you need is a text editor and an idea of what you want to do. Start small and use scripts to automate small tasks. Over time you can build on what you know and wind up doing more and more with scripts.
Starting Off
Each script starts with a “shebang” and the path to the shell that you want the script to use, like so:
The “#!” combo is called a shebang by most Unix geeks. This is used by the shell to decide which interpreter to run the rest of the script, and ignored by the shell that actually runs the script. Confused? Scripts can be written for all kinds of interpreters — bash, tsch, zsh, or other shells, or for Perl, Python, and so on. You could even omit that line if you wanted to run the script by sourcing it at the shell, but let’s save ourselves some trouble and add it to allow scripts to be run non-interactively.
What’s next? You might want to include a comment or two about what the script is for. Preface comments with the hash (#) character:
Let’s say you want to run an rsync command from the script, rather than typing it each time. Just add the rsync command to the script that you want to use:
#!/bin/bash # rsync script rsync -avh --exclude="*.bak" /home/user/Documents/ /media/diskid/user_backup/Documents/
Save your file, and then make sure that it’s set executable. You can do this using the chmod utility, which changes a file’s mode. To set it so that a script is executable by you and not the rest of the users on a system, use “chmod 700 scriptname” — this will let you read, write, and execute (run) the script — but only your user. To see the results, run ls -lh scriptname and you’ll see something like this:
-rwx------ 1 jzb jzb 21 2010-02-01 03:08 echo
The first column of rights, rwx, shows that the owner of the file (jzb) has read, write, and execute permissions. The other columns with a dash show that other users have no rights for that file at all.
Variables
The above script is useful, but it has hard-coded paths. That might not be a problem, but if you want to write longer scripts that reference paths often, you probably want to utilize variables. Here’s a quick sample:
#!/bin/bash # rsync using variables SOURCEDIR=/home/user/Documents/ DESTDIR=/media/diskid/user_backup/Documents/ rsync -avh --exclude="*.bak" $SOURCEDIR $DESTDIR
There’s not a lot of benefit if you only reference the directories once, but if they’re used multiple times, it’s much easier to change them in one location than changing them throughout a script.
Taking Input
Non-interactive scripts are useful, but what if you need to give the script new information each time it’s run? For instance, what if you want to write a script to modify a file? One thing you can do is take an argument from the command line. So, for instance, when you run “script foo” the script will take the name of the first argument (foo):
Here bash will read the command line and echo (print) the first argument — that is, the first string after the command itself.
You can also use read to accept user input. Let’s say you want to prompt a user for input:
#!/bin/bash echo -e "Please enter your name: " read name echo "Nice to meet you $name"
That script will wait for the user to type in their name (or any other input, for that matter) and use it as the variable $name. Pretty simple, yeah? Let’s put all this together into a script that might be useful. Let’s say you want to have a script that will back up a directory you specify on the command line to a remote host:
#!/bin/bash echo -e "What directory would you like to back up?" read directory DESTDIR= This e-mail address is being protected from spambots. You need JavaScript enabled to view it :$directory/ rsync --progress -avze ssh --exclude="*.iso" $directory $DESTDIR
That script will read in the input from the command line and substitute it as the destination directory at the target system, as well as the local directory that will be synced. It might look a bit complex as a final script, but each of the bits that you need to know to put it together are pretty simple. A little trial and error and you’ll be creating useful scripts of your own.
Of course, this is just scraping the surface of bash scripting. If you’re interested in learning more, be sure to check out the Bash Guide for Beginners.
Ready to continue your Linux journey? Check out our free intro to Linux course!
How to write simple shell scripts in Linux
In this article, we will learn the most basic knowledge to program with bash script. Understanding them makes us strong into shell scripting.
Table of contents
Introduction to Shell
A Shell is a program that works between us and the Linux system, enabling us to enter commands for the OS to execute.
In Linux, the standard shell is bash — the GNU Bourne-Again SHell, from the GNU suite of tools, is installed in the /bin/sh. In the most Linux distributions, the program /bin/sh, the default shell, is actually a link to the program /bin/bash.
Belows are some shell programs that we can use.
Shell Name | history |
---|---|
sh (Bourne) | The original shell from early version of UNIX |
csh, tcsh, zsh | The C shell, and its derivatives, originally created by Bill Joy of Berkeley UNIX fame. The C Shell is probably the third most popular type of shell after bash and the Korn shell |
ksh, pdksh | The Korn shell and its public domain cousin. Written by David Korn, this is the default shell on many commercial UNIX versions. |
bash | The Linux staple shell from the GNU project. bash, or Bourne Again SHell, has the advantage that the source code is freely available, and even if it’s not currently running on our UNIX system, it has probably been ported to it. bash has many similarities to the Korn shell. |
Use different interpreter in script file
#!/bin/bash echo "Hello, world!" echo "User - $USER, Directory - $HOME"
The #! characters tell the system that the argument that follows on the line is the program to be used to execute this file.
#!/bin/bash or #!/usr/bin/python is known as hash bang, or shebang. Basically, it just tells the shell which interpreter to use to run the commands inside the script.
How to provide permission to run script file
To run our script file, there are two ways:
- Invoke the shell with the name of the script file as a parameter For example, /bin/sh hello-world.sh
- Running our script file by calling its name Before doing it, we need to change the file mode to make the file executable for all users by using the chmod command.
Variables
- The declaration of variables In Linux, we do not need to declare variables in the shell before using them. The easiest way is that when we want to use them, create them such as assigning an initial value to them. By default, all variables are stored as strings, even when they are assigned numeric values. The shell and some utilities will convert numeric strings to their values in order to operate on them as required.
- Access their value To get the the variables’s value, we insert $ symbol before their name. For example:
strHelloWorld="hello world" echo $strHelloWorld
- The behavior of variables inside quotes depends on the type of quotes we use.
- If we enclose a $ variable expression in double quotes, then it’s replaced with its value when the line is executed.
- If we enclose it in single quotes, then no substitution takes place.
- We can remove the special meaning of the $ symbol by prefacing it with a **.
#!/bin/sh str="Hello, world!" echo $str echo "$str" echo '$str' echo \$str
Loop statements in bash script
while [ condition ] do commands done
#!/bin/bash valid=true count=1 while [ $valid ] do echo $count if [ $count -eq 10 ]; then break # continue fi ((count++)) done
for var in do commands done
#!/bin/bash names='Obama Trump Clinton' for name in $names do echo $name done echo 'Done.'
until [ condition ] do commands done
#!/bin/bash counter=1 until [ $counter -gt 5 ] do echo $counter ((counter++)) done
for value in 1..5> do echo $value done
Condition statements in bash script
if [ conditionals ]; then commands fi
if [ conditionals ]; then commands elif [ conditionals ]; then commands else commands fi
#!/bin/bash # $1 means the first command line argument if [ $1 -gt 100 ]; then echo 'Your number is greater than one hundred.' pwd fi date
#!/bin/bash if [ "$1" -gt 100 ]; then echo Hey that\'s a large number if (( $1 % 2 == 0 )) then echo And is also an even number fi fi
#!/bin/bash # use && or || to express boolean operations if [ -r $1 ] && [ -s $1 ] then echo 'This file is existed and can be read.' fi
case in ) commands ;; ) commands ;; esac
case $1 in start) echo 'starting' ;; stop) echo 'stopping' ;; restart) echo 'restarting' ;; *) # * represents any number of any characters. echo 'do not know' ;; esac
Functions
function_name() commands > # or function function_name commands >
- Parameter variables If no parameters are passed, the environment variable $# exists but has a value of 0. Belows are some parameter variables that we need to know.
Parameter variable Description $1, $2, … The parameters given to the script $* A list of all the parameters, in a single variable, seperated by the first character in the environment variable IFS. If IFS is modified, then the way $* seperates the command line into parameters will change. $@ A subtle variation on $*; it does not use the IFS environment variable, so parameters are not run together even if IFS is empty - Pass arguments and return value to function We supply the arguments directly after the function name. In function, we can access the value of arguments by using $1 , $2 , … We will use keyword return to return our something.
print_value() echo "Hello $1" return 10 > print_value world # Use #? contains the return status of the previously run command or function. echo "The returned value from above function is $?" # or value=$( print_value VietNam )
#!/bin/bash calc_tax() local tax_percent=0.1 return $1 * tax_percent > calc_tax 100
Some necessary operators
- Comparation opertor = = used to compare two string != = used to compare two string -eq = check whether the value is equal to something. -ne = not equal -gt = greater than -ge = greater than or equal -lt = less than -n STRING = The length of STRING is greater than zero. -z STRING = The length of STRING is zero. = is slightly different to -eq . [ 001 = 1 ] will return false as = does a string comparison (ie. character for character the same) whereas -eq does a numerical comparison meaning [ 001 -eq 1 ] will return true.
- File operator -d FILE = FILE exists and is a directory -e FILE = FILE exists -r FILE = FILE exists and the read permission is granted. -s FILE = FILE exists and its size is greater than zero -w FILE = FILE exists and the write permission is granted. -x FILE = FILE exists and the execute permission is granted. When we refer to FILE above we are actually meaning a path. Remember that a path may be absolute or relative and may refer to a file or a directory.
Installing packages in Ubuntu
#!/bin/bash # Install Apache if it's not already present if [ -f /usr/sbin/apache2 ]; then sudo apt install -y apache2 sudo apt install -y libapache2-mod-php7.2 sudo a2enmod php sudo systemctl restart apache2 fi
- Check for existence of the apache2 library Use -f option specifies that we’re looking for a file. If we want to check for existence of a directory, use -d option. ! operator — exclamation mark is an inverse, it means we’re checking if something is not present.
- Install packages We can use -y option to omit some confirmation that process’s installing package is required.
- if statement We should close out if statement with the word fi backward — fi . If we forgot to do this, the script will fail.
Wrapping up
- Understanding some basic statements and operators in Bash script.
- Split function into smaller function to help us easily maintainable and readable code.