Shell Script #0 - (Introduction)
#! Shell Scripting
Note: Since the only shell I am familiar with is "bash", in this series, we will mostly work with bash.
GitHub repository where I share code examples: Shell Scripting 101
What is Shell?
The interface that allows us to use the operating system is called the "shell". Shells can be GUI or TUI. When you think of a shell, don't just think of text running on a black screen. However, when we look at common usage, if a process is done using a graphical interface, with a mouse, seeing icons, etc., we see that this environment is referred to as GUI. In cases where there is no graphical interface, you will encounter terms such as shell, terminal, console, serial connection, CLI (Command Line Interface). And then you also hear "bash"... Calling shell bash is like calling a razor blade "Gilette" or a tissue "Selpak". Don't do that.
What is Shell Script?
Shells are interactive. You type something and get a response. But sometimes these tasks become routine, and you no longer want to see the response. The outcomes are quite predictable. For example, you want to delete all files with the "PNG" extension in a directory. That's your only goal. When you run the related command, those files - if any - will be deleted. Let's think of a different scenario. You want the "tmp" extension files in a directory to be deleted every 3 hours. Let's make things a bit more interesting. You want the logs of your web server to be archived, compressed, moved to another location, and the original log files deleted every 24 hours. The process is always the same, the expectations are always the same, the tools used are always the same. Is there a way to automate this?
This is where "shell programming" or "shell scripts" comes in. Shell programming is actually a bit tricky. Because there is no program involved. There is a text file containing commands (instructions). This file is given to a program (such as bash) that can interpret it, and the commands are executed. A shell script is essentially a text file containing commands that will be executed by a shell.
Content of a Shell Script
In fact, what you write in your shell forms the content of your shell script.
A shell script can contain the built-in commands of the relevant shell, such as "echo", "pwd". Don't jump to conclusions when you see "pwd". pwd is both a program and a bash built-in (bash internal).
Programs known as "Linux commands", but actually "GNU/Linux programs" like ls, cp, mv, grep can be used in shell scripts. The important thing to note here is that the programs and path settings in the environment where the script is written should be consistent with the programs and path settings in the environment where it will be executed. For example, you may have written a shell script using the "mv" program to rename some files. Let's assume I renamed the "mv" program to "degistir" on my device. Therefore, your script will not work on my device. On the other hand, if I renamed "mv" to "degistir", I probably don't deserve to run anything anymore :)
Of course, as with other scripts, decision structures (like if - else), loops (for, while), variables will be created, and mathematical operations will be performed.
GNU Bash
Before we move on to GNU Bash, let's talk about the Bourne Shell (sh)1. The Bourne Shell is a command-line interface (CLI) written for use in operating systems. Its development began in 1976, and it was first used in Version 7 Unix in 1979. It was developed by Stephen Bourne.
GNU Bash (Bourne-Again SHell)2, on the other hand, is a new shell compatible with sh. It was developed as part of the GNU project. It introduced features like command-line editing, unlimited command history, and mathematical operations in all bases from 2 to 64.
GNU Bash is the default shell in many GNU/Linux distributions.
Our First Script
We said that shell scripts are text files. What we need to do is write the necessary commands into a text file, save it, and run it. When we look at scripting languages, we see that they require an interpreter. For example, to run a JavaScript file, we need a web browser. To run a Python script, we run a command like "python test.py", and we execute our code with the Python interpreter. We will do something similar for our shell script.
Creating and Running the Script
To print a message on the screen in the bash environment, we use the "echo" command.
Now, if we were to explain it plainly, we would say, "Friends, you can put text in single or double quotes." But we don't say that. Because this doesn't always work that way, really. That's why we try, that's why we test, that's why we try to learn things in more depth. Please examine the output below:[root@localhost ~]# echo Shell scripting öğreniyoruz
Shell scripting öğreniyoruz
[root@localhost ~]# echo 'Shell scripting öğreniyoruz'
Shell scripting öğreniyoruz
[root@localhost ~]# echo "Shell scripting öğreniyoruz"
Shell scripting öğreniyoruz
[root@localhost ~]# echo 'Shell scripting öğreniyoruz!'
Shell scripting öğreniyoruz!
[root@localhost ~]# echo "Shell scripting öğreniyoruz!"
-bash: !": event not found
We used echo without any marks. No problem occurred. We also used it with single and double quotes. Again, no problem occurred. We added an exclamation mark at the end of our sentence. No problem with single quotes, but double quotes failed :) So why?
Let's examine the output above. We can write "Shell script!" without any quotation marks and with single quotation marks. There is also the exclamation mark. However, we couldn't write it with double quotes. Look at the error we got, "event not found". What does "event" mean? The "!" symbol is used in bash - and actually in different shells as well - to refer to "history". After the exclamation mark, you run the last command that started with the characters you typed. If you want, you can also continue with a number to run the command from that line in the history list, like !127.
Looking at the example above, here's what we see. The last successfully executed command is the message written in single quotes on line 3. The example with double quotes on line 5 gave an error. In line 7, we used "!ec". This means "run the last successful command that started with ec". After "!ec", the last successful command that started with ec was shown and executed. Since the exclamation mark tried to run something that started with the character following it, and we gave it that character as a double quote, it couldn't succeed and gave an error. As you can see, we didn't have such an issue with single quotes.
Now, let's prepare a bash script that will write some messages one after another:
[root@localhost bashscript]# vi echo_ornegi.sh
[root@localhost bashscript]# cat echo_ornegi.sh
echo Alti üstü beş metreydi
echo dertlerinin birikimi
echo Belki biter dedin ama
echo sen kaparsan gözlerini
[root@localhost bashscript]#
We know that "echo" will print a message. I created a file named "echo_ornegi.sh" using a text editor (in this example, vi). I also displayed what I wrote inside it using the "cat" command. Let's see what happens when we run it.
[root@localhost bashscript]# bash echo_ornegi.sh
Alti üstü beş metreydi
dertlerinin birikimi
Belki biter dedin ama
sen kaparsan gözlerini
[root@localhost bashscript]#
As you can see, I sent the script file I wrote as a parameter to the bash program, and it ran successfully.
[root@localhost bashscript]# bash echo_ornegi.sh
Alti üstü beş metreydi
dertlerinin birikimi
Belki biter dedin ama
sen kaparsan gözlerini
[root@localhost bashscript]# ls -l echo_ornegi.sh
-rw-r--r--. 1 root root 113 Eki 28 14:53 echo_ornegi.sh
[root@localhost bashscript]# echo_ornegi.sh
-bash: echo_ornegi.sh: komut yok
[root@localhost bashscript]# ./echo_ornegi.sh
-bash: ./echo_ornegi.sh: Erişim engellendi
[root@localhost bashscript]# file echo_ornegi.sh
echo_ornegi.sh: UTF-8 Unicode text
[root@localhost bashscript]#
Let's examine the above output step by step:
- We ran the script with
bash echo_ornegi.sh. No issues appeared. - We checked the permissions of the script with ls -l. We saw that the owner only had "rw", meaning "read - write" permissions. Let's keep this information in mind.
- I tried to run the
echo_ornegi.shscript. It didn't work. We received a "Command not found" error because the directory where the script is located is not defined in our PATH variable. - With
./echo_ornegi.sh, we told the system, "No need to check the PATH, run theecho_ornegi.shfile from the current directory." We got an "Access denied" error. As a reminder, we had read and write permissions for this file, but we didn't have execute (x) permissions. - We checked the file type using
file. We saw that it is "UTF-8 Unicode text."
In this case, we will give our file "execute" permission. Also, to avoid adding "bash" before every execution, we will add a line to indicate that this file is a "bash script." This line is called a shebang3.
About Shebang
If you don't add the shebang line, your scripts can still be executed. However, including this line in your scripts is the correct approach because the default shell on every system may not be the shell in which you wrote the script. Additionally, in cases of radical version changes, like Python 2 and Python 3, you'll inevitably face issues.
[root@localhost bashscript]# vi echo_ornegi.sh
[root@localhost bashscript]# cat echo_ornegi.sh
#! /bin/bash
echo Alti üstü beş metreydi
echo dertlerinin birikimi
echo Belki biter dedin ama
echo sen kaparsan gözlerini
[root@localhost bashscript]# file echo_ornegi.sh
echo_ornegi.sh: Bourne-Again shell script, UTF-8 Unicode text executable
[root@localhost bashscript]# chmod u+x echo_ornegi.sh
[root@localhost bashscript]# ./echo_ornegi.sh
Alti üstü beş metreydi
dertlerinin birikimi
Belki biter dedin ama
sen kaparsan gözlerini
[root@localhost bashscript]#
Let's see what we've done:
- We opened the file with
viand added the shebang. - We used
catto read the content, and we see it on the screen. The shebang line we added is "#! /bin/bash". Shebangs start with "#!", followed by the full path of the shell to specify which shell to use, in this case, "/bin/bash". - We checked with
file. Previously, the file was listed as "UTF-8 text", but now it appears as "Bourne-Again shell script. UTF-8 Unicode text executable.". - We gave the file owner execute permissions with
chmod u+x. - We ran it with
./echo_ornegi.sh. No issues occurred.
[root@localhost bashscript]# sh echo_ornegi.sh
Alti üstü beş metreydi
dertlerinin birikimi
Belki biter dedin ama
sen kaparsan gözlerini
[root@localhost bashscript]#
We can see that there is no issue when we run the same script with "sh". This script was compatible with "sh". We already mentioned that GNU Bash is compatible with sh. However, in light of this information and this example, we should not conclude that "Every bash script will always work on sh".
Conclusion
As we can see, if you're working with shell scripting, you need to master some topics:
- Full path, relative path
- Shell commands
- Basic GNU/Linux tools
- File and directory permissions
Additionally, in the examples above, you can see that I wrote and ran all scripts as the "root" user. Running an unknown script as root is like transferring all your assets to someone else randomly. When writing your own scripts, if you're not 100% sure of what you're doing, please write and run them as a standard user instead of root. Avoid running every script you see. Stay away from scripts that you cannot confirm are from a trusted and reliable source. And lastly, if you're writing a script that will be run with root privileges, don't make any mistakes. :)
I hope it was helpful. I will continue this series as much as I can.
