Mastering Bash
4.5/5
()
About this ebook
- From roots to leaves, learn how to program in Bash and automate daily tasks, pouring some spice in your scripts
- Daemonize a script and make a real service of it, ensuring it’s available at any time to process user-fed data or commands
- This book provides functional examples that show you practical applications of commands
If you're a power user or system administrator involved in writing Bash scripts to automate tasks, then this book is for you. This book is also ideal for advanced users who are engaged in complex daily tasks.
Related to Mastering Bash
Related ebooks
Working with Linux – Quick Hacks for the Command Line Rating: 5 out of 5 stars5/5Learning Shell Scripting with Zsh Rating: 0 out of 5 stars0 ratingsMastering Python Networking Rating: 5 out of 5 stars5/5Mastering Ansible - Second Edition Rating: 0 out of 5 stars0 ratingsMastering Embedded Linux Programming - Second Edition Rating: 4 out of 5 stars4/5PostgreSQL Administration Cookbook, 9.5/9.6 Edition Rating: 0 out of 5 stars0 ratingsMastering Ansible Rating: 5 out of 5 stars5/5Linux Shell Scripting Cookbook - Third Edition Rating: 4 out of 5 stars4/5Mastering Linux Shell Scripting Rating: 4 out of 5 stars4/5Learning Linux Shell Scripting Rating: 4 out of 5 stars4/5Linux Bible Rating: 0 out of 5 stars0 ratingsThe Linux Command Line Beginner's Guide Rating: 4 out of 5 stars4/5Linux Networking Cookbook Rating: 0 out of 5 stars0 ratingsLinux Commands By Example Rating: 5 out of 5 stars5/5Bash Command Line Pro Tips Rating: 5 out of 5 stars5/5Simply Linux: Basics Rating: 5 out of 5 stars5/5Linux Shell Scripting Cookbook, Second Edition Rating: 0 out of 5 stars0 ratingsMastering Linux Network Administration Rating: 4 out of 5 stars4/5Going Text: Mastering the Command Line Rating: 4 out of 5 stars4/5Linux Command-Line Tips & Tricks Rating: 0 out of 5 stars0 ratingsArch Linux: Fast and Light! Rating: 3 out of 5 stars3/5A Beginners Guide to Linux Rating: 0 out of 5 stars0 ratingsLinux Command Line and Shell Scripting Bible Rating: 3 out of 5 stars3/5Penetration Testing with the Bash shell Rating: 0 out of 5 stars0 ratingsBash for Fun: Bash Programming: Principles and Examples Rating: 0 out of 5 stars0 ratingsPowerShell: A Comprehensive Guide to Windows PowerShell Rating: 4 out of 5 stars4/5Kali Linux Cookbook Rating: 4 out of 5 stars4/5Linux for Beginners: Linux Command Line, Linux Programming and Linux Operating System Rating: 4 out of 5 stars4/5
Operating Systems For You
Excel : The Ultimate Comprehensive Step-By-Step Guide to the Basics of Excel Programming: 1 Rating: 5 out of 5 stars5/5iPhone For Dummies Rating: 0 out of 5 stars0 ratingsThe Windows Command Line Beginner's Guide: Second Edition Rating: 4 out of 5 stars4/5Linux: Learn in 24 Hours Rating: 5 out of 5 stars5/5Linux Command-Line Tips & Tricks Rating: 0 out of 5 stars0 ratingsWindows 11 For Dummies Rating: 0 out of 5 stars0 ratingsMacBook Pro User Manual: 2022 MacBook Pro User Guide for beginners and seniors to Master Macbook Pro like a Pro Rating: 0 out of 5 stars0 ratingsThe Linux Command Line Beginner's Guide Rating: 4 out of 5 stars4/5Make Your PC Stable and Fast: What Microsoft Forgot to Tell You Rating: 4 out of 5 stars4/5Ubuntu Linux Bible Rating: 0 out of 5 stars0 ratingsmacOS Sonoma For Dummies Rating: 0 out of 5 stars0 ratingsOneNote: The Ultimate Guide on How to Use Microsoft OneNote for Getting Things Done Rating: 1 out of 5 stars1/5iPhone Unlocked Rating: 0 out of 5 stars0 ratingsApple Card and Apple Pay: A Ridiculously Simple Guide to Mobile Payments Rating: 0 out of 5 stars0 ratingsTor Darknet Bundle: Master the Art of Invisibility Rating: 0 out of 5 stars0 ratingsWindows 11 All-in-One For Dummies Rating: 5 out of 5 stars5/5Hacking : The Ultimate Comprehensive Step-By-Step Guide to the Basics of Ethical Hacking Rating: 5 out of 5 stars5/5The iPadOS 17: The Complete User Manual to Quick Set Up and Mastering the iPadOS 17 with New Features, Pictures, Tips, and Tricks Rating: 0 out of 5 stars0 ratingsCompTIA Linux+ Study Guide: Exam XK0-004 Rating: 0 out of 5 stars0 ratingsBash Command Line Pro Tips Rating: 5 out of 5 stars5/5Learn Windows PowerShell in a Month of Lunches Rating: 0 out of 5 stars0 ratingsNetworking for System Administrators: IT Mastery, #5 Rating: 5 out of 5 stars5/5Raspberry Pi Cookbook for Python Programmers Rating: 0 out of 5 stars0 ratingsLinux Bible Rating: 0 out of 5 stars0 ratingsAndroid Security Cookbook Rating: 0 out of 5 stars0 ratingsMac Unlocked: Everything You Need to Know to Get Cracking in macOS Big Sur Rating: 0 out of 5 stars0 ratingsM2 Mac Book Air User Guide: Features, Tips, and Tricks With Pictures Rating: 0 out of 5 stars0 ratings
Reviews for Mastering Bash
3 ratings0 reviews
Book preview
Mastering Bash - Giorgio Zarrelli
Mastering Bash
Automate daily tasks with Bash
Giorgio Zarrelli
BIRMINGHAM - MUMBAI
Mastering Bash
Copyright © 2017 Packt Publishing
All rights reserved. No part of this book may be reproduced, stored in a retrieval system, or transmitted in any form or by any means, without the prior written permission of the publisher, except in the case of brief quotations embedded in critical articles or reviews.
Every effort has been made in the preparation of this book to ensure the accuracy of the information presented. However, the information contained in this book is sold without warranty, either express or implied. Neither the author, nor Packt Publishing, and its dealers and distributors will be held liable for any damages caused or alleged to be caused directly or indirectly by this book.
Packt Publishing has endeavored to provide trademark information about all of the companies and products mentioned in this book by the appropriate use of capitals. However, Packt Publishing cannot guarantee the accuracy of this information.
First published: June 2017
Production reference: 1190617
Published by Packt Publishing Ltd.
Livery Place
35 Livery Street
Birmingham
B3 2PB, UK.
ISBN 978-1-78439-687-9
www.packtpub.com
Credits
About the Author
Giorgio Zarrelli is a passionate GNU/Linux system administrator and Debian user, but has worked over the years with Windows, Mac, and OpenBSD, writing scripts, programming, installing and configuring services--whatever is required from an IT guy. He started tinkering seriously with servers back in his university days, when he took part in the Computational Philosophy Laboratory and was introduced to the Prolog language. As a young guy, he had fun being paid for playing games and write about them in video game magazines. Then he grew up and worked as an IT journalist and Nagios architect, and recently moved over to the threat intelligence field, where a lot of interesting stuff is happening nowadays.
Over the years, he has worked for start-ups and well-established companies, among them In3 incubator and Onebip as a database and systems administrator, IBM as QRadar support, and Anomali as CSO, trying to find the best ways to help companies make the best out of IT.
Giorgio has written several books in Italian on different topics related to IT, from Windows security to Linux system administration, covering MySQL DB administration and Bash scripting.
At last, some acknowledgments since we cannot do much without the help of the people who make our lives better. Firstly, Ilaria, who had to go through all the weekends and the mornings I spent writing instead of strolling downtown. Then, mum and dad and my brother, Maurizio. Being Italian, my mum would kill me if I did not acknowledge her--and, by the way, they are such an important part of my life. Let’s keep it short, since I cannot thank all the people who enrich my life and have put some flourishes into this book. So let me thank my bosses at Anomali, Gabe and Mitul, for supporting me and letting me use a Mac (I do whatever needed to write a book, even if it is crazy) when my laptop broke and the replacement was stuck somewhere around the globe. Thanks to my editor, Abhishek, for being supportive, professional, and patient during the writing of this book. Finally, thank you, dear reader, for having a look at this book--sometimes IT can be boring; I've tried to make it fun.
About the Reviewer
Sebastian F. Colomar is a GNU/Linux system engineer specializing in the scripting, installation, configuration, and maintenance of Linux servers for better security and performance.
He is currently an infrastructure architect at Hanscan, having been a consultant for scripting and Linux administration for many companies, such as IBM, Indra, Thales, Accelya, Accenture, AXA, Cetelem, RTVCM, EMT, and ESA.
www.PacktPub.com
For support files and downloads related to your book, please visit www.PacktPub.com.
Did you know that Packt offers eBook versions of every book published, with PDF and ePub files available? You can upgrade to the eBook version at www.PacktPub.comand as a print book customer, you are entitled to a discount on the eBook copy. Get in touch with us at [email protected] for more details.
At www.PacktPub.com, you can also read a collection of free technical articles, sign up for a range of free newsletters and receive exclusive discounts and offers on Packt books and eBooks.
https://www.packtpub.com/mapt
Get the most in-demand software skills with Mapt. Mapt gives you full access to all Packt books and video courses, as well as industry-leading tools to help you plan your personal development and advance your career.
Why subscribe?
Fully searchable across every book published by Packt
Copy and paste, print, and bookmark content
On demand and accessible via a web browser
Customer Feedback
Thanks for purchasing this Packt book. At Packt, quality is at the heart of our editorial process. To help us improve, please leave us an honest review on this book's Amazon page at https://www.amazon.com/dp/1784396877.
If you'd like to join our team of regular reviewers, you can e-mail us at [email protected]. We award our regular reviewers with free eBooks and videos in exchange for their valuable feedback. Help us be relentless in improving our products!
Table of Contents
Preface
What this book covers
What you need for this book
Who this book is for
Conventions
Reader feedback
Customer support
Downloading the example code
Downloading the color images of this book
Errata
Piracy
Questions
Let's Start Programming
I/O redirection
Messing around with stdin, stdout, and stderr
Time for the interpreter: the sha-bang
Calling your script
Something went wrong, let's trace it
Variables
Assigning a variable
Keep the variable name safe
Variables with limited scope
Environment variables
Variable expansion
Pattern matching against variables
Special variables
Summary
Operators
Arithmetic operators
The + operator
The - operator
The * operator
The / operator
The % operator
The ** operator
Assignment operators
The += operator
The -= operator
The *= operator
The /= operator
The %= operator
The ++ or -- operators
Bitwise operators
Left shift (<<)
Right shift (>>)
Bitwise AND
Bitwise OR (|)
Bitwise XOR (^)
Bitwise NOT (~)
Logical operators
Logical NOT (!)
Logical AND
Logical OR (||)
Comma operator (,)
Operators evaluation order and precedence in decreasing relevance
Exit codes
Exiting a script
Summary
Testing
What if...else
Test command recap
Testing files
Testing integers
Testing strings
More on tests
Summary
Quoting and Escaping
Special characters
The hash character (#)
The semicolon character (;)
The double semicolon character (;;)
The case terminator (;;&) and (;&))
The dot character (.)
The double quotes (...
)
The single quotes ('...')
The comma character (,)
The ,, and , () case modificators
The ^^ and ^ () case modificators
The backslash (\)
The forward slash (/)
'...'
The colon character (:)
The exclamation (!)
Keywords
The asterisk (*)
The double asterisk (**)
Test operators (?)
The substitution ($)
The parameter substitution (${})
The quoted string expansion ($'...')
The positional parameters ($* and $")
The exit status ($?)
The process ID ($$)
Grouping the command (command1 ; command2 ; commandn)
Braces ({})
The full path ({} \;)
Expression ([])
Expression ([[]])
The array index ([])
Characters range ([])
Integer expansion ($[…])
Integer expansion (((..)))
DEMO
The here document (<<)
The here string (<<<)
The ASCII comparison operators (<) and (>)
Delimiters (\< and \>)
The pipe character (|)
The force redirection (>|)
The logical OR (||)
DEMO
Logical AND
The dash character (-)
The double dash (--)
Operator =
Operator +
The modulo operator (%)
Operator ~
Operator ~+
Operator ~-
Operator ~=
Operator ^
The control characters (^ and ^^)
Quoting and escaping
The backslash (\)
Double quotes ()
Single quotes (')
Summary
Menus, Arrays, and Functions
The case statement
Arrays
Functions
Summary
Iterations
The for loop
Let's do something while, until…
Exiting the loop with break and continue
Time to give our client a menu
CLI, passing the arguments to the command line
Summary
Plug into the Real World
What is Nagios?
Active and passive checks
Active checks
Passive checks
Returning code and thresholds
Command and service definitions
Our first Nagios plugin
Summary
We Want to Chat
The Slack messaging service
Slack WebHooks
What is a JSON?
Do you like cURLing?
Formatting our messages
Message attachments
Our wee chatty script for Slack
Summary
Subshells, Signals, and Job Controls
What is a subshell?
Background processes
Signals
Job controls
Subshells and parallel processing
Summary
Lets Make a Process Chat
Pipes
Redirection to a file
The command substitution
The process substitution
Environment variables
Coprocesses
/dev/tcp and /dev/udp
Netcat
Summary
Living as a Daemon
What is a daemon?
DEMO
nohup
disown
Double fork and setsid
Becoming a daemon
Trapping a daemon
Going dark with the daemon
Summary
Remote Connections over SSH
What is SSH?
Configuration files
The sshd_config file
ssh_config
Passwordless connections
Configuring the server
Preparing the remote account
Configuring the client
Proxies and tunnels
Summary
Its Time for a Timer
One shot at it
The cron scheduler
cron
Summary
Time for Safety
The restricted shell
Restricted shells for OpenSSH
Restricted sftp sessions with OpenSSH
Summary
Preface
Bash is a common tool for everyday tasks that almost every Linux user relies on. Whatever you want to do, you have to log in to a shell, and most of the time, it will be Bash. This book aims to explain how to use this tool to get the most out of it, whether it be programming a plugin or network client or simply explaining why a double dot means what it means, we will dig a bit deeper than usual to become fully confident with our shell. Starting from the basics but with a different point of view, we will climb up step by step, focusing on the programming side of our environment, looking at how to prevent any issues in setting up our recurring tasks and ensure that everything works fine. Make it once, take your time, debug, improve, and then fire and forget; as in old Linux saying states, If it works, why change it?
So, since we are dealing with sayings, we could stick to the other two cornerstones: KISS: Keep it simple, stupid
and Do only one thing, but do it well.
These are three principles around which Linux revolves: making something, not everything, and making it simple and reliable and taking your time to make it work well so you do not have to modify it too often over time. When something is focused and simple, it is easy to understand, well maintained, and safe. And that is our approach, since Bash is not only a tool but also the environment we spend a lot of time in, and so understanding it, making the best use of it, and keeping everything clean and tidy should be our daily aim.
What this book covers
Chapter 1, Let's Start Programming, is our first brush with the magic of Bash. We will use basic shell programming bits to write easy code that will forecast all the benefits of more advanced scripts.
Chapter 2, Operators, is where we perform some simple operations, such as checking whether something is greater, equal to, or less than something else and how to add, subtract, and fiddle with numbers. This is the first step toward imposing conditions on events dealt with in our scripts.
Chapter 3, Testing, explains how checking whether something fits into boundaries and certain conditions are met or not is fundamental to making our scripts able to react to events and to decide what to do based on real-time indicators coming from the system or from other programs.
Chapter 4, Quoting and Escaping, tells you how the shell has its own reserved words, which cannot be used without knowing exactly what they do. Furthermore, the variables hold values that must be preserved while we are working on them. This is where we'll learn to be cautions about what we are going to write.
Chapter 5, Menus, Arrays, and Functions, explores how to make the script interact with the user, for example, giving the user the chance to answer some questions and deal with the options highlighted. This involves the ability to create a command-line interface for the program itself and a way to store the data in a structure that will make it easy to retrieve that data. And that is what arrays are all about.
Chapter 6, Iterations, explains how iterations are fundamental to going over data and extracting and processing them based on some conditions while they last, for instance, or for some values we use as counters. We will learn how to use while and for loops.
Chapter 7, Plug into the Real World, introduces one of the most famous open source monitoring system, Nagios, which is all about plugins. You can write complex programs in any language to perform whichever checks you want on your sites and applications. But some of the most tricky plugins I have used have been written using Bash, and nothing else.
Chapter 8, We Want to Chat, is about Slack, currently one of the most widely used messaging systems. Why not write a small fragment of code to send our thoughts over a Slack channel and, maybe, make a communication plugin out of it, enabling other scripts to send messages through the messaging system?
Chapter 9, Subshells, Signals, and Job Controls, discusses how sometimes a single process is not enough. Our script has to do many things at once, using a sort of raw parallelism to get to the desired outcome. Well, it's time to see what we can spawn inside a shell, how to control our jobs, and send signals.
Chapter 10, Let's Make a Process Chat, explores the topic of processes talking to each other, feeding each other data and sharing the burden of data elaboration. Pipes, redirections, process substitution, and a bit of netcat--this could open up new scenarios, and we'll see how.
Chapter 11, Living as a Daemon, explains how sometimes sending a script into the background is not enough. It will not survive long, but you can use some tricks such as double forking, setsid, and disowning to make it a bit devilish and survive until process death. Make it a daemon and let it wait for your orders.
Chapter 12, Remote Connections over SSH, tells you how scripts can be run locally, but they can do much more for you. They can log in remotely over a secure channel and issue commands on your behalf without you inputting any further instructions. Everything is stored in a key, which unlocks a whole bunch of new possibilities.
Chapter 13, It's Time for a Timer, discusses how to fully automate routine tasks. We have to have a method to run our scripts based on some conditions. The most common is based on time, such as hourly, daily, weekly, or monthly repetitions. Just think about a simple log rotation triggered on certain conditions, the most common being on a daily schedule.
Chapter 14, Time for Safety, explains how safety is a must in your working environment. Scripting often means access to remote servers and interacting with them, so learning some tricks to keep your server more secure will help you prevent intrusions and keep your job away from unwanted eyes.
What you need for this book
This book assumes a good level of experience with Linux operating systems and an intermediate knowledge of the Bash shell, and since there will be some chapters dealing with Nagios monitoring and Slack messaging, basic understanding of networking concepts is required.
A simple Linux installation is required with really low specifications, as even the Nagios plugin can be tested without requiring the actual installation of the monitoring system. So, this is the minimum configuration required:
CPU: single-core
Memory: 2 GB
Disk space: 20 GB
For this book, you will need the following software:
Linux operating system: Debian 8
Nagios Core 3.5.1
OpenSSH 6.7p1
rssh 2.3.4
Internet connectivity is required to install the necessary service packages and to try out some of the examples.
Who this book is for
This book is intended for advanced users who are engaged in complex daily tasks. Starting from the basics, this book aims to serve as a reference manual where one can find handy solutions and advice to make their scripts flexible and powerful.
Conventions
In this book, you will find a number of text styles that distinguish between different kinds of information. Here are some examples of these styles and an explanation of their meaning.
Code words in text, database table names, folder names, filenames, file extensions, pathnames, dummy URLs, user input, and Twitter handles are shown as follows: What is interesting here is that the value of real is slightly different between the two commands.
A block of code is set as follows:
Any command-line input or output is written as follows:
New terms and important words are shown in bold.
Warnings or important notes appear in a box like this.
Tips and tricks appear like this.
Reader feedback
Feedback from our readers is always welcome. Let us know what you think about this book-what you liked or disliked. Reader feedback is important for us as it helps us develop titles that you will really get the most out of.
To send us general feedback, simply e-mail [email protected], and mention the book's title in the subject of your message.
If there is a topic that you have expertise in and you are interested in either writing or contributing to a book, see our author guide at www.packtpub.com/authors.
Customer support
Now that you are the proud owner of a Packt book, we have a number of things to help you to get the most from your purchase.
Downloading the example code
You can download the example code files for this book from your account at http://www.packtpub.com. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you.
You can download the code files by following these steps:
Log in or register to our website using your e-mail address and password.
Hover the mouse pointer on the SUPPORT tab at the top.
Click on Code Downloads & Errata.
Enter the name of the book in the Search box.
Select the book for which you're looking to download the code files.
Choose from the drop-down menu where you purchased this book from.
Click on Code Download.
Once the file is downloaded, please make sure that you unzip or extract the folder using the latest version of:
WinRAR / 7-Zip for Windows
Zipeg / iZip / UnRarX for Mac
7-Zip / PeaZip for Linux
The code bundle for the book is also hosted on GitHub at https://github.com/PacktPublishing/Mastering-Bash. We also have other code bundles from our rich catalog of books and videos available at https://github.com/PacktPublishing/. Check them out!
Downloading the color images of this book
We also provide you with a PDF file that has color images of the screenshots/diagrams used in this book. The color images will help you better understand the changes in the output. You can download this file from https://www.packtpub.com/sites/default/files/downloads/MasteringBash_ColorImages.pdf.
Errata
Although we have taken every care to ensure the accuracy of our content, mistakes do happen. If you find a mistake in one of our books-maybe a mistake in the text or the code-we would be grateful if you could report this to us. By doing so, you can save other readers from frustration and help us improve subsequent versions of this book. If you find any errata, please report them by visiting http://www.packtpub.com/submit-errata, selecting your book, clicking on the Errata Submission Form link, and entering the details of your errata. Once your errata are verified, your submission will be accepted and the errata will be uploaded to our website or added to any list of existing errata under the Errata section of that title.
To view the previously submitted errata, go to https://www.packtpub.com/books/content/support and enter the name of the book in the search field. The required information will appear under the Errata section.
Piracy
Piracy of copyrighted material on the Internet is an ongoing problem across all media. At Packt, we take the protection of our copyright and licenses very seriously. If you come across any illegal copies of our works in any form on the Internet, please provide us with the location address or website name immediately so that we can pursue a remedy.
Please contact us at [email protected] with a link to the suspected pirated material.
We appreciate your help in protecting our authors and our ability to bring you valuable content.
Questions
If you have a problem with any aspect of this book, you can contact us at [email protected], and we will do our best to address the problem.
Let's Start Programming
Mastering Bash is the art of taking advantage of your environment to make the best out of it. It is not just a matter of dealing with boring routine tasks that can be automated. It is crafting your working space so that it becomes more efficient for your goals. Thus, even though Bash scripting is not as expressive as other more complex languages, such as Python or JavaScript, it is simple enough to be grabbed in a short time, and so flexible that it will suffice for most of your everyday tasks, even the trickiest ones.
But is Bash so plain and easy? Let's have a look at our first lines in Bash. Let's begin with something easy:
Now, let us do it again in a slightly different way:
What is interesting here is that the value of real is slightly different between the two commands. OK, but why? Let's dig a bit further with the following commands:
Interestingly enough, the first seems to be a shell builtin, the second simply a system program, an external utility, and it is here that lies the difference. builtin is a command that is built into the shell, the opposite of a system program, which is invoked by the shell. An internal command, the opposite to an external command.
To understand the difference between internal and external shell commands that lead to such different timing, we have to understand how an external program is invoked by the shell. When an external program is to be executed, Bash creates a copy of itself with the same environment of the parent shell, giving birth to a new process with a different process ID number. So to speak, we just saw how forking is carried out. Inside the new address space, a system exec is called to load the new process data.
For the builtin commands, it is a different story, Bash executes them without any forks, and this leads to a couple of the following interesting outcomes:
The builtin execution is faster because there are no copies and no executables invoked. One side note is that this advantage is more evident with short-running programs because the overhead is before any executable is called: once the external program is invoked, the difference in the pure execution time between the builtin command and the program is negligible.
Being internal to Bash, the builtin commands can affect its internal state, and this is not possible with the external program. Let's take into account a classic example using builtincd. If cd were an external program, once invoked from shell as:
The first operation would be our shell forking a process for cd, and this latter would change the current directory for its own process, not for the one we are inside and that was forked to give birth to the cd process. The parent shell would remain unaffected. So, we would not go anywhere.
Curious about which bulitins are available? You have some options, to either execute the following builtin:
Or this other builtin:
To better understand why there is a difference between the execution of a builtin and an external program, we must see what happens when we invoke a command.
First, remember that the shell works from left to right and takes all the variable assignments and redirections and saves them in order to process later.
If nothing else is left, the shell takes the first word from the command line as the name of the command itself, while all the rest is considered as its arguments.
The next step is dealing with the required input and output redirection.
Finally, before being assigned to a variable, all the text following the sign = is subject to tilde expansion, parameter expansion, command substitution, arithmetic expansion, and quote removal.
If no command name comes out as a result of the last operation, the variable can then affect the environment. If an assignment fails, an error is raised and the command invoked exits with a non-zero status.
If no command name is the outcome of the operation seen before, all the redirections are applied, but differently from variables, they do not affect the current environment. Again, if any error occurs, there is a non-zero status exit.
Once the preceding operations are performed, the command is then executed and exited with a status, depending on whether one or more expansions contain command substitutions. The overall exit status will be the one from the last command substitution, and if no command substitution were performed, the exit status will be zero.
At this point, we are finally left with a command name and some optional arguments. It is at this point the roads of builtins and external programs divert.
At first, the shell looks at the command name, and if there are no slashes, it searches for its location
If there are no slashes, the shell tries to see if there is a function with that name and executes it
If no functions are found, the shell tries to hit builtin, and if there is anyone with that name, it is executed
OK, now if there is any builtin, it already got invoked. What about an external program?
Our Bash goes on, and if it finds no builtins by that name on the command line, there are three chances:
The full path of the command to execute is already contained into its internal hash table, which is a structure used to speed up the search
If the full path is not in the hash, the shell looks for it into the content of the environmental PATH variable, and if it finds it, it is added to the hash table
The full path is not available in the PATH variable, so the shell returns with an exit status of 127
Hash can even be invoked as follows:
The second column will then tell you not only which commands have been hashed, but also how many times each of them has been executed during the current session (hits).
Let's say that the search found the full path to the command we want to execute; now we have a full path, and we are in the same situation as if the Bash found one or more slashes into the command name. In either case, the shell thinks that it has a good path to invoke a command and executes the latter in a forked environment.
This is when we are lucky, but it can happen that the file invoked is not an executable, and in this case, given that our path does not point to a directory instead of a file, the Bash makes an educated guess and thinks to run a shell script. In this case, the script is executed in a subshell that is at all a new environment, which inherits the content of the hash table of the parent shell.
Before doing anything else, the shell looks at the first line of the script for an optional sha-bang (we will see later what this is) - after the sha-bang, there is the path to the interpreter used to manage the script and some optional arguments.
At this point, and only at this point, your external command, if it is a script, is executed. If it is an executable, it is invoked a bit before, but way after any builtin.
During these first paragraphs, we saw some commands and concepts that should sound familiar to you. The next paragraphs of this chapter will quickly deal with some basic elements of Bash, such as variables, expansions, and redirections. If you already know them, you will be able to use the next pages as a reference while working on your scripts. If, on the contrary, you are not so familiar with them, have a look at what comes next because all you will read will be fundamental in understanding what you can do in and with the shell.
I/O redirection
As we saw in the previous pages, redirection is one of the last operations undertaken by Bash to parse and prepare the command line that will lead to the execution of a command. But what is a redirection? You can easily guess from your everyday experience. It means taking a stream that goes from one point to another and making it go somewhere else, like changing the flow of a river and making it go somewhere else. In Linux and Unix, it is quite the same, just keep in mind the following two principles:
In Unix, each process, except for daemons, is supposed to be connected to a standard input, standard output, and standard error device
Every device in Unix is represented by a file
You can also think of these devices as streams:
Standard input, named stdin, is the intaking stream from which the process receives input data
Standard output, named stdout, is the outbound stream where the process writes its output data
Standard error, named stderr, is the stream where the process writes its error messages
These streams are also identified by a standard POSIX file descriptor, which is an integer used by the kernel as a handler to refer to them, as you can see in the following table:
So, tinkering with the file descriptors for the three main streams means that we can redirect the flows between stdin and stdout, but also stderr, from one process to the other. So, we can make different processes communicate with each other, and this is actually a form of IPC, inter-process communication, which we will look at it in more detail later in this book.
How do we redirect the Input/Output (I/O), from one process to another? We can get to this goal making use of some special characters:
Let's start stating that the default output of a process, usually, is the stdout. Whatever it returns is returned on the stdout which, again usually, is the monitor or the terminal. Using the > character, we can divert this flow and make it go to a file. If the file does not exist, it is created, and if it exists, it is flattened and its content is overwritten with the output stream of the process.
A simple example will clarify how the redirection to a file works:
We used the command echo to print a message on the stdout, and so we see the message written, in our case, to the text terminal that is usually connected to the shell:
There is nothing on the filesystem, so the output went straight to the terminal, but the underlying directory was not affected. Now, time for a redirection:
Well, nothing to the screen; no output at all:
Actually, as you can see, the output did not vanish; it was simply redirected to a file on the current directory which got created and filled in:
Here we have something interesting. The cat command takes the content of the output_file.txt and sends it on the stdout. What we can see is that the output from the former command was redirected from the terminal and written to a file.
This double mark answers a requirement we often face: How can we add more content coming from a process to a file without overwriting anything? Using this double character, which means no file is already in place, create a new one; if it already exists, just append the new data. Let's take the previous file and add some content to it:
Bingo, the file was not overwritten and the new content from the echo command was added to the old. Now, we know how to write to a file, but what about reading from somewhere else other than the stdin?
If the text terminal is the stdin, the keyboard is the standard input for a process, where it expects some data from. Again, we can divert the flow or data reading and get the process read from a file. For our example, we start creating a file containing a set of unordered numbers:
And let us verify its content, as follows:
Now we can have the sort command read this file into its stdin, as follows:
Nice, our numbers are now in sequence, but we can do something more interesting:
What did we do? We simply gave the file to_sort to the command sort into its standard input, and at the same time, we concatenated a second redirection so that the output of sort is written into the file sorted:
So, we can concatenate multiple redirections and have some interesting results, but we can do something even trickier, that is, chaining together inputs and outputs, not on files but on processes, as we will see now.
The pipe character does exactly what its name suggests, pipes the stream; could be the stdout or stderr, from one process to another, creating a simple interprocess communication facility:
In this example, we had a bit of fun, first getting a list of processes, then piping the output to the awk utility, which printed only the first, eleventh, and twelfth fields of the output of the first command, giving us the process ID, CPU percentage, and memory percentage columns. Then, we got rid of the heading PID %CPU %MEM, piping the awk output to the input of grep, which performed a reverse pattern matching on any strings containing a character, not a number. In the next stage, we piped the output to the sort command, which reverse-ordered the data based on the values in the second column. Finally, we wanted only the three lines, and so we got the PID of the first three