reworking content
All checks were successful
learn org at code.softwareshinobi.com/linux.softwareshinobi.com/pipeline/head This commit looks good
All checks were successful
learn org at code.softwareshinobi.com/linux.softwareshinobi.com/pipeline/head This commit looks good
This commit is contained in:
91
landing/docs/Bash-Scripts/.recycle/000-about-the-author.md
Normal file
91
landing/docs/Bash-Scripts/.recycle/000-about-the-author.md
Normal file
@@ -0,0 +1,91 @@
|
||||
# About the book
|
||||
|
||||
* **This version was published on Oct 30 2023**
|
||||
|
||||
This is an open-source introduction to Bash scripting guide that will help you learn the basics of Bash scripting and start writing awesome Bash scripts that will help you automate your daily SysOps, DevOps, and Dev tasks. No matter if you are a DevOps/SysOps engineer, developer, or just a Linux enthusiast, you can use Bash scripts to combine different Linux commands and automate tedious and repetitive daily tasks so that you can focus on more productive and fun things.
|
||||
|
||||
The guide is suitable for anyone working as a developer, system administrator, or a DevOps engineer and wants to learn the basics of Bash scripting.
|
||||
|
||||
The first 13 chapters would be purely focused on getting some solid Bash scripting foundations, then the rest of the chapters would give you some real-life examples and scripts.
|
||||
|
||||
## About the author
|
||||
|
||||
My name is Bobby Iliev, and I have been working as a Linux DevOps Engineer since 2014. I am an avid Linux lover and supporter of the open-source movement philosophy. I am always doing that which I cannot do in order that I may learn how to do it, and I believe in sharing knowledge.
|
||||
|
||||
I think it's essential always to keep professional and surround yourself with good people, work hard, and be nice to everyone. You have to perform at a consistently higher level than others. That's the mark of a true professional.
|
||||
|
||||
For more information, please visit my blog at [https://bobbyiliev.com](https://bobbyiliev.com), follow me on Twitter [@bobbyiliev_](https://twitter.com/bobbyiliev_) and [YouTube](https://www.youtube.com/channel/UCQWmdHTeAO0UvaNqve9udRw).
|
||||
|
||||
## Sponsors
|
||||
|
||||
This book is made possible thanks to these fantastic companies!
|
||||
|
||||
### Materialize
|
||||
|
||||
The Streaming Database for Real-time Analytics.
|
||||
|
||||
[Materialize](https://materialize.com/) is a reactive database that delivers incremental view updates. Materialize helps developers easily build with streaming data using standard SQL.
|
||||
|
||||
### DigitalOcean
|
||||
|
||||
DigitalOcean is a cloud services platform delivering the simplicity developers love and businesses trust to run production applications at scale.
|
||||
|
||||
It provides highly available, secure, and scalable compute, storage, and networking solutions that help developers build great software faster.
|
||||
|
||||
Founded in 2012 with offices in New York and Cambridge, MA, DigitalOcean offers transparent and affordable pricing, an elegant user interface, and one of the largest libraries of open source resources available.
|
||||
|
||||
For more information, please visit [https://www.digitalocean.com](https://www.digitalocean.com) or follow [@digitalocean](https://twitter.com/digitalocean) on Twitter.
|
||||
|
||||
If you are new to DigitalOcean, you can get a free $200 credit and spin up your own servers via this referral link here:
|
||||
|
||||
[Free $200 Credit For DigitalOcean](https://m.do.co/c/2a9bba940f39)
|
||||
|
||||
### DevDojo
|
||||
|
||||
The DevDojo is a resource to learn all things web development and web design. Learn on your lunch break or wake up and enjoy a cup of coffee with us to learn something new.
|
||||
|
||||
Join this developer community, and we can all learn together, build together, and grow together.
|
||||
|
||||
[Join DevDojo](https://devdojo.com?ref=bobbyiliev)
|
||||
|
||||
For more information, please visit [https://www.devdojo.com](https://www.devdojo.com?ref=bobbyiliev) or follow [@thedevdojo](https://twitter.com/thedevdojo) on Twitter.
|
||||
|
||||
## Ebook PDF Generation Tool
|
||||
|
||||
This ebook was generated by [Ibis](https://github.com/themsaid/ibis/) developed by [Mohamed Said](https://github.com/themsaid).
|
||||
|
||||
Ibis is a PHP tool that helps you write eBooks in markdown.
|
||||
|
||||
## Ebook ePub Generation Tool
|
||||
|
||||
The ePub version was generated by [Pandoc](https://pandoc.org/).
|
||||
|
||||
## Book Cover
|
||||
|
||||
The cover for this ebook was created with [Canva.com](https://www.canva.com/join/determined-cork-learn).
|
||||
|
||||
If you ever need to create a graphic, poster, invitation, logo, presentation – or anything that looks good — give Canva a go.
|
||||
|
||||
## License
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 Bobby Iliev
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,11 @@
|
||||
# Introduction to Bash scripting
|
||||
|
||||
Welcome to this Bash basics training guide! In this **bash crash course**, you will learn the **Bash basics** so you could start writing your own Bash scripts and automate your daily tasks.
|
||||
|
||||
Bash is a Unix shell and command language. It is widely available on various operating systems, and it is also the default command interpreter on most Linux systems.
|
||||
|
||||
Bash stands for Bourne-Again SHell. As with other shells, you can use Bash interactively directly in your terminal, and also, you can use Bash like any other programming language to write scripts. This book will help you learn the basics of Bash scripting including Bash Variables, User Input, Comments, Arguments, Arrays, Conditional Expressions, Conditionals, Loops, Functions, Debugging, and testing.
|
||||
|
||||
Bash scripts are great for automating repetitive workloads and can help you save time considerably. For example, imagine working with a group of five developers on a project that requires a tedious environment setup. In order for the program to work correctly, each developer has to manually set up the environment. That's the same and very long task (setting up the environment) repeated five times at least. This is where you and Bash scripts come to the rescue! So instead, you create a simple text file containing all the necessary instructions and share it with your teammates. And now, all they have to do is execute the Bash script and everything will be created for them.
|
||||
|
||||
In order to write Bash scripts, you just need a UNIX terminal and a text editor like Sublime Text, VS Code, or a terminal-based editor like vim or nano.
|
||||
@@ -0,0 +1,104 @@
|
||||
# Working with Cloudflare API with Bash
|
||||
|
||||
I host all of my websites on **DigitalOcean** Droplets and I also use Cloudflare as my CDN provider. One of the benefits of using Cloudflare is that it reduces the overall traffic to your user and also hides your actual server IP address behind their CDN.
|
||||
|
||||
My personal favorite Cloudflare feature is their free DDoS protection. It has saved my servers multiple times from different DDoS attacks. They have a cool API that you could use to enable and disable their DDoS protection easily.
|
||||
|
||||
This chapter is going to be an exercise! I challenge you to go ahead and write a short bash script that would enable and disable the Cloudflare DDoS protection for your server automatically if needed!
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before following this guide here, please set up your Cloudflare account and get your website ready. If you are not sure how to do that you can follow these steps here: [Create a Cloudflare account and add a website](https://support.cloudflare.com/hc/en-us/articles/201720164-Step-2-Create-a-Cloudflare-account-and-add-a-website).
|
||||
|
||||
Once you have your Cloudflare account, make sure to obtain the following information:
|
||||
|
||||
* A Cloudflare account
|
||||
* Cloudflare API key
|
||||
* Cloudflare Zone ID
|
||||
|
||||
Also, Make sure curl is installed on your server:
|
||||
|
||||
```bash
|
||||
curl --version
|
||||
```
|
||||
|
||||
If curl is not installed you need to run the following:
|
||||
|
||||
* For RedHat/CentOs:
|
||||
|
||||
```bash
|
||||
yum install curl
|
||||
```
|
||||
|
||||
* For Debian/Ubuntu
|
||||
|
||||
```bash
|
||||
apt-get install curl
|
||||
```
|
||||
|
||||
## Challenge - Script requirements
|
||||
|
||||
The script needs to monitor the CPU usage on your server and if the CPU usage gets high based on the number vCPU it would enable the Cloudflare DDoS protection automatically via the Cloudflare API.
|
||||
|
||||
The main features of the script should be:
|
||||
|
||||
* Checks the script CPU load on the server
|
||||
* In case of a CPU spike the script triggers an API call to Cloudflare and enables the DDoS protection feature for the specified zone
|
||||
* After the CPU load is back to normal the script would disable the "I'm under attack" option and set it back to normal
|
||||
|
||||
## Example script
|
||||
|
||||
I already have prepared a demo script which you could use as a reference. But I encourage you to try and write the script yourself first and only then take a look at my script!
|
||||
|
||||
To download the script just run the following command:
|
||||
|
||||
```bash
|
||||
wget https://raw.githubusercontent.com/bobbyiliev/cloudflare-ddos-protection/main/protection.sh
|
||||
```
|
||||
|
||||
Open the script with your favorite text editor:
|
||||
|
||||
```bash
|
||||
nano protection.sh
|
||||
```
|
||||
|
||||
And update the following details with your Cloudflare details:
|
||||
|
||||
```bash
|
||||
CF_CONE_ID=YOUR_CF_ZONE_ID
|
||||
CF_EMAIL_ADDRESS=YOUR_CF_EMAIL_ADDRESS
|
||||
CF_API_KEY=YOUR_CF_API_KEY
|
||||
```
|
||||
|
||||
After that make the script executable:
|
||||
|
||||
```bash
|
||||
chmod +x ~/protection.sh
|
||||
```
|
||||
|
||||
Finally, set up 2 Cron jobs to run every 30 seconds. To edit your crontab run:
|
||||
|
||||
```bash
|
||||
crontab -e
|
||||
```
|
||||
|
||||
And add the following content:
|
||||
|
||||
```bash
|
||||
* * * * * /path-to-the-script/cloudflare/protection.sh
|
||||
* * * * * ( sleep 30 ; /path-to-the-script/cloudflare/protection.sh )
|
||||
```
|
||||
|
||||
Note that you need to change the path to the script with the actual path where you've stored the script at.
|
||||
|
||||
## Conclusion
|
||||
|
||||
This is quite straight forward and budget solution, one of the downsides of the script is that if your server gets unresponsive due to an attack, the script might not be triggered at all.
|
||||
|
||||
Of course, a better approach would be to use a monitoring system like Nagios and based on the statistics from the monitoring system then you can trigger the script, but this script challenge could be a good learning experience!
|
||||
|
||||
Here is another great resource on how to use the Discord API and send notifications to your Discord Channel with a Bash script:
|
||||
|
||||
[How To Use Discord Webhooks to Get Notifications for Your Website Status on Ubuntu 18.04](https://www.digitalocean.com/community/tutorials/how-to-use-discord-webhooks-to-get-notifications-for-your-website-status-on-ubuntu-18-04)
|
||||
|
||||
>{notice} This content was initially posted on [DevDojo](https://devdojo.com/bobbyiliev/bash-script-to-automatically-enable-cloudflare-ddos-protection)
|
||||
@@ -0,0 +1,83 @@
|
||||
# BASH Script parser to Summarize Your NGINX and Apache Access Logs
|
||||
|
||||
One of the first things that I would usually do in case I notice a high CPU usage on some of my Linux servers would be to check the process list with either top or htop and in case that I notice a lot of Apache or Nginx process I would quickly check my access logs to determine what has caused or is causing the CPU spike on my server or to figure out if anything malicious is going on.
|
||||
|
||||
Sometimes reading the logs could be quite intimidating as the log might be huge and going though it manually could take a lot of time. Also, the raw log format could be confusing for people with less experience.
|
||||
|
||||
Just like the previous chapter, this chapter is going to be a challenge! You need to write a short bash script that would summarize the whole access log for you without the need of installing any additional software.
|
||||
|
||||
# Script requirements
|
||||
|
||||
This BASH script needs to parse and summarize your access logs and provide you with very useful information like:
|
||||
|
||||
* The 20 top pages with the most POST requests
|
||||
* The 20 top pages with the most GET requests
|
||||
* Top 20 IP addresses and their geo-location
|
||||
|
||||
## Example script
|
||||
|
||||
I already have prepared a demo script which you could use as a reference. But I encourage you to try and write the script yourself first and only then take a look at my script!
|
||||
|
||||
In order to download the script, you can either clone the repository with the following command:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/bobbyiliev/quick_access_logs_summary.git
|
||||
```
|
||||
|
||||
Or run the following command which would download the script in your current directory:
|
||||
|
||||
```bash
|
||||
wget https://raw.githubusercontent.com/bobbyiliev/quick_access_logs_summary/master/spike_check
|
||||
```
|
||||
|
||||
The script does not make any changes to your system, it only reads the content of your access log and summarizes it for you, however, once you've downloaded the file, make sure to review the content yourself.
|
||||
|
||||
## Running the script
|
||||
|
||||
All that you have to do once the script has been downloaded is to make it executable and run it.
|
||||
|
||||
To do that run the following command to make the script executable:
|
||||
|
||||
```bash
|
||||
chmod +x spike_check
|
||||
```
|
||||
|
||||
Then run the script:
|
||||
|
||||
```bash
|
||||
./spike_check /path/to/your/access_log
|
||||
```
|
||||
|
||||
Make sure to change the path to the file with the actual path to your access log. For example if you are using Apache on an Ubuntu server, the exact command would look like this:
|
||||
|
||||
```bash
|
||||
./spike_check /var/log/apache2/access.log
|
||||
```
|
||||
|
||||
If you are using Nginx the exact command would be almost the same, but with the path to the Nginx access log:
|
||||
|
||||
```bash
|
||||
./spike_check /var/log/nginx/access.log
|
||||
```
|
||||
|
||||
## Understanding the output
|
||||
|
||||
Once you run the script, it might take a while depending on the size of the log.
|
||||
|
||||
The output that you would see should look like this:
|
||||
|
||||

|
||||
|
||||
Essentially what we can tell in this case is that we've received 16 POST requests to our xmlrpc.php file which is often used by attackers to try and exploit WordPress websites by using various username and password combinations.
|
||||
|
||||
In this specific case, this was not a huge brute force attack, but it gives us an early indication and we can take action to prevent a larger attack in the future.
|
||||
|
||||
We can also see that there were a couple of Russian IP addresses accessing our site, so in case that you do not expect any traffic from Russia, you might want to block those IP addresses as well.
|
||||
|
||||
## Conclusion
|
||||
|
||||
This is an example of a simple BASH script that allows you to quickly summarize your access logs and determine if anything malicious is going on.
|
||||
|
||||
Of course, you might want to also manually go through the logs as well but it is a good challenge to try and automate this with Bash!
|
||||
|
||||
>{notice} This content was initially posted on [DevDojo](https://devdojo.com/bobbyiliev/bash-script-to-summarize-your-nginx-and-apache-access-logs)
|
||||
@@ -0,0 +1,95 @@
|
||||
# Sending emails with Bash and SSMTP
|
||||
|
||||
SSMTP is a tool that delivers emails from a computer or a server to a configured mail host.
|
||||
|
||||
SSMTP is not an email server itself and does not receive emails or manage a queue.
|
||||
|
||||
One of its primary uses is for forwarding automated email (like system alerts) off your machine and to an external email address.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
You would need the following things in order to be able to complete this tutorial successfully:
|
||||
|
||||
* Access to an Ubuntu 18.04 server as a non-root user with sudo privileges and an active firewall installed on your server. To set these up, please refer to our [Initial Server Setup Guide for Ubuntu 18.04](https://www.digitalocean.com/community/tutorials/initial-server-setup-with-ubuntu-18-04)
|
||||
|
||||
* An SMTP server along with SMTP username and password, this would also work with Gmail's SMTP server, or you could set up your own SMTP server by following the steps from this tutorial on [How to Install and Configure Postfix as a Send-Only SMTP Server on Ubuntu 16.04](https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-postfix-as-a-send-only-smtp-server-on-ubuntu-16-04)
|
||||
|
||||
## Installing SSMTP
|
||||
|
||||
In order to install SSMTP, you’ll need to first update your apt cache with:
|
||||
|
||||
```bash
|
||||
sudo apt update
|
||||
```
|
||||
|
||||
Then run the following command to install SSMTP:
|
||||
|
||||
```bash
|
||||
sudo apt install ssmtp
|
||||
```
|
||||
|
||||
Another thing that you would need to install is `mailutils`, to do that run the following command:
|
||||
|
||||
```bash
|
||||
sudo apt install mailutils
|
||||
```
|
||||
|
||||
## Configuring SSMTP
|
||||
|
||||
Now that you have `ssmtp` installed, in order to configure it to use your SMTP server when sending emails, you need to edit the SSMTP configuration file.
|
||||
|
||||
Using your favourite text editor to open the `/etc/ssmtp/ssmtp.conf` file:
|
||||
|
||||
```bash
|
||||
sudo nano /etc/ssmtp/ssmtp.conf
|
||||
```
|
||||
|
||||
You need to include your SMTP configuration:
|
||||
|
||||
```
|
||||
root=postmaster
|
||||
mailhub=<^>your_smtp_host.com<^>:587
|
||||
hostname=<^>your_hostname<^>
|
||||
AuthUser=<^>your_gmail_username@your_smtp_host.com<^>
|
||||
AuthPass=<^>your_gmail_password<^>
|
||||
FromLineOverride=YES
|
||||
UseSTARTTLS=YES
|
||||
```
|
||||
|
||||
Save the file and exit.
|
||||
|
||||
## Sending emails with SSMTP
|
||||
|
||||
Once your configuration is done, in order to send an email just run the following command:
|
||||
|
||||
```bash
|
||||
echo "<^>Here add your email body<^>" | mail -s "<^>Here specify your email subject<^>" <^>your_recepient_email@yourdomain.com<^>
|
||||
```
|
||||
|
||||
You can run this directly in your terminal or include it in your bash scripts.
|
||||
|
||||
## Sending A File with SSMTP (optional)
|
||||
|
||||
If you need to send files as attachments, you can use `mpack`.
|
||||
|
||||
To install `mpack` run the following command:
|
||||
|
||||
```bash
|
||||
sudo apt install mpack
|
||||
```
|
||||
|
||||
Next, in order to send an email with a file attached, run the following command.
|
||||
|
||||
```bash
|
||||
mpack -s "<^>Your Subject here<^>" your_file.zip <^>your_recepient_email@yourdomain.com<^>
|
||||
```
|
||||
|
||||
The above command would send an email to `<^>your_recepient_email@yourdomain.com<^>` with the `<^>your_file.zip<^>` attached.
|
||||
|
||||
## Conclusion
|
||||
|
||||
SSMTP is a great and reliable way to implement SMTP email functionality directly in bash scripts.
|
||||
|
||||
For more information about SSMTP I would recommend checking the official documentation [here](https://wiki.archlinux.org/index.php/SSMTP).
|
||||
|
||||
>{notice} This content was initially posted on the [DigitalOcean community forum](https://www.digitalocean.com/community/questions/how-to-send-emails-from-a-bash-script-using-ssmtp).
|
||||
@@ -0,0 +1,126 @@
|
||||
# Password Generator Bash Script
|
||||
|
||||
It's not uncommon situation where you will need to generate a random password that you can use for any software installation or when you sign-up to any website.
|
||||
|
||||
There are a lot of options in order to achieve this. You can use a password manager/vault where you often have the option to randomly generate a password or to use a website that can generate the password on your behalf.
|
||||
|
||||
You can also use Bash in your terminal (command-line) to generate a password that you can quickly use. There are a lot of ways to achieve that and I will make sure to cover few of them and will leave up to you to choose which option is most suitable with your needs.
|
||||
|
||||
## :warning: Security
|
||||
|
||||
**This script is intended to practice your bash scripting skills. You can have fun while doing simple projects with BASH, but security is not a joke, so please make sure you do not save your passwords in plain text in a local file or write them down by hand on a piece of paper.**
|
||||
|
||||
**I will highly recommend everyone to use secure and trusted providers to generate and save the passwords.**
|
||||
|
||||
## Script summary
|
||||
|
||||
Let me first do a quick summary of what our script is going to do.:
|
||||
|
||||
1. We will have to option to choose the password characters length when the script is executed.
|
||||
2. The script will then generate 5 random passwords with the length that was specified in step 1
|
||||
|
||||
## Prerequisites
|
||||
|
||||
You would need a bash terminal and a text editor. You can use any text editor like vi, vim, nano or Visual Studio Code.
|
||||
|
||||
I'm running the script locally on my Linux laptop but if you're using Windows PC you can ssh to any server of your choice and execute the script there.
|
||||
|
||||
Although the script is pretty simple, having some basic BASH scripting knowledge will help you to better understand the script and how it's working.
|
||||
|
||||
## Generate a random password
|
||||
One of the great benefits of Linux is that you can do a lot of things using different methods. When it comes to generating a random string of characters it's not different as well.
|
||||
|
||||
You can use several commands in order to generate a random string of characters. I will cover few of them and will provide some examples.
|
||||
|
||||
- Using the ```date``` command.
|
||||
The date command will output the current date and time. However we also further manipulate the output in order to use it as randomly generated password. We can hash the date using md5, sha or just run it through base64. These are few examples:
|
||||
|
||||
```
|
||||
date | md5sum
|
||||
94cb1cdecfed0699e2d98acd9a7b8f6d -
|
||||
```
|
||||
using sha256sum:
|
||||
|
||||
```
|
||||
date | sha256sum
|
||||
30a0c6091e194c8c7785f0d7bb6e1eac9b76c0528f02213d1b6a5fbcc76ceff4 -
|
||||
```
|
||||
using base64:
|
||||
```
|
||||
date | base64
|
||||
0YHQsSDRj9C90YMgMzAgMTk6NTE6NDggRUVUIDIwMjEK
|
||||
```
|
||||
|
||||
- We can also use openssl in order to generate pseudo-random bytes and run the output through base64. An example output will be:
|
||||
```
|
||||
openssl rand -base64 10
|
||||
9+soM9bt8mhdcw==
|
||||
```
|
||||
Keep in mind that openssl might not be installed on your system so it's likely that you will need to install it first in order to use it.
|
||||
|
||||
- The most preferred way is to use the pseudorandom number generator - /dev/urandom
|
||||
since it is intended for most cryptographic purposes. We would also need to manipulate the output using ```tr``` in order to translate it. An example command is:
|
||||
|
||||
```
|
||||
tr -cd '[:alnum:]' < /dev/urandom | fold -w10 | head -n 1
|
||||
```
|
||||
With this command we take the output from /dev/urandom and translate it with ```tr``` while using all letters and digits and print the desired number of characters.
|
||||
|
||||
## The script
|
||||
First we begin the script with the shebang. We use it to tell the operating system which interpreter to use to parse the rest of the file.
|
||||
```
|
||||
#!/bin/bash
|
||||
```
|
||||
We can then continue and ask the user for some input. In this case we would like to know how many characters the password needs to be:
|
||||
|
||||
```
|
||||
# Ask user for password length
|
||||
clear
|
||||
printf "\n"
|
||||
read -p "How many characters you would like the password to have? " pass_length
|
||||
printf "\n"
|
||||
```
|
||||
Generate the passwords and then print it so the user can use it.
|
||||
```
|
||||
# This is where the magic happens!
|
||||
# Generate a list of 10 strings and cut it to the desired value provided from the user
|
||||
|
||||
for i in {1..10}; do (tr -cd '[:alnum:]' < /dev/urandom | fold -w${pass_length} | head -n 1); done
|
||||
|
||||
# Print the strings
|
||||
printf "$pass_output\n"
|
||||
printf "Goodbye, ${USER}\n"
|
||||
```
|
||||
|
||||
## The full script:
|
||||
```
|
||||
#!/bin/bash
|
||||
#=======================================
|
||||
# Password generator with login option
|
||||
#=======================================
|
||||
|
||||
# Ask user for the string length
|
||||
clear
|
||||
printf "\n"
|
||||
read -p "How many characters you would like the password to have? " pass_length
|
||||
printf "\n"
|
||||
|
||||
# This is where the magic happens!
|
||||
# Generate a list of 10 strings and cut it to the desired value provided from the user
|
||||
|
||||
for i in {1..10}; do (tr -cd '[:alnum:]' < /dev/urandom | fold -w${pass_length} | head -n 1); done
|
||||
|
||||
# Print the strings
|
||||
printf "$pass_output\n"
|
||||
printf "Goodbye, ${USER}\n"
|
||||
```
|
||||
|
||||
## Conclusion
|
||||
This is pretty much how you can use simple bash script to generate random passwords.
|
||||
|
||||
:warning: **As already mentioned, please make sure to use strong passwords in order to make sure your account is protected. Also whenever is possible use 2 factor authentication as this will provide additional layer of security for your account.**
|
||||
|
||||
While the script is working fine, it expects that the user will provide the requested input. In order to prevent any issues you would need to do some more advance checks on the user input in order to make sure the script will continue to work fine even if the provided input does not match our needs.
|
||||
|
||||
## Contributed by
|
||||
[Alex Georgiev](https://twitter.com/alexgeorgiev17)
|
||||
@@ -0,0 +1,336 @@
|
||||
# Automatic WordPress on LAMP installation with BASH
|
||||
|
||||
Here is an example of a full LAMP and WordPress installation that works on any Debian-based machine.
|
||||
|
||||
# Prerequisites
|
||||
|
||||
- A Debian-based machine (Ubuntu, Debian, Linux Mint, etc.)
|
||||
|
||||
# Planning the functionality
|
||||
|
||||
Let's start again by going over the main functionality of the script:
|
||||
|
||||
**Lamp Installation**
|
||||
|
||||
* Update the package manager
|
||||
* Install a firewall (ufw)
|
||||
* Allow SSH, HTTP and HTTPS traffic
|
||||
* Install Apache2
|
||||
* Install & Configure MariaDB
|
||||
* Install PHP and required plugins
|
||||
* Enable all required Apache2 mods
|
||||
|
||||
**Apache Virtual Host Setup**
|
||||
|
||||
* Create a directory in `/var/www`
|
||||
* Configure permissions to the directory
|
||||
* Create the `$domain` file under `/etc/apache2/sites-available` and append the required Virtualhost content
|
||||
* Enable the site
|
||||
* Restart Apache2
|
||||
|
||||
**SSL Config**
|
||||
|
||||
* Generate the OpenSSL certificate
|
||||
* Append the SSL certificate to the `ssl-params.conf` file
|
||||
* Append the SSL config to the Virtualhost file
|
||||
* Enable SSL
|
||||
* Reload Apache2
|
||||
|
||||
**Database Config**
|
||||
|
||||
* Create a database
|
||||
* Create a user
|
||||
* Flush Privileges
|
||||
|
||||
**WordPress Config**
|
||||
|
||||
* Install required WordPress PHP plugins
|
||||
* Install WordPress
|
||||
* Append the required information to `wp-config.php` file
|
||||
|
||||
Without further ado, let's start writing the script.
|
||||
|
||||
# The script
|
||||
|
||||
We start by setting our variables and asking the user to input their domain:
|
||||
|
||||
```bash
|
||||
echo 'Please enter your domain of preference without www:'
|
||||
read DOMAIN
|
||||
echo "Please enter your Database username:"
|
||||
read DBUSERNAME
|
||||
echo "Please enter your Database password:"
|
||||
read DBPASSWORD
|
||||
echo "Please enter your Database name:"
|
||||
read DBNAME
|
||||
|
||||
ip=`hostname -I | cut -f1 -d' '`
|
||||
```
|
||||
|
||||
We are now ready to start writing our functions. Start by creating the `lamp_install()` function. Inside of it, we are going to update the system, install ufw, allow SSH, HTTP and HTTPS traffic, install Apache2, install MariaDB and PHP. We are also going to enable all required Apache2 mods.
|
||||
|
||||
```bash
|
||||
lamp_install () {
|
||||
apt update -y
|
||||
apt install ufw
|
||||
ufw enable
|
||||
ufw allow OpenSSH
|
||||
ufw allow in "WWW Full"
|
||||
|
||||
apt install apache2 -y
|
||||
apt install mariadb-server
|
||||
mysql_secure_installation -y
|
||||
apt install php libapache2-mod-php php-mysql -y
|
||||
sed -i "2d" /etc/apache2/mods-enabled/dir.conf
|
||||
sed -i "2i\\\tDirectoryIndex index.php index.html index.cgi index.pl index.xhtml index.htm" /etc/apache2/mods-enabled/dir.conf
|
||||
systemctl reload apache2
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
Next, we are going to create the `apache_virtualhost_setup()` function. Inside of it, we are going to create a directory in `/var/www`, configure permissions to the directory, create the `$domain` file under `/etc/apache2/sites-available` and append the required Virtualhost content, enable the site and restart Apache2.
|
||||
|
||||
```bash
|
||||
apache_virtual_host_setup () {
|
||||
mkdir /var/www/$DOMAIN
|
||||
chown -R $USER:$USER /var/www/$DOMAIN
|
||||
|
||||
echo "<VirtualHost *:80>" >> /etc/apache2/sites-available/$DOMAIN.conf
|
||||
echo -e "\tServerName $DOMAIN" >> /etc/apache2/sites-available/$DOMAIN.conf
|
||||
echo -e "\tServerAlias www.$DOMAIN" >> /etc/apache2/sites-available/$DOMAIN.conf
|
||||
echo -e "\tServerAdmin webmaster@localhost" >> /etc/apache2/sites-available/$DOMAIN.conf
|
||||
echo -e "\tDocumentRoot /var/www/$DOMAIN" >> /etc/apache2/sites-available/$DOMAIN.conf
|
||||
echo -e '\tErrorLog ${APACHE_LOG_DIR}/error.log' >> /etc/apache2/sites-available/$DOMAIN.conf
|
||||
echo -e '\tCustomLog ${APACHE_LOG_DIR}/access.log combined' >> /etc/apache2/sites-available/$DOMAIN.conf
|
||||
echo "</VirtualHost>" >> /etc/apache2/sites-available/$DOMAIN.conf
|
||||
a2ensite $DOMAIN
|
||||
a2dissite 000-default
|
||||
systemctl reload apache2
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
Next, we are going to create the `ssl_config()` function. Inside of it, we are going to generate the OpenSSL certificate, append the SSL certificate to the `ssl-params.conf` file, append the SSL config to the Virtualhost file, enable SSL and reload Apache2.
|
||||
|
||||
```bash
|
||||
ssl_config () {
|
||||
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/apache-selfsigned.key -out /etc/ssl/certs/apache-selfsigned.crt
|
||||
|
||||
echo "SSLCipherSuite EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH" >> /etc/apache2/conf-available/ssl-params.conf
|
||||
echo "SSLProtocol All -SSLv2 -SSLv3 -TLSv1 -TLSv1.1" >> /etc/apache2/conf-available/ssl-params.conf
|
||||
echo "SSLHonorCipherOrder On" >> /etc/apache2/conf-available/ssl-params.conf
|
||||
echo "Header always set X-Frame-Options DENY" >> /etc/apache2/conf-available/ssl-params.conf
|
||||
echo "Header always set X-Content-Type-Options nosniff" >> /etc/apache2/conf-available/ssl-params.conf
|
||||
echo "SSLCompression off" >> /etc/apache2/conf-available/ssl-params.conf
|
||||
echo "SSLUseStapling on" >> /etc/apache2/conf-available/ssl-params.conf
|
||||
echo "SSLStaplingCache \"shmcb:logs/stapling-cache(150000)\"" >> /etc/apache2/conf-available/ssl-params.conf
|
||||
echo "SSLSessionTickets Off" >> /etc/apache2/conf-available/ssl-params.conf
|
||||
|
||||
cp /etc/apache2/sites-available/default-ssl.conf /etc/apache2/sites-available/default-ssl.conf.bak
|
||||
sed -i "s/var\/www\/html/var\/www\/$DOMAIN/1" /etc/apache2/sites-available/default-ssl.conf
|
||||
sed -i "s/etc\/ssl\/certs\/ssl-cert-snakeoil.pem/etc\/ssl\/certs\/apache-selfsigned.crt/1" /etc/apache2/sites-available/default-ssl.conf
|
||||
sed -i "s/etc\/ssl\/private\/ssl-cert-snakeoil.key/etc\/ssl\/private\/apache-selfsigned.key/1" /etc/apache2/sites-available/default-ssl.conf
|
||||
sed -i "4i\\\t\tServerName $ip" /etc/apache2/sites-available/default-ssl.conf
|
||||
sed -i "22i\\\tRedirect permanent \"/\" \"https://$ip/\"" /etc/apache2/sites-available/000-default.conf
|
||||
a2enmod ssl
|
||||
a2enmod headers
|
||||
a2ensite default-ssl
|
||||
a2enconf ssl-params
|
||||
systemctl reload apache2
|
||||
}
|
||||
```
|
||||
|
||||
Next, we are going to create the `db_setup()` function. Inside of it, we are going to create the database, create the user and grant all privileges to the user.
|
||||
|
||||
```bash
|
||||
db_config () {
|
||||
mysql -e "CREATE DATABASE $DBNAME;"
|
||||
mysql -e "GRANT ALL ON $DBNAME.* TO '$DBUSERNAME'@'localhost' IDENTIFIED BY '$DBPASSWORD' WITH GRANT OPTION;"
|
||||
mysql -e "FLUSH PRIVILEGES;"
|
||||
}
|
||||
```
|
||||
|
||||
Next, we are going to create the `wordpress_config()` function. Inside of it, we are going to download the latest version of WordPress, extract it to the `/var/www/$DOMAIN` directory, create the `wp-config.php` file and append the required content to it.
|
||||
|
||||
```bash
|
||||
wordpress_config () {
|
||||
db_config
|
||||
|
||||
|
||||
apt install php-curl php-gd php-mbstring php-xml php-xmlrpc php-soap php-intl php-zip -y
|
||||
systemctl restart apache2
|
||||
sed -i "8i\\\t<Directory /var/www/$DOMAIN/>" /etc/apache2/sites-available/$DOMAIN.conf
|
||||
sed -i "9i\\\t\tAllowOverride All" /etc/apache2/sites-available/$DOMAIN.conf
|
||||
sed -i "10i\\\t</Directory>" /etc/apache2/sites-available/$DOMAIN.conf
|
||||
|
||||
a2enmod rewrite
|
||||
systemctl restart apache2
|
||||
|
||||
apt install curl
|
||||
cd /tmp
|
||||
curl -O https://wordpress.org/latest.tar.gz
|
||||
tar xzvf latest.tar.gz
|
||||
touch /tmp/wordpress/.htaccess
|
||||
cp /tmp/wordpress/wp-config-sample.php /tmp/wordpress/wp-config.php
|
||||
mkdir /tmp/wordpress/wp-content/upgrade
|
||||
cp -a /tmp/wordpress/. /var/www/$DOMAIN
|
||||
chown -R www-data:www-data /var/www/$DOMAIN
|
||||
find /var/www/$DOMAIN/ -type d -exec chmod 750 {} \;
|
||||
find /var/www/$DOMAIN/ -type f -exec chmod 640 {} \;
|
||||
curl -s https://api.wordpress.org/secret-key/1.1/salt/ >> /var/www/$DOMAIN/wp-config.php
|
||||
echo "define('FS_METHOD', 'direct');" >> /var/www/$DOMAIN/wp-config.php
|
||||
sed -i "51,58d" /var/www/$DOMAIN/wp-config.php
|
||||
sed -i "s/database_name_here/$DBNAME/1" /var/www/$DOMAIN/wp-config.php
|
||||
sed -i "s/username_here/$DBUSERNAME/1" /var/www/$DOMAIN/wp-config.php
|
||||
sed -i "s/password_here/$DBPASSWORD/1" /var/www/$DOMAIN/wp-config.php
|
||||
}
|
||||
```
|
||||
|
||||
And finally, we are going to create the `execute()` function. Inside of it, we are going to call all the functions we created above.
|
||||
|
||||
```bash
|
||||
execute () {
|
||||
lamp_install
|
||||
apache_virtual_host_setup
|
||||
ssl_config
|
||||
wordpress_config
|
||||
}
|
||||
```
|
||||
|
||||
With this, you have the script ready and you are ready to run it. And if you need the full script, you can find it in the next section.
|
||||
|
||||
# The full script
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
echo 'Please enter your domain of preference without www:'
|
||||
read DOMAIN
|
||||
echo "Please enter your Database username:"
|
||||
read DBUSERNAME
|
||||
echo "Please enter your Database password:"
|
||||
read DBPASSWORD
|
||||
echo "Please enter your Database name:"
|
||||
read DBNAME
|
||||
|
||||
ip=`hostname -I | cut -f1 -d' '`
|
||||
|
||||
lamp_install () {
|
||||
apt update -y
|
||||
apt install ufw
|
||||
ufw enable
|
||||
ufw allow OpenSSH
|
||||
ufw allow in "WWW Full"
|
||||
|
||||
apt install apache2 -y
|
||||
apt install mariadb-server
|
||||
mysql_secure_installation -y
|
||||
apt install php libapache2-mod-php php-mysql -y
|
||||
sed -i "2d" /etc/apache2/mods-enabled/dir.conf
|
||||
sed -i "2i\\\tDirectoryIndex index.php index.html index.cgi index.pl index.xhtml index.htm" /etc/apache2/mods-enabled/dir.conf
|
||||
systemctl reload apache2
|
||||
|
||||
}
|
||||
|
||||
apache_virtual_host_setup () {
|
||||
mkdir /var/www/$DOMAIN
|
||||
chown -R $USER:$USER /var/www/$DOMAIN
|
||||
|
||||
echo "<VirtualHost *:80>" >> /etc/apache2/sites-available/$DOMAIN.conf
|
||||
echo -e "\tServerName $DOMAIN" >> /etc/apache2/sites-available/$DOMAIN.conf
|
||||
echo -e "\tServerAlias www.$DOMAIN" >> /etc/apache2/sites-available/$DOMAIN.conf
|
||||
echo -e "\tServerAdmin webmaster@localhost" >> /etc/apache2/sites-available/$DOMAIN.conf
|
||||
echo -e "\tDocumentRoot /var/www/$DOMAIN" >> /etc/apache2/sites-available/$DOMAIN.conf
|
||||
echo -e '\tErrorLog ${APACHE_LOG_DIR}/error.log' >> /etc/apache2/sites-available/$DOMAIN.conf
|
||||
echo -e '\tCustomLog ${APACHE_LOG_DIR}/access.log combined' >> /etc/apache2/sites-available/$DOMAIN.conf
|
||||
echo "</VirtualHost>" >> /etc/apache2/sites-available/$DOMAIN.conf
|
||||
a2ensite $DOMAIN
|
||||
a2dissite 000-default
|
||||
systemctl reload apache2
|
||||
|
||||
}
|
||||
|
||||
|
||||
ssl_config () {
|
||||
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/apache-selfsigned.key -out /etc/ssl/certs/apache-selfsigned.crt
|
||||
|
||||
echo "SSLCipherSuite EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH" >> /etc/apache2/conf-available/ssl-params.conf
|
||||
echo "SSLProtocol All -SSLv2 -SSLv3 -TLSv1 -TLSv1.1" >> /etc/apache2/conf-available/ssl-params.conf
|
||||
echo "SSLHonorCipherOrder On" >> /etc/apache2/conf-available/ssl-params.conf
|
||||
echo "Header always set X-Frame-Options DENY" >> /etc/apache2/conf-available/ssl-params.conf
|
||||
echo "Header always set X-Content-Type-Options nosniff" >> /etc/apache2/conf-available/ssl-params.conf
|
||||
echo "SSLCompression off" >> /etc/apache2/conf-available/ssl-params.conf
|
||||
echo "SSLUseStapling on" >> /etc/apache2/conf-available/ssl-params.conf
|
||||
echo "SSLStaplingCache \"shmcb:logs/stapling-cache(150000)\"" >> /etc/apache2/conf-available/ssl-params.conf
|
||||
echo "SSLSessionTickets Off" >> /etc/apache2/conf-available/ssl-params.conf
|
||||
|
||||
cp /etc/apache2/sites-available/default-ssl.conf /etc/apache2/sites-available/default-ssl.conf.bak
|
||||
sed -i "s/var\/www\/html/var\/www\/$DOMAIN/1" /etc/apache2/sites-available/default-ssl.conf
|
||||
sed -i "s/etc\/ssl\/certs\/ssl-cert-snakeoil.pem/etc\/ssl\/certs\/apache-selfsigned.crt/1" /etc/apache2/sites-available/default-ssl.conf
|
||||
sed -i "s/etc\/ssl\/private\/ssl-cert-snakeoil.key/etc\/ssl\/private\/apache-selfsigned.key/1" /etc/apache2/sites-available/default-ssl.conf
|
||||
sed -i "4i\\\t\tServerName $ip" /etc/apache2/sites-available/default-ssl.conf
|
||||
sed -i "22i\\\tRedirect permanent \"/\" \"https://$ip/\"" /etc/apache2/sites-available/000-default.conf
|
||||
a2enmod ssl
|
||||
a2enmod headers
|
||||
a2ensite default-ssl
|
||||
a2enconf ssl-params
|
||||
systemctl reload apache2
|
||||
}
|
||||
|
||||
db_config () {
|
||||
mysql -e "CREATE DATABASE $DBNAME;"
|
||||
mysql -e "GRANT ALL ON $DBNAME.* TO '$DBUSERNAME'@'localhost' IDENTIFIED BY '$DBPASSWORD' WITH GRANT OPTION;"
|
||||
mysql -e "FLUSH PRIVILEGES;"
|
||||
}
|
||||
|
||||
wordpress_config () {
|
||||
db_config
|
||||
|
||||
|
||||
apt install php-curl php-gd php-mbstring php-xml php-xmlrpc php-soap php-intl php-zip -y
|
||||
systemctl restart apache2
|
||||
sed -i "8i\\\t<Directory /var/www/$DOMAIN/>" /etc/apache2/sites-available/$DOMAIN.conf
|
||||
sed -i "9i\\\t\tAllowOverride All" /etc/apache2/sites-available/$DOMAIN.conf
|
||||
sed -i "10i\\\t</Directory>" /etc/apache2/sites-available/$DOMAIN.conf
|
||||
|
||||
a2enmod rewrite
|
||||
systemctl restart apache2
|
||||
|
||||
apt install curl
|
||||
cd /tmp
|
||||
curl -O https://wordpress.org/latest.tar.gz
|
||||
tar xzvf latest.tar.gz
|
||||
touch /tmp/wordpress/.htaccess
|
||||
cp /tmp/wordpress/wp-config-sample.php /tmp/wordpress/wp-config.php
|
||||
mkdir /tmp/wordpress/wp-content/upgrade
|
||||
cp -a /tmp/wordpress/. /var/www/$DOMAIN
|
||||
chown -R www-data:www-data /var/www/$DOMAIN
|
||||
find /var/www/$DOMAIN/ -type d -exec chmod 750 {} \;
|
||||
find /var/www/$DOMAIN/ -type f -exec chmod 640 {} \;
|
||||
curl -s https://api.wordpress.org/secret-key/1.1/salt/ >> /var/www/$DOMAIN/wp-config.php
|
||||
echo "define('FS_METHOD', 'direct');" >> /var/www/$DOMAIN/wp-config.php
|
||||
sed -i "51,58d" /var/www/$DOMAIN/wp-config.php
|
||||
sed -i "s/database_name_here/$DBNAME/1" /var/www/$DOMAIN/wp-config.php
|
||||
sed -i "s/username_here/$DBUSERNAME/1" /var/www/$DOMAIN/wp-config.php
|
||||
sed -i "s/password_here/$DBPASSWORD/1" /var/www/$DOMAIN/wp-config.php
|
||||
}
|
||||
|
||||
execute () {
|
||||
lamp_install
|
||||
apache_virtual_host_setup
|
||||
ssl_config
|
||||
wordpress_config
|
||||
}
|
||||
```
|
||||
|
||||
## Summary
|
||||
|
||||
The script does the following:
|
||||
|
||||
* Install LAMP
|
||||
* Create a virtual host
|
||||
* Configure SSL
|
||||
* Install WordPress
|
||||
* Configure WordPress
|
||||
|
||||
With this being said, I hope you enjoyed this example. If you have any questions, please feel free to ask me directly at [@denctl](https://twitter.com/denctl).
|
||||
15
landing/docs/Bash-Scripts/.recycle/100-bash-wrap-up.md
Normal file
15
landing/docs/Bash-Scripts/.recycle/100-bash-wrap-up.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# Wrap Up
|
||||
|
||||
Congratulations! You have just completed the Bash basics guide!
|
||||
|
||||
If you found this useful, be sure to star the project on [GitHub](https://github.com/bobbyiliev/introduction-to-bash-scripting)!
|
||||
|
||||
If you have any suggestions for improvements, make sure to contribute pull requests or open issues.
|
||||
|
||||
In this introduction to Bash scripting book, we just covered the basics, but you still have enough under your belt to start wringing some awesome scripts and automating daily tasks!
|
||||
|
||||
As a next step try writing your own script and share it with the world! This is the best way to learn any new programming or scripting language!
|
||||
|
||||
In case that this book inspired you to write some cool Bash scripts, make sure to tweet about it and tag [@bobbyiliev_](https://twitter.com) so that we could check it out!
|
||||
|
||||
Congrats again on completing this book!
|
||||
23
landing/docs/Bash-Scripts/002-bash-structure.md
Normal file
23
landing/docs/Bash-Scripts/002-bash-structure.md
Normal file
@@ -0,0 +1,23 @@
|
||||
# Bash Basics
|
||||
|
||||
To begin, create a new file with a `.sh` extension. We'll use `shinobi.sh` as our example.
|
||||
|
||||
You can create it instantly with `touch`:
|
||||
|
||||
```bash
|
||||
touch shinobi.sh
|
||||
```
|
||||
|
||||
Or, open it directly in your text editor:
|
||||
|
||||
```bash
|
||||
nano shinobi.sh
|
||||
```
|
||||
|
||||
For your script to execute, the very first line must specify the interpreter. This is called the Shebang. While `#!/bin/bash` instructs the operating system to use `/bin/bash`, its location can vary. For wider compatibility, use this:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
```
|
||||
|
||||
This tells the system to find `bash` within your `PATH` environment variable, ensuring your script runs consistently across different systems.
|
||||
45
landing/docs/Bash-Scripts/003-bash-hello-world.md
Normal file
45
landing/docs/Bash-Scripts/003-bash-hello-world.md
Normal file
@@ -0,0 +1,45 @@
|
||||
# Hello World Bash
|
||||
|
||||
Let's build your first script. Create `shinobi.sh` and add the essential shebang, followed by your `Hello World` message:
|
||||
|
||||
```bash
|
||||
touch shinobi.sh
|
||||
```
|
||||
|
||||
Now, open `shinobi.sh` and add this content:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
echo "Hello World!"
|
||||
```
|
||||
|
||||
Save and close the file.
|
||||
|
||||
Next, make your script executable:
|
||||
|
||||
```bash
|
||||
chmod +x shinobi.sh
|
||||
```
|
||||
|
||||
Execute your script directly:
|
||||
|
||||
```bash
|
||||
./shinobi.sh
|
||||
```
|
||||
|
||||
You'll see "Hello World!" printed.
|
||||
|
||||
Alternatively, you can run the script by explicitly calling the `bash` interpreter:
|
||||
|
||||
```bash
|
||||
bash shinobi.sh
|
||||
```
|
||||
|
||||
For quick tests, `echo` works directly in your terminal:
|
||||
|
||||
```bash
|
||||
echo "Hello Shinobi!"
|
||||
```
|
||||
|
||||
Scripts become powerful when combining multiple commands for automated tasks. This is your first step.
|
||||
121
landing/docs/Bash-Scripts/004-bash-variables.md
Normal file
121
landing/docs/Bash-Scripts/004-bash-variables.md
Normal file
@@ -0,0 +1,121 @@
|
||||
# Variables
|
||||
|
||||
Like any language, Bash uses variables. No strict data types here; a variable holds numbers or characters.
|
||||
|
||||
Assign a value:
|
||||
|
||||
```bash
|
||||
name="Shinobi"
|
||||
```
|
||||
|
||||
> **Note:** No spaces around the `=` sign. This is critical.
|
||||
|
||||
Access the value using `$` before the variable name:
|
||||
|
||||
```bash
|
||||
echo $name
|
||||
```
|
||||
|
||||
While optional, wrapping the name in curly braces is good practice for clarity:
|
||||
|
||||
```bash
|
||||
echo ${name}
|
||||
```
|
||||
|
||||
Both would output: `Shinobi`.
|
||||
|
||||
Now, let's build a script.
|
||||
|
||||
First, create the file:
|
||||
|
||||
```bash
|
||||
touch shinobi.sh
|
||||
```
|
||||
|
||||
Then, open `shinobi.sh` and add this content to include a variable:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
name="Shinobi"
|
||||
|
||||
echo "Hi there $name"
|
||||
```
|
||||
|
||||
Save and exit.
|
||||
|
||||
Make it executable:
|
||||
|
||||
```bash
|
||||
chmod +x shinobi.sh
|
||||
```
|
||||
|
||||
Run your script:
|
||||
|
||||
```bash
|
||||
./shinobi.sh
|
||||
```
|
||||
|
||||
You'll see:
|
||||
|
||||
```bash
|
||||
Hi there Shinobi
|
||||
```
|
||||
|
||||
This script:
|
||||
* `#!/usr/bin/env bash`: Sets the interpreter.
|
||||
* `name="Shinobi"`: Defines `name` with its value.
|
||||
* `echo "Hi there $name"`: Outputs the welcome message using the variable.
|
||||
|
||||
You can use multiple variables:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
name="Shinobi"
|
||||
greeting="Hello"
|
||||
|
||||
echo "$greeting $name"
|
||||
```
|
||||
|
||||
Save and run `shinobi.sh` again:
|
||||
|
||||
```bash
|
||||
./shinobi.sh
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```bash
|
||||
Hello Shinobi
|
||||
```
|
||||
|
||||
No semicolons needed at line ends.
|
||||
|
||||
### Command Line Parameters
|
||||
|
||||
Bash scripts also read variables passed directly from the command line. These are called parameters.
|
||||
|
||||
Run your script with inputs like this:
|
||||
|
||||
```bash
|
||||
./shinobi.sh Troy buddy!
|
||||
```
|
||||
|
||||
Now, modify your `shinobi.sh` file to access these parameters:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
echo "Hello there" $1 # $1: first parameter
|
||||
echo "Hello there" $2 # $2: second parameter
|
||||
echo "Hello there" $@ # $@: all parameters
|
||||
```
|
||||
|
||||
The output for `./shinobi.sh Troy buddy!` will be:
|
||||
|
||||
```bash
|
||||
Hello there Troy
|
||||
Hello there buddy!
|
||||
Hello there Troy buddy!
|
||||
```
|
||||
64
landing/docs/Bash-Scripts/005-bash-user-input.md
Normal file
64
landing/docs/Bash-Scripts/005-bash-user-input.md
Normal file
@@ -0,0 +1,64 @@
|
||||
# User Input
|
||||
|
||||
You've outputted variable values. Now, let's get input from the user.
|
||||
|
||||
First, create your script file:
|
||||
|
||||
```bash
|
||||
touch shinobi.sh
|
||||
```
|
||||
|
||||
Next, open `shinobi.sh` and add this:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
echo "What is your name?"
|
||||
read name
|
||||
|
||||
echo "Hi there $name"
|
||||
echo "Welcome to Shinobi!"
|
||||
```
|
||||
|
||||
Save and exit the file.
|
||||
|
||||
Make it executable:
|
||||
|
||||
```bash
|
||||
chmod +x shinobi.sh
|
||||
```
|
||||
|
||||
Run your script:
|
||||
|
||||
```bash
|
||||
./shinobi.sh
|
||||
```
|
||||
|
||||
The script will prompt you:
|
||||
|
||||
```
|
||||
What is your name?
|
||||
Troy
|
||||
```
|
||||
|
||||
Enter a name (e.g., `Troy`) and hit Enter. You'll see:
|
||||
|
||||
```
|
||||
Hi there Troy
|
||||
Welcome to Shinobi!
|
||||
```
|
||||
|
||||
This script prompts the user, stores their input in the `name` variable, then uses it to print a personalized message.
|
||||
|
||||
### Streamlined Input
|
||||
|
||||
To reduce lines, use `read` with the `-p` flag. This prints a prompt before waiting for input:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
read -p "What is your name? " name
|
||||
|
||||
echo "Hi there $name"
|
||||
echo "Welcome to Shinobi!"
|
||||
```
|
||||
40
landing/docs/Bash-Scripts/006-bash-comments.md
Normal file
40
landing/docs/Bash-Scripts/006-bash-comments.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# Comments
|
||||
|
||||
Add comments to your Bash scripts for notes and clarity. Lines starting with `#` are ignored by the interpreter.
|
||||
|
||||
```bash
|
||||
# This is a comment. It will not run.
|
||||
```
|
||||
|
||||
Let's create a new script, `shinobi.sh`, and include comments:
|
||||
|
||||
```bash
|
||||
touch shinobi.sh
|
||||
```
|
||||
|
||||
Now, open `shinobi.sh` and add this:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Ask the user for their name
|
||||
|
||||
read -p "What is your name? " name
|
||||
|
||||
# Greet the user
|
||||
|
||||
echo "Hi there $name"
|
||||
|
||||
echo "Welcome to Dev Team Six!"
|
||||
```
|
||||
|
||||
Save and exit.
|
||||
|
||||
Make your script executable and run it:
|
||||
|
||||
```bash
|
||||
chmod +x shinobi.sh
|
||||
./shinobi.sh
|
||||
```
|
||||
|
||||
Comments are essential. They make your code readable, for yourself and for anyone else who works on it. Clarity drives efficiency.
|
||||
101
landing/docs/Bash-Scripts/007-bash-arguments.md
Normal file
101
landing/docs/Bash-Scripts/007-bash-arguments.md
Normal file
@@ -0,0 +1,101 @@
|
||||
# Runtime Arguments
|
||||
|
||||
Pass data into your script at execution. Arguments follow the script name:
|
||||
|
||||
```bash
|
||||
./your_script.sh first_argument
|
||||
```
|
||||
|
||||
Inside the script, `$1` references the first argument, `$2` the second, and so on.
|
||||
|
||||
Let's see this in `arguments.sh`:
|
||||
|
||||
```bash
|
||||
touch arguments.sh
|
||||
```
|
||||
|
||||
Open `arguments.sh` and add:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
echo "Arg 1: $1"
|
||||
echo "Arg 2: $2"
|
||||
echo "Arg 3: $3"
|
||||
```
|
||||
|
||||
Save and exit. Make it executable:
|
||||
|
||||
```bash
|
||||
chmod +x arguments.sh
|
||||
```
|
||||
|
||||
Run with three arguments:
|
||||
|
||||
```bash
|
||||
./arguments.sh dog cat bird
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```bash
|
||||
Arg 1: dog
|
||||
Arg 2: cat
|
||||
Arg 3: bird
|
||||
```
|
||||
|
||||
To access *all* arguments, use `$@`. Update `arguments.sh`:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
echo "All arguments: $@"
|
||||
```
|
||||
|
||||
Save. Run again with arguments:
|
||||
|
||||
```bash
|
||||
./arguments.sh dog cat bird
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```bash
|
||||
All arguments: dog cat bird
|
||||
```
|
||||
|
||||
### Script Name (`$0`)
|
||||
|
||||
`$0` references the script itself. This is useful for logging or unique operations.
|
||||
|
||||
You can even use `$0` for self-deletion. **Handle with extreme caution!**
|
||||
|
||||
Create `self_destruct.sh`:
|
||||
|
||||
```bash
|
||||
touch self_destruct.sh
|
||||
```
|
||||
|
||||
Open `self_destruct.sh` and add:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
echo "This script: $0 is self-destructing."
|
||||
|
||||
rm -f $0
|
||||
```
|
||||
|
||||
Save and exit. Make it executable:
|
||||
|
||||
```bash
|
||||
chmod +x self_destruct.sh
|
||||
```
|
||||
|
||||
Run it:
|
||||
|
||||
```bash
|
||||
./self_destruct.sh
|
||||
```
|
||||
|
||||
The script will print its name, then delete itself. **This is irreversible. No second chances.** Always back up before testing self-deletion.
|
||||
97
landing/docs/Bash-Scripts/008-bash-arrays.md
Normal file
97
landing/docs/Bash-Scripts/008-bash-arrays.md
Normal file
@@ -0,0 +1,97 @@
|
||||
# Arrays
|
||||
|
||||
Arrays are essential. They let a single variable hold multiple values. Initialize them by listing values, separated by spaces, inside parentheses:
|
||||
|
||||
```bash
|
||||
# Example initialization:
|
||||
my_array=("value 1" "value 2" "value 3" "value 4")
|
||||
```
|
||||
|
||||
Access array elements using their numeric index. **Always use curly brackets.**
|
||||
|
||||
Let's create `arrays.sh` to demonstrate:
|
||||
|
||||
```bash
|
||||
touch arrays.sh
|
||||
```
|
||||
|
||||
Now, open `arrays.sh` and add:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
my_array=("value 1" "value 2" "value 3" "value 4")
|
||||
|
||||
echo "Second element (index 1): ${my_array[1]}"
|
||||
echo "Last element (index -1): ${my_array[-1]}"
|
||||
echo "All elements: ${my_array[@]}"
|
||||
echo "Total elements: ${#my_array[@]}"
|
||||
```
|
||||
|
||||
Save and exit. Make it executable:
|
||||
|
||||
```bash
|
||||
chmod +x arrays.sh
|
||||
```
|
||||
|
||||
Run your script:
|
||||
|
||||
```bash
|
||||
./arrays.sh
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
value 2
|
||||
value 4
|
||||
value 1 value 2 value 3 value 4
|
||||
4
|
||||
```
|
||||
|
||||
### Slicing
|
||||
|
||||
Extract specific portions of an array or string using slicing notation.
|
||||
|
||||
Create `slicing.sh`:
|
||||
|
||||
```bash
|
||||
touch slicing.sh
|
||||
```
|
||||
|
||||
Open `slicing.sh` and add these examples:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
letters=("A" "B" "C" "D" "E")
|
||||
|
||||
echo "Original array: ${letters[@]}"
|
||||
|
||||
echo "Example 1 (start 0, length 2): ${letters:0:2}" # Prints AB
|
||||
echo "Example 2 (start 0, all elements): ${letters::5}" # Prints ABCDE
|
||||
echo "Example 3 (start 3, to end): ${letters:3}" # Prints DE
|
||||
```
|
||||
|
||||
Save and exit. Make it executable:
|
||||
|
||||
```bash
|
||||
chmod +x slicing.sh
|
||||
```
|
||||
|
||||
Run `slicing.sh`:
|
||||
|
||||
```bash
|
||||
./slicing.sh
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
A B C D E
|
||||
AB
|
||||
ABCDE
|
||||
DE
|
||||
```
|
||||
|
||||
Mastering arrays and slicing gives you precise control over your data structures.
|
||||
110
landing/docs/Bash-Scripts/009-bash-conditional-expressions.md
Normal file
110
landing/docs/Bash-Scripts/009-bash-conditional-expressions.md
Normal file
@@ -0,0 +1,110 @@
|
||||
# Conditional Expressions
|
||||
|
||||
Conditionals are how your scripts make decisions: run different code based on a true/false outcome.
|
||||
|
||||
In Bash, `[[` is your go-to for testing files, strings, and numbers.
|
||||
|
||||
Let's start with a basic example:
|
||||
|
||||
```bash
|
||||
touch conditional_test.sh
|
||||
```
|
||||
|
||||
Open `conditional_test.sh` and add:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
my_var="data"
|
||||
|
||||
if [[ -n "$my_var" ]]; then # If variable is not empty
|
||||
echo "Variable contains data."
|
||||
fi
|
||||
```
|
||||
|
||||
Save, make executable, and run:
|
||||
|
||||
```bash
|
||||
chmod +x conditional_test.sh
|
||||
./conditional_test.sh
|
||||
```
|
||||
|
||||
Output: `Variable contains data.`
|
||||
|
||||
Now, for your full reference:
|
||||
|
||||
## File Tests
|
||||
|
||||
These check file attributes. Use `"${file}"` to handle spaces in names.
|
||||
|
||||
* `[[ -e "${file}" ]]` - True if `file` exists.
|
||||
* `[[ -f "${file}" ]]` - True if `file` exists and is a regular file.
|
||||
* `[[ -d "${file}" ]]` - True if `file` exists and is a directory.
|
||||
* `[[ -s "${file}" ]]` - True if `file` exists and is not empty (size > 0).
|
||||
* `[[ -r "${file}" ]]` - True if `file` exists and is readable.
|
||||
* `[[ -w "${file}" ]]` - True if `file` exists and is writable.
|
||||
* `[[ -x "${file}" ]]` - True if `file` exists and is executable.
|
||||
* `[[ -L "${file}" ]]` - True if `file` is a symbolic link (`-h` is also used).
|
||||
* `[[ -b "${file}" ]]` - True if `file` exists and is a block device.
|
||||
* `[[ -c "${file}" ]]` - True if `file` exists and is a character device.
|
||||
|
||||
## String Tests
|
||||
|
||||
Compare string properties and values.
|
||||
|
||||
* `[[ -v "${varname}" ]]` - True if `varname` is set (has a value).
|
||||
* `[[ -z "${string}" ]]` - True if `string` has zero length (empty).
|
||||
* `[[ -n "${string}" ]]` - True if `string` has non-zero length (not empty).
|
||||
* `[[ "${string1}" == "${string2}" ]]` - True if strings are equal. (`==` allows pattern matching inside `[[`.)
|
||||
* `[[ "${string1}" != "${string2}" ]]` - True if strings are not equal.
|
||||
* `[[ "${string1}" < "${string2}" ]]` - True if `string1` sorts before `string2` lexicographically.
|
||||
* `[[ "${string1}" > "${string2}" ]]` - True if `string1` sorts after `string2` lexicographically.
|
||||
|
||||
## Numeric Comparisons
|
||||
|
||||
Compare integer values.
|
||||
|
||||
* `[[ ${arg1} -eq ${arg2} ]]` - True if `arg1` equals `arg2`.
|
||||
* `[[ ${arg1} -ne ${arg2} ]]` - True if `arg1` not equals `arg2`.
|
||||
* `[[ ${arg1} -lt ${arg2} ]]` - True if `arg1` less than `arg2`.
|
||||
* `[[ ${arg1} -le ${arg2} ]]` - True if `arg1` less than or equal to `arg2`.
|
||||
* `[[ ${arg1} -gt ${arg2} ]]` - True if `arg1` greater than `arg2`.
|
||||
* `[[ ${arg1} -ge ${arg2} ]]` - True if `arg1` greater than or equal to `arg2`.
|
||||
|
||||
## Logical Operators
|
||||
|
||||
Combine multiple conditions.
|
||||
|
||||
* **AND (`&&`)**: Both conditions must be true.
|
||||
```bash
|
||||
# Example: file exists AND is not empty
|
||||
if [[ -f "my_file.txt" && -s "my_file.txt" ]]; then
|
||||
echo "File is present and has content."
|
||||
fi
|
||||
```
|
||||
* **OR (`||`)**: At least one condition must be true.
|
||||
```bash
|
||||
# Example: either file or directory exists
|
||||
if [[ -f "another_file.txt" || -d "another_dir" ]]; then
|
||||
echo "Found a file or a directory."
|
||||
fi
|
||||
```
|
||||
|
||||
## Exit Status Checks
|
||||
|
||||
`$?:` The exit status of the *last* executed command. `0` means success. Any non-zero value indicates an error.
|
||||
|
||||
* **Success:**
|
||||
```bash
|
||||
command_to_run
|
||||
if [[ $? -eq 0 ]]; then
|
||||
echo "Command succeeded."
|
||||
fi
|
||||
```
|
||||
* **Failure:**
|
||||
```bash
|
||||
command_to_run
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo "Command failed."
|
||||
fi
|
||||
```
|
||||
237
landing/docs/Bash-Scripts/010-bash-conditionals.md
Normal file
237
landing/docs/Bash-Scripts/010-bash-conditionals.md
Normal file
@@ -0,0 +1,237 @@
|
||||
# Conditionals
|
||||
|
||||
You've mastered conditional expressions. Now, let's put them to work using `if`, `if-else`, `elif`, and `case` statements to control your script's flow.
|
||||
|
||||
---
|
||||
|
||||
### If Statements
|
||||
|
||||
The `if` statement executes commands only if a condition is true.
|
||||
|
||||
```bash
|
||||
if [[ some_test ]]
|
||||
then
|
||||
<commands>
|
||||
fi
|
||||
```
|
||||
|
||||
Example: Prompt for a name, then check if it's empty.
|
||||
|
||||
```bash
|
||||
touch if_example.sh
|
||||
```
|
||||
|
||||
Open `if_example.sh` and add:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
read -p "What is your name? " name
|
||||
|
||||
if [[ -z "${name}" ]]; then # Check if name is empty
|
||||
echo "Please enter your name!"
|
||||
fi
|
||||
```
|
||||
|
||||
Save and exit. Make it executable and run:
|
||||
|
||||
```bash
|
||||
chmod +x if_example.sh
|
||||
./if_example.sh
|
||||
```
|
||||
|
||||
### If-Else Statements
|
||||
|
||||
Use `else` to define actions when the `if` condition is false.
|
||||
|
||||
Create `if_else_example.sh`:
|
||||
|
||||
```bash
|
||||
touch if_else_example.sh
|
||||
```
|
||||
|
||||
Open `if_else_example.sh` and add:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
read -p "What is your name? " name
|
||||
|
||||
if [[ -z "${name}" ]]; then
|
||||
echo "Please enter your name!"
|
||||
else
|
||||
echo "Hi there ${name}!"
|
||||
fi
|
||||
```
|
||||
|
||||
Save, make executable, and run.
|
||||
|
||||
### Admin/Root Checks
|
||||
|
||||
Check user roles. For admin verification:
|
||||
|
||||
Create `admin_check.sh`:
|
||||
|
||||
```bash
|
||||
touch admin_check.sh
|
||||
```
|
||||
|
||||
Open `admin_check.sh` and add:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
admin="Dev Team Six"
|
||||
|
||||
read -p "Enter your username: " username
|
||||
|
||||
if [[ "${username}" == "${admin}" ]]; then
|
||||
echo "You are the admin user!"
|
||||
else
|
||||
echo "You are NOT the admin user!"
|
||||
fi
|
||||
```
|
||||
|
||||
Save, make executable, and run.
|
||||
|
||||
To prevent a script from running as `root` (`EUID` is 0 for root):
|
||||
|
||||
Create `root_check.sh`:
|
||||
|
||||
```bash
|
||||
touch root_check.sh
|
||||
```
|
||||
|
||||
Open `root_check.sh` and add:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
if [[ $EUID -eq 0 ]]; then # Check if current user ID is 0 (root)
|
||||
echo "This script should not be run as root. Exiting."
|
||||
exit 1 # Exit with error code
|
||||
fi
|
||||
echo "Script running as non-root user."
|
||||
```
|
||||
|
||||
Save, make executable, and run (test as root and non-root).
|
||||
|
||||
Combine conditions for stricter control. This example ensures the user is neither `admin` nor `root`.
|
||||
|
||||
Create `combined_check.sh`:
|
||||
|
||||
```bash
|
||||
touch combined_check.sh
|
||||
```
|
||||
|
||||
Open `combined_check.sh` and add:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
admin_user="Dev Team Six"
|
||||
|
||||
read -p "Enter your username: " username
|
||||
|
||||
if [[ "${username}" != "${admin_user}" || $EUID -ne 0 ]]; then # OR operator
|
||||
echo "You are not the admin or root user. Proceeding safely."
|
||||
else
|
||||
echo "You are an admin or root user. Exercise caution."
|
||||
fi
|
||||
```
|
||||
|
||||
Save, make executable, and run.
|
||||
|
||||
### Elif Statements
|
||||
|
||||
For multiple, mutually exclusive conditions, use `elif`.
|
||||
|
||||
Create `elif_example.sh`:
|
||||
|
||||
```bash
|
||||
touch elif_example.sh
|
||||
```
|
||||
|
||||
Open `elif_example.sh` and add:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
read -p "Enter a number: " num
|
||||
|
||||
if [[ $num -gt 0 ]]; then
|
||||
echo "The number is positive."
|
||||
elif [[ $num -lt 0 ]]; then
|
||||
echo "The number is negative."
|
||||
else
|
||||
echo "The number is 0."
|
||||
fi
|
||||
```
|
||||
|
||||
Save, make executable, and run.
|
||||
|
||||
### Case Statements
|
||||
|
||||
Simplify complex conditionals with `case` when you have multiple choices.
|
||||
|
||||
The `case` syntax:
|
||||
|
||||
```bash
|
||||
case $variable_to_test in
|
||||
pattern_1)
|
||||
commands_for_pattern_1
|
||||
;;
|
||||
pattern_2|pattern_3) # Multiple patterns with |
|
||||
commands_for_pattern_2_or_3
|
||||
;;
|
||||
*) # Default case (catch-all)
|
||||
default_commands
|
||||
;;
|
||||
esac
|
||||
```
|
||||
|
||||
Key points: `case` starts the statement, `in` follows the variable. Patterns end with `)`. Commands are terminated by `;;`. `*` is the default. `esac` closes the statement.
|
||||
|
||||
Example: Check car brand and factory location.
|
||||
|
||||
Create `car_brand_case.sh`:
|
||||
|
||||
```bash
|
||||
touch car_brand_case.sh
|
||||
```
|
||||
|
||||
Open `car_brand_case.sh` and add:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
read -p "Enter the name of your car brand: " car
|
||||
|
||||
case $car in
|
||||
|
||||
Tesla)
|
||||
echo "${car}'s factory is in the USA."
|
||||
;;
|
||||
|
||||
BMW | Mercedes | Audi | Porsche)
|
||||
echo "${car}'s factory is in Germany."
|
||||
;;
|
||||
|
||||
Toyota | Mazda | Mitsubishi | Subaru)
|
||||
echo "${car}'s factory is in Japan."
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "${car} is an unknown car brand."
|
||||
;;
|
||||
|
||||
esac
|
||||
```
|
||||
|
||||
Save, make executable, and run.
|
||||
|
||||
---
|
||||
|
||||
### Conclusion
|
||||
|
||||
Practice these conditional structures. Modify the examples. Mastering flow control is critical for effective scripting.
|
||||
232
landing/docs/Bash-Scripts/011-bash-loops.md
Normal file
232
landing/docs/Bash-Scripts/011-bash-loops.md
Normal file
@@ -0,0 +1,232 @@
|
||||
# Loops
|
||||
|
||||
Loops are fundamental for automation. Bash provides `for`, `while`, and `until` loops to repeat commands efficiently.
|
||||
|
||||
---
|
||||
|
||||
### For Loops
|
||||
|
||||
The `for` loop iterates through a list of items.
|
||||
|
||||
```bash
|
||||
for var in ${list}
|
||||
do
|
||||
your_commands
|
||||
done
|
||||
```
|
||||
|
||||
Example: Loop through a list of users.
|
||||
|
||||
```bash
|
||||
touch for_users.sh
|
||||
```
|
||||
|
||||
Open `for_users.sh` and add:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
users="Dev Team Six softwareshinobi troy"
|
||||
|
||||
for user in ${users}
|
||||
do
|
||||
echo "${user}"
|
||||
done
|
||||
```
|
||||
|
||||
Save and exit. Make it executable and run:
|
||||
|
||||
```bash
|
||||
chmod +x for_users.sh
|
||||
./for_users.sh
|
||||
```
|
||||
|
||||
Output:
|
||||
```
|
||||
Dev Team Six
|
||||
softwareshinobi
|
||||
troy
|
||||
```
|
||||
|
||||
Loop through a range of numbers:
|
||||
|
||||
```bash
|
||||
touch for_numbers.sh
|
||||
```
|
||||
|
||||
Open `for_numbers.sh` and add:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
for num in {1..10}
|
||||
do
|
||||
echo ${num}
|
||||
done
|
||||
```
|
||||
|
||||
Save, make executable, and run.
|
||||
|
||||
### While Loops
|
||||
|
||||
A `while` loop continues as long as its condition remains true.
|
||||
|
||||
```bash
|
||||
while [[ your_condition ]]
|
||||
do
|
||||
your_commands
|
||||
done
|
||||
```
|
||||
|
||||
Example: Counter from 1 to 10.
|
||||
|
||||
```bash
|
||||
touch while_counter.sh
|
||||
```
|
||||
|
||||
Open `while_counter.sh` and add:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
counter=1
|
||||
while [[ $counter -le 10 ]]
|
||||
do
|
||||
echo $counter
|
||||
((counter++)) # Increment counter
|
||||
done
|
||||
```
|
||||
|
||||
Save, make executable, run.
|
||||
|
||||
Example: Require user input. Loop until a non-empty name is provided.
|
||||
|
||||
```bash
|
||||
touch while_input.sh
|
||||
```
|
||||
|
||||
Open `while_input.sh` and add:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
read -p "What is your name? " name
|
||||
|
||||
while [[ -z "${name}" ]]
|
||||
do
|
||||
echo "Name cannot be blank. Please enter a valid name!"
|
||||
read -p "Enter your name again: " name
|
||||
done
|
||||
|
||||
echo "Hi there ${name}!"
|
||||
```
|
||||
|
||||
Save, make executable, run (test with empty and valid input).
|
||||
|
||||
### Until Loops
|
||||
|
||||
An `until` loop runs *until* its condition becomes true.
|
||||
|
||||
```bash
|
||||
until [[ your_condition ]]
|
||||
do
|
||||
your_commands
|
||||
done
|
||||
```
|
||||
|
||||
Example: Counter from 1 to 10.
|
||||
|
||||
```bash
|
||||
touch until_loop.sh
|
||||
```
|
||||
|
||||
Open `until_loop.sh` and add:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
count=1
|
||||
until [[ $count -gt 10 ]]
|
||||
do
|
||||
echo $count
|
||||
((count++))
|
||||
done
|
||||
```
|
||||
|
||||
Save, make executable, run.
|
||||
|
||||
### Continue and Break
|
||||
|
||||
Control loop flow with `continue` (skip current iteration) and `break` (exit loop entirely).
|
||||
|
||||
#### `continue`
|
||||
|
||||
```bash
|
||||
touch continue_example.sh
|
||||
```
|
||||
|
||||
Open `continue_example.sh` and add:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
for i in 1 2 3 4 5
|
||||
do
|
||||
if [[ $i -eq 2 ]]; then
|
||||
echo "Skipping number 2"
|
||||
continue # Skip to next iteration
|
||||
fi
|
||||
echo "i is equal to $i"
|
||||
done
|
||||
```
|
||||
|
||||
Save, make executable, run.
|
||||
|
||||
#### `break`
|
||||
|
||||
```bash
|
||||
touch break_example.sh
|
||||
```
|
||||
|
||||
Open `break_example.sh` and add:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
num=1
|
||||
while [[ $num -lt 10 ]]; do
|
||||
if [[ $num -eq 5 ]]; then
|
||||
break # Exit loop
|
||||
fi
|
||||
((num++))
|
||||
done
|
||||
echo "Loop completed. Num stopped at: $num"
|
||||
```
|
||||
|
||||
Save, make executable, run.
|
||||
|
||||
For nested loops, `break N` exits `N` levels of loops. `break 2` exits the current and the parent loop.
|
||||
|
||||
```bash
|
||||
touch nested_break_example.sh
|
||||
```
|
||||
|
||||
Open `nested_break_example.sh` and add:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
for (( a = 1; a < 3; a++ )); do # Outer loop
|
||||
echo "Outer loop: $a"
|
||||
for (( b = 1; b < 5; b++ )); do # Inner loop
|
||||
if [[ $b -gt 2 ]]; then
|
||||
echo " Breaking inner and outer loop at b=$b"
|
||||
break 2 # Exits both loops
|
||||
fi
|
||||
echo " Inner loop: $b"
|
||||
done
|
||||
done
|
||||
echo "All loops finished."
|
||||
```
|
||||
|
||||
Save, make executable, run.
|
||||
87
landing/docs/Bash-Scripts/012-bash-functions.md
Normal file
87
landing/docs/Bash-Scripts/012-bash-functions.md
Normal file
@@ -0,0 +1,87 @@
|
||||
# Functions
|
||||
|
||||
Functions organize your code for reuse. Here's the structure:
|
||||
|
||||
```bash
|
||||
function_name() {
|
||||
your_commands
|
||||
}
|
||||
```
|
||||
|
||||
You can also use the `function` keyword for clarity, though it's optional:
|
||||
|
||||
```bash
|
||||
function function_name() {
|
||||
your_commands
|
||||
}
|
||||
```
|
||||
|
||||
Example: A simple 'Hello World!' function.
|
||||
|
||||
```bash
|
||||
touch hello_function.sh
|
||||
```
|
||||
|
||||
Open `hello_function.sh` and add:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
function hello() {
|
||||
echo "Hello World Function!"
|
||||
}
|
||||
|
||||
hello # Call the function (no parentheses)
|
||||
```
|
||||
|
||||
Save and exit. Make it executable and run:
|
||||
|
||||
```bash
|
||||
chmod +x hello_function.sh
|
||||
./hello_function.sh
|
||||
```
|
||||
|
||||
Functions accept arguments just like scripts.
|
||||
|
||||
```bash
|
||||
touch function_args.sh
|
||||
```
|
||||
|
||||
Open `function_args.sh` and add:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
function greet_team() {
|
||||
echo "Hello $1!"
|
||||
}
|
||||
|
||||
greet_team "Dev Team Six" # Pass argument when calling
|
||||
```
|
||||
|
||||
Save and exit. Make it executable and run:
|
||||
|
||||
```bash
|
||||
chmod +x function_args.sh
|
||||
./function_args.sh
|
||||
```
|
||||
|
||||
Document your functions clearly. Include a description, arguments, and expected output/return values.
|
||||
|
||||
```bash
|
||||
#######################################
|
||||
# Description: Greets a single argument.
|
||||
# Globals: None
|
||||
# Arguments:
|
||||
# $1 - Name/value to greet.
|
||||
# Outputs:
|
||||
# Prints a greeting to stdout.
|
||||
# Returns:
|
||||
# 0 on success.
|
||||
#######################################
|
||||
function greet_example() {
|
||||
echo "Greeting: $1"
|
||||
}
|
||||
```
|
||||
|
||||
Functions are key to building organized and reusable Bash scripts. Master them for efficient automation.
|
||||
42
landing/docs/Bash-Scripts/013-debugging.md
Normal file
42
landing/docs/Bash-Scripts/013-debugging.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# Debugging
|
||||
|
||||
Debugging is vital for efficient Bash scripting.
|
||||
|
||||
### Debugging Your Scripts
|
||||
|
||||
Troubleshoot your Bash scripts by tracing execution. Use `-x` directly or `set -x` for specific sections.
|
||||
|
||||
Run your script with `bash -x` to see every command executed:
|
||||
|
||||
```bash
|
||||
bash -x ./your_script.sh
|
||||
```
|
||||
|
||||
For targeted debugging, use `set -x` where you want to start tracing, and `set +x` to stop.
|
||||
|
||||
Create `debug_example.sh`:
|
||||
|
||||
```bash
|
||||
touch debug_example.sh
|
||||
```
|
||||
|
||||
Open `debug_example.sh` and add:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
echo "Starting script."
|
||||
set -x # Enable debug mode from here
|
||||
ls -l
|
||||
my_variable="test_data"
|
||||
echo "Variable is: $my_variable"
|
||||
set +x # Disable debug mode
|
||||
echo "Debugging finished."
|
||||
```
|
||||
|
||||
Save, make executable, and run:
|
||||
|
||||
```bash
|
||||
chmod +x debug_example.sh
|
||||
./debug_example.sh
|
||||
```
|
||||
44
landing/docs/Bash-Scripts/0131-debugging.md
Normal file
44
landing/docs/Bash-Scripts/0131-debugging.md
Normal file
@@ -0,0 +1,44 @@
|
||||
# Debugging
|
||||
|
||||
Ensure your Bash scripts run flawlessly. Master debugging to identify issues quickly and build robust code.
|
||||
|
||||
### Debugging Your Scripts
|
||||
|
||||
Troubleshoot your Bash scripts by tracing execution. Use `-x` directly or `set -x` for specific sections.
|
||||
|
||||
Run your script with `bash -x` to see every command executed:
|
||||
|
||||
```bash
|
||||
bash -x ./your_script.sh
|
||||
```
|
||||
|
||||
For targeted debugging, use `set -x` where you want to start tracing, and `set +x` to stop.
|
||||
|
||||
Create `debug_example.sh`:
|
||||
|
||||
```bash
|
||||
touch debug_example.sh
|
||||
```
|
||||
|
||||
Open `debug_example.sh` and add:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
echo "Starting script."
|
||||
set -x # Enable debug mode from here
|
||||
ls -l
|
||||
my_variable="test_data"
|
||||
echo "Variable is: $my_variable"
|
||||
set +x # Disable debug mode
|
||||
echo "Debugging finished."
|
||||
```
|
||||
|
||||
Save, make executable, and run:
|
||||
|
||||
```bash
|
||||
chmod +x debug_example.sh
|
||||
./debug_example.sh
|
||||
```
|
||||
|
||||
Master these debugging techniques. They are indispensable for building high-quality, dependable Bash scripts.
|
||||
@@ -0,0 +1,82 @@
|
||||
# Custom Commands
|
||||
|
||||
Optimize repetitive terminal tasks. Custom commands, or aliases, create shortcuts for long or frequently used commands.
|
||||
|
||||
### Creating an Alias
|
||||
|
||||
Consider a common scenario: checking web server connections with a lengthy `netstat` command:
|
||||
|
||||
```bash
|
||||
netstat -plant | grep '80\|443' | grep -v LISTEN | wc -l
|
||||
```
|
||||
|
||||
Typing this repeatedly is inefficient. Create an alias as a shortcut. For example, let `conn` execute this command.
|
||||
|
||||
```bash
|
||||
alias conn="netstat -plant | grep '80\|443' | grep -v LISTEN | wc -l"
|
||||
```
|
||||
|
||||
Now, simply type `conn`:
|
||||
|
||||
```bash
|
||||
conn
|
||||
```
|
||||
|
||||
You'll get the same output.
|
||||
|
||||
Enhance it with an informative message:
|
||||
|
||||
```bash
|
||||
alias conn="echo 'Total connections on port 80 and 443:' ; netstat -plant | grep '80\|443' | grep -v LISTEN | wc -l"
|
||||
```
|
||||
|
||||
Running `conn` will now yield:
|
||||
|
||||
```
|
||||
Total connections on port 80 and 443:
|
||||
12
|
||||
```
|
||||
|
||||
Note: Aliases created this way are temporary. They disappear when your terminal session ends.
|
||||
|
||||
### Making Aliases Permanent
|
||||
|
||||
Aliases are session-bound by default. To make them permanent, add them to your shell's profile file. For Bash, this is typically `~/.bashrc`.
|
||||
|
||||
Open `~/.bashrc` (or create it if it doesn't exist):
|
||||
|
||||
```bash
|
||||
nano ~/.bashrc
|
||||
```
|
||||
|
||||
Add your alias to the end of the file:
|
||||
|
||||
```bash
|
||||
alias conn="echo 'Total connections on port 80 and 443:' ; netstat -plant | grep '80\|443' | grep -v LISTEN | wc -l"
|
||||
```
|
||||
|
||||
Save and exit.
|
||||
|
||||
Apply changes without restarting your terminal:
|
||||
|
||||
```bash
|
||||
source ~/.bashrc
|
||||
```
|
||||
|
||||
Now, your custom command `conn` will be available in all new and sourced terminal sessions.
|
||||
|
||||
### Listing Aliases
|
||||
|
||||
To view all active aliases in your current shell, simply run:
|
||||
|
||||
```bash
|
||||
alias
|
||||
```
|
||||
|
||||
This helps in troubleshooting command behavior.
|
||||
|
||||
### Conclusion
|
||||
|
||||
Aliases are powerful tools for optimizing your terminal workflow, offering quick command shortcuts. While full Bash scripts offer more complexity, aliases provide an immediate, user-level solution without requiring root access for installation.
|
||||
|
||||
> {notice} This content was inspired by a piece by softwareshinobi on Dev Team Six.
|
||||
142
landing/docs/Bash-Scripts/015-writing-your-first-bash-script.md
Normal file
142
landing/docs/Bash-Scripts/015-writing-your-first-bash-script.md
Normal file
@@ -0,0 +1,142 @@
|
||||
# Your First Bash Script
|
||||
|
||||
Time to build your first Bash script. We'll create a script to monitor server status, including:
|
||||
* Disk usage
|
||||
* CPU load
|
||||
* RAM usage (Memory)
|
||||
* TCP connections
|
||||
* Kernel version
|
||||
|
||||
Customize as needed.
|
||||
|
||||
### Script Setup
|
||||
|
||||
First, create your script file, `status.sh`:
|
||||
|
||||
```bash
|
||||
touch status.sh
|
||||
```
|
||||
|
||||
Open `status.sh` with your text editor. Start with the shebang, `#!/usr/bin/env bash`. This tells the system how to execute the script.
|
||||
|
||||
Add initial comments for clarity:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Script to report current server status.
|
||||
```
|
||||
|
||||
### Variables
|
||||
|
||||
Variables store data. Assign values using `=` (no spaces). Use `$()` for command substitution.
|
||||
|
||||
Capture the server's hostname:
|
||||
|
||||
```bash
|
||||
server_name=$(hostname)
|
||||
```
|
||||
|
||||
Echo the variable to see its value:
|
||||
|
||||
```bash
|
||||
echo "${server_name}"
|
||||
```
|
||||
|
||||
### Functions
|
||||
|
||||
Functions group commands for reuse. Let's create one for memory usage:
|
||||
|
||||
```bash
|
||||
function memory_check() {
|
||||
echo ""
|
||||
echo "Memory usage on ${server_name}: "
|
||||
free -h
|
||||
echo ""
|
||||
}
|
||||
```
|
||||
|
||||
This function prints a message and calls `free -h` for memory details. Call it by name (no parentheses):
|
||||
|
||||
```bash
|
||||
memory_check
|
||||
```
|
||||
|
||||
Before seeing the complete solution, try implementing functions for:
|
||||
* Disk usage
|
||||
* CPU load
|
||||
* TCP connections
|
||||
* Kernel version
|
||||
|
||||
Google commands if needed. There are multiple valid approaches.
|
||||
|
||||
### The Complete Script
|
||||
|
||||
Here's the full `status.sh` script:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
##
|
||||
# Server status script:
|
||||
# - Memory usage
|
||||
# - CPU load
|
||||
# - TCP connections
|
||||
# - Kernel version
|
||||
##
|
||||
|
||||
server_name=$(hostname)
|
||||
|
||||
function memory_check() {
|
||||
echo ""
|
||||
echo "Memory usage on ${server_name}: "
|
||||
free -h
|
||||
echo ""
|
||||
}
|
||||
|
||||
function cpu_check() {
|
||||
echo ""
|
||||
echo "CPU load on ${server_name}: "
|
||||
echo ""
|
||||
uptime
|
||||
echo ""
|
||||
}
|
||||
|
||||
function tcp_check() {
|
||||
echo ""
|
||||
echo "TCP connections on ${server_name}: "
|
||||
echo ""
|
||||
cat /proc/net/tcp | wc -l
|
||||
echo ""
|
||||
}
|
||||
|
||||
function kernel_check() {
|
||||
echo ""
|
||||
echo "Kernel version on ${server_name}: "
|
||||
echo ""
|
||||
uname -r
|
||||
echo ""
|
||||
}
|
||||
|
||||
function all_checks() {
|
||||
memory_check
|
||||
cpu_check
|
||||
tcp_check
|
||||
kernel_check
|
||||
}
|
||||
|
||||
all_checks
|
||||
```
|
||||
|
||||
Save `status.sh`, then make it executable and run:
|
||||
|
||||
```bash
|
||||
chmod +x status.sh
|
||||
./status.sh
|
||||
```
|
||||
|
||||
### Conclusion
|
||||
|
||||
Bash scripting combines Linux commands to automate routine tasks, freeing you for more impactful work. This basic script demonstrates the power of automation.
|
||||
|
||||
> {notice} This content was inspired by a piece by softwareshinobi on Dev Team Six.
|
||||
@@ -0,0 +1,265 @@
|
||||
# Interactive Menu
|
||||
|
||||
Build interactive Bash menus. This guide shows you how to create a menu where users choose which actions to run, leveraging previously defined functions for server status checks:
|
||||
|
||||
* Memory usage
|
||||
* CPU load
|
||||
* TCP connections
|
||||
* Kernel version
|
||||
|
||||
Here's the base script containing these functions:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
##
|
||||
# Server status script:
|
||||
# - Memory usage
|
||||
# - CPU load
|
||||
# - Number of TCP connections
|
||||
# - Kernel version
|
||||
##
|
||||
|
||||
server_name=$(hostname)
|
||||
|
||||
function memory_check() {
|
||||
echo ""
|
||||
echo "Memory usage on ${server_name}: "
|
||||
free -h
|
||||
echo ""
|
||||
}
|
||||
|
||||
function cpu_check() {
|
||||
echo ""
|
||||
echo "CPU load on ${server_name}: "
|
||||
echo ""
|
||||
uptime
|
||||
echo ""
|
||||
}
|
||||
|
||||
function tcp_check() {
|
||||
echo ""
|
||||
echo "TCP connections on ${server_name}: "
|
||||
echo ""
|
||||
cat /proc/net/tcp | wc -l
|
||||
echo ""
|
||||
}
|
||||
|
||||
function kernel_check() {
|
||||
echo ""
|
||||
echo "Kernel version on ${server_name}: "
|
||||
echo ""
|
||||
uname -r
|
||||
echo ""
|
||||
}
|
||||
|
||||
function all_checks() {
|
||||
memory_check
|
||||
cpu_check
|
||||
tcp_check
|
||||
kernel_check
|
||||
}
|
||||
```
|
||||
|
||||
We'll now integrate this with a menu, allowing users to select a function to execute.
|
||||
|
||||
---
|
||||
|
||||
### Add Color for Readability
|
||||
|
||||
Enhance your menu's readability with simple color functions. Add these variables and functions to your script:
|
||||
|
||||
```bash
|
||||
##
|
||||
# Color Variables
|
||||
##
|
||||
green='\e[32m'
|
||||
blue='\e[34m'
|
||||
red='\e[31m'
|
||||
clear='\e[0m'
|
||||
|
||||
##
|
||||
# Color Functions
|
||||
##
|
||||
|
||||
ColorGreen(){
|
||||
echo -ne $green$1$clear
|
||||
}
|
||||
ColorBlue(){
|
||||
echo -ne $blue$1$clear
|
||||
}
|
||||
ColorRed(){
|
||||
echo -ne $red$1$clear
|
||||
}
|
||||
```
|
||||
|
||||
Use them like: `$(ColorBlue 'Your text')`.
|
||||
|
||||
---
|
||||
|
||||
### Build the Interactive Menu
|
||||
|
||||
Create a `menu` function containing the display logic, user input, and a `case` statement for selection.
|
||||
|
||||
```bash
|
||||
menu(){
|
||||
echo -ne "
|
||||
My Server Status Menu
|
||||
$(ColorGreen '1)') Memory usage
|
||||
$(ColorGreen '2)') CPU load
|
||||
$(ColorGreen '3)') TCP connections
|
||||
$(ColorGreen '4)') Kernel version
|
||||
$(ColorGreen '5)') Check All
|
||||
$(ColorGreen '0)') Exit
|
||||
$(ColorBlue 'Choose an option:') "
|
||||
read -r a
|
||||
case $a in
|
||||
1) memory_check ; menu ;;
|
||||
2) cpu_check ; menu ;;
|
||||
3) tcp_check ; menu ;;
|
||||
4) kernel_check ; menu ;;
|
||||
5) all_checks ; menu ;;
|
||||
0) exit 0 ;;
|
||||
*) echo -e $(ColorRed 'Invalid option.') ; menu ;;
|
||||
esac
|
||||
}
|
||||
```
|
||||
|
||||
Here's how it works:
|
||||
* The `echo -ne` block prints the menu options, applying colors.
|
||||
* `read -r a` captures user input into variable `a`.
|
||||
* The `case` statement executes the corresponding function. After each function, `menu` is called again to display the menu for another choice, creating a loop. `exit 0` handles the exit option.
|
||||
|
||||
Finally, call the `menu` function at the end of your script to start the interaction:
|
||||
|
||||
```bash
|
||||
menu
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Complete Script and Testing
|
||||
|
||||
Here's the entire script, `menu.sh`, combining all components:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
##
|
||||
# BASH menu script that checks:
|
||||
# - Memory usage
|
||||
# - CPU load
|
||||
# - Number of TCP connections
|
||||
# - Kernel version
|
||||
##
|
||||
|
||||
server_name=$(hostname)
|
||||
|
||||
function memory_check() {
|
||||
echo ""
|
||||
echo "Memory usage on ${server_name}: "
|
||||
free -h
|
||||
echo ""
|
||||
}
|
||||
|
||||
function cpu_check() {
|
||||
echo ""
|
||||
echo "CPU load on ${server_name}: "
|
||||
echo ""
|
||||
uptime
|
||||
echo ""
|
||||
}
|
||||
|
||||
function tcp_check() {
|
||||
echo ""
|
||||
echo "TCP connections on ${server_name}: "
|
||||
echo ""
|
||||
cat /proc/net/tcp | wc -l
|
||||
echo ""
|
||||
}
|
||||
|
||||
function kernel_check() {
|
||||
echo ""
|
||||
echo "Kernel version on ${server_name}: "
|
||||
echo ""
|
||||
uname -r
|
||||
echo ""
|
||||
}
|
||||
|
||||
function all_checks() {
|
||||
memory_check
|
||||
cpu_check
|
||||
tcp_check
|
||||
kernel_check
|
||||
}
|
||||
|
||||
##
|
||||
# Color Variables
|
||||
##
|
||||
green='\e[32m'
|
||||
blue='\e[34m'
|
||||
red='\e[31m'
|
||||
clear='\e[0m'
|
||||
|
||||
##
|
||||
# Color Functions
|
||||
##
|
||||
|
||||
ColorGreen(){
|
||||
echo -ne $green$1$clear
|
||||
}
|
||||
ColorBlue(){
|
||||
echo -ne $blue$1$clear
|
||||
}
|
||||
ColorRed(){
|
||||
echo -ne $red$1$clear
|
||||
}
|
||||
|
||||
menu(){
|
||||
echo -ne "
|
||||
My Server Status Menu
|
||||
$(ColorGreen '1)') Memory usage
|
||||
$(ColorGreen '2)') CPU load
|
||||
$(ColorGreen '3)') TCP connections
|
||||
$(ColorGreen '4)') Kernel version
|
||||
$(ColorGreen '5)') Check All
|
||||
$(ColorGreen '0)') Exit
|
||||
$(ColorBlue 'Choose an option:') "
|
||||
read -r a
|
||||
case $a in
|
||||
1) memory_check ; menu ;;
|
||||
2) cpu_check ; menu ;;
|
||||
3) tcp_check ; menu ;;
|
||||
4) kernel_check ; menu ;;
|
||||
5) all_checks ; menu ;;
|
||||
0) exit 0 ;;
|
||||
*) echo -e $(ColorRed 'Invalid option.') ; menu ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Call the menu function
|
||||
menu
|
||||
```
|
||||
|
||||
Save this code as `menu.sh`:
|
||||
|
||||
```bash
|
||||
touch menu.sh
|
||||
```
|
||||
|
||||
Open `menu.sh` and paste the script. Save and close. Then, make it executable and run:
|
||||
|
||||
```bash
|
||||
chmod +x menu.sh
|
||||
./menu.sh
|
||||
```
|
||||
|
||||
You'll see the colored menu, prompting for input. Select an option (e.g., `1` for memory check), and the corresponding information will display before the menu reappears, ready for another choice.
|
||||
|
||||
---
|
||||
|
||||
### Conclusion
|
||||
|
||||
You've built an interactive Bash menu, allowing users to effortlessly navigate script functionalities. This enhances user experience for your automation tools.
|
||||
|
||||
> {notice} This content was inspired by a piece by softwareshinobi on Dev Team Six.
|
||||
@@ -0,0 +1,113 @@
|
||||
# Running On Multiple Servers
|
||||
|
||||
Automate script execution across multiple remote servers. Instead of manual copying and logging in, learn to run Bash scripts on many machines with a single command.
|
||||
|
||||
### Prerequisites
|
||||
|
||||
You'll need a few remote Linux servers with **SSH access**. Gather their **IP addresses** or **hostnames** and list them in a file named `servers.txt`, one per line.
|
||||
|
||||
Create `servers.txt`:
|
||||
|
||||
```bash
|
||||
touch servers.txt
|
||||
```
|
||||
|
||||
Open `servers.txt` and add your server details:
|
||||
|
||||
```
|
||||
your_server_ip_1
|
||||
your_server_ip_2
|
||||
your_server_ip_3
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### The Script for Remote Execution
|
||||
|
||||
We'll use a simple Bash script that performs basic server checks: memory, CPU, TCP connections, and kernel version. Create a file named `remote_check.sh` and add the following content:
|
||||
|
||||
```bash
|
||||
touch remote_check.sh
|
||||
```
|
||||
|
||||
Open `remote_check.sh` and add:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
##
|
||||
# Server status script:
|
||||
# - Memory usage
|
||||
# - CPU load
|
||||
# - Number of TCP connections
|
||||
# - Kernel version
|
||||
##
|
||||
|
||||
server_name=$(hostname)
|
||||
|
||||
function memory_check() {
|
||||
echo "#######"
|
||||
echo "The current memory usage on ${server_name} is: "
|
||||
free -h
|
||||
echo "#######"
|
||||
}
|
||||
|
||||
function cpu_check() {
|
||||
echo "#######"
|
||||
echo "The current CPU load on ${server_name} is: "
|
||||
echo ""
|
||||
uptime
|
||||
echo "#######"
|
||||
}
|
||||
|
||||
function tcp_check() {
|
||||
echo "#######"
|
||||
echo "Total TCP connections on ${server_name}: "
|
||||
echo ""
|
||||
cat /proc/net/tcp | wc -l
|
||||
echo "#######"
|
||||
}
|
||||
|
||||
function kernel_check() {
|
||||
echo "#######"
|
||||
echo "The exact Kernel version on ${server_name} is: "
|
||||
echo ""
|
||||
uname -r
|
||||
echo "#######"
|
||||
}
|
||||
|
||||
function all_checks() {
|
||||
memory_check
|
||||
cpu_check
|
||||
tcp_check
|
||||
kernel_check
|
||||
}
|
||||
|
||||
all_checks
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Execute on Remote Servers
|
||||
|
||||
With `remote_check.sh` and `servers.txt` ready, run the following single command. This loop iterates through each server, using **SSH** to execute the script without local file transfer or manual logins.
|
||||
|
||||
```bash
|
||||
for server in $(cat servers.txt); do ssh your_user@"${server}" 'bash -s' < ./remote_check.sh; done
|
||||
```
|
||||
|
||||
**Breakdown:**
|
||||
* `for server in $(cat servers.txt)`: Reads each IP/hostname from `servers.txt` into the `server` variable.
|
||||
* `ssh your_user@"${server}"`: Connects to the remote server via SSH as `your_user`.
|
||||
* `'bash -s'`: Executes a Bash shell on the remote server, reading commands from standard input.
|
||||
* `< ./remote_check.sh`: Redirects the local `remote_check.sh` script's content to the remote Bash shell's standard input.
|
||||
|
||||
Each server will then execute the script, printing its status checks directly to your local terminal.
|
||||
|
||||
---
|
||||
|
||||
### Conclusion
|
||||
|
||||
This method efficiently executes Bash scripts across multiple remote servers. It avoids manual file transfers and individual logins, proving scalable for more complex scripts and larger environments. For extensive, state-managed automation, dedicated tools are often recommended.
|
||||
|
||||
> {notice} This content was inspired by a piece by softwareshinobi on Dev Team Six.
|
||||
@@ -0,0 +1,134 @@
|
||||
# Json Data
|
||||
|
||||
`jq` is your lightweight, flexible command-line JSON processor. It's built in portable C with zero runtime dependencies, making it simple to install and powerful for parsing JSON in Bash.
|
||||
|
||||
-----
|
||||
|
||||
### Demo Setup: QuizAPI
|
||||
|
||||
This demo uses the [QuizAPI](https://quizapi.io/) to fetch JSON data. Obtain a free **API key** from their [client area](https://quizapi.io/clientarea/settings/token) to follow along.
|
||||
|
||||
-----
|
||||
|
||||
### Installing `jq`
|
||||
|
||||
`jq` is easily installed via your system's package manager or direct download.
|
||||
|
||||
* **Ubuntu/Debian:** `sudo apt-get install jq`
|
||||
* **Red Hat/Fedora:** `sudo dnf install jq`
|
||||
* **Arch Linux:** `sudo pacman -S jq`
|
||||
|
||||
For other systems, refer to the [official `jq` download page](https://www.google.com/search?q=%5Bhttps://stedolan.github.io/jq/download/%5D\(https://stedolan.github.io/jq/download/\)). Verify your installation:
|
||||
|
||||
```bash
|
||||
jq --version
|
||||
```
|
||||
|
||||
-----
|
||||
|
||||
### Basic JSON Parsing with `jq`
|
||||
|
||||
Once `jq` is installed and you have your QuizAPI key, you can start processing JSON.
|
||||
|
||||
First, set your API key:
|
||||
|
||||
```bash
|
||||
API_KEY=YOUR_API_KEY_HERE # Replace with your actual key
|
||||
```
|
||||
|
||||
Fetch questions using `curl`:
|
||||
|
||||
```bash
|
||||
curl "https://quizapi.io/api/v1/questions?apiKey=${API_KEY}&limit=10"
|
||||
```
|
||||
|
||||
The raw output is hard to read. Pipe it to `jq` for beautifully formatted and colored JSON:
|
||||
|
||||
```bash
|
||||
curl "https://quizapi.io/api/v1/questions?apiKey=${API_KEY}&limit=10" | jq
|
||||
```
|
||||
|
||||
This command makes the JSON output structured and easy to inspect.
|
||||
|
||||
-----
|
||||
|
||||
### Extracting Specific Elements
|
||||
|
||||
To get only the first element from a JSON array, use `.[0]`:
|
||||
|
||||
```bash
|
||||
curl "https://quizapi.io/api/v1/questions?apiKey=${API_KEY}&limit=10" | jq '.[0]'
|
||||
```
|
||||
|
||||
This will output only the first JSON object in the array.
|
||||
|
||||
-----
|
||||
|
||||
### Fetching Key Values Across an Array
|
||||
|
||||
To extract the value of a specific key (e.g., `question`) from every object in a JSON array, use `.[].key`:
|
||||
|
||||
```bash
|
||||
curl "https://quizapi.io/api/v1/questions?apiKey=${API_KEY}&limit=10" | jq '.[].question'
|
||||
```
|
||||
|
||||
This will return a list of all questions from the API response.
|
||||
|
||||
-----
|
||||
|
||||
### Integrating `jq` into a Bash Script
|
||||
|
||||
Let's create a script to fetch a question and its answers, then display them. We'll use `jq` to parse specific fields and assign them to Bash variables.
|
||||
|
||||
Create `quiz_script.sh`:
|
||||
|
||||
```bash
|
||||
touch quiz_script.sh
|
||||
```
|
||||
|
||||
Open `quiz_script.sh` and add (remember to replace `YOUR_API_KEY_HERE`):
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Your QuizAPI Key (replace YOUR_API_KEY_HERE with your actual key)
|
||||
API_KEY="YOUR_API_KEY_HERE"
|
||||
|
||||
# Make an API call and get the first question object
|
||||
# Using -s for silent mode to suppress curl's progress meter
|
||||
QUIZ_DATA=$(curl -s "https://quizapi.io/api/v1/questions?apiKey=${API_KEY}&limit=1" 2>/dev/null)
|
||||
|
||||
# Extract specific values using jq with raw output (-r) for Bash variables
|
||||
question=$(echo "${QUIZ_DATA}" | jq -r '.[0].question')
|
||||
answer_a=$(echo "${QUIZ_DATA}" | jq -r '.[0].answers.answer_a')
|
||||
answer_b=$(echo "${QUIZ_DATA}" | jq -r '.[0].answers.answer_b')
|
||||
answer_c=$(echo "${QUIZ_DATA}" | jq -r '.[0].answers.answer_c')
|
||||
answer_d=$(echo "${QUIZ_DATA}" | jq -r '.[0].answers.answer_d')
|
||||
|
||||
# Output the question and answers
|
||||
echo "
|
||||
Question: ${question}
|
||||
|
||||
A) ${answer_a}
|
||||
B) ${answer_b}
|
||||
C) ${answer_c}
|
||||
D) ${answer_d}
|
||||
"
|
||||
```
|
||||
|
||||
Save, make executable, and run:
|
||||
|
||||
```bash
|
||||
chmod +x quiz_script.sh
|
||||
./quiz_script.sh
|
||||
```
|
||||
|
||||
The script will print a random question and its corresponding answers. For more advanced, interactive Bash quizzes, explore community projects that build upon these `jq` principles.
|
||||
|
||||
-----
|
||||
|
||||
### Conclusion
|
||||
|
||||
`jq` empowers you to process **JSON** directly within your Bash terminal, facilitating seamless interaction with **REST APIs**. For deeper dives, consult the [official `jq` manual](https://www.google.com/search?q=%5Bhttps://stedolan.github.io/jq/manual/%5D\(https://stedolan.github.io/jq/manual/\)) and the [QuizAPI documentation](https://quizapi.io/docs/1.0/overview).
|
||||
|
||||
> {notice} This content was inspired by a piece by softwareshinobi on Dev Team Six.
|
||||
217
landing/docs/Bash-Scripts/023-bash-redirection.md
Normal file
217
landing/docs/Bash-Scripts/023-bash-redirection.md
Normal file
@@ -0,0 +1,217 @@
|
||||
# Redirection
|
||||
|
||||
Master Bash redirection and pipes. These essential Linux features are critical for efficient system administration. Every command handles input, output, and errors through **File Descriptors (FDs)**:
|
||||
|
||||
* **STDIN** (0): Standard Input – receives data.
|
||||
* **STDOUT** (1): Standard Output – sends regular data.
|
||||
* **STDERR** (2): Standard Error – sends error messages.
|
||||
|
||||
---
|
||||
|
||||
### Pipes vs. Redirection
|
||||
|
||||
Both manage data streams, but with a key difference:
|
||||
* **Redirection** routes a command's input/output to or from a **file**.
|
||||
* **Pipes** (`|`) connect the **output of one command directly to the input of another command**.
|
||||
|
||||
---
|
||||
|
||||
### STDIN (Standard Input)
|
||||
|
||||
Commands often expect input. By default, this is your keyboard, but you can redirect it from other sources.
|
||||
|
||||
**Redirecting from a file (`<`)**:
|
||||
Use `<` to feed a file's content as input to a command. Create `input.txt`:
|
||||
|
||||
```bash
|
||||
touch input.txt
|
||||
```
|
||||
Open `input.txt` and add:
|
||||
```
|
||||
Line 1
|
||||
Line 2
|
||||
```
|
||||
Save `input.txt`.
|
||||
Then run:
|
||||
|
||||
```bash
|
||||
cat < input.txt
|
||||
```
|
||||
This prints `input.txt` content, similar to `cat input.txt`.
|
||||
|
||||
**Here-Documents (`<< DELIMITER`)**:
|
||||
For multi-line input directly in your script or terminal, use a here-document with a custom delimiter (e.g., `EOF`).
|
||||
|
||||
```bash
|
||||
cat << EOF
|
||||
Hello World!
|
||||
How are you?
|
||||
EOF
|
||||
```
|
||||
This will print:
|
||||
```
|
||||
Hello World!
|
||||
How are you?
|
||||
```
|
||||
Similarly, with `wc -l` to count lines:
|
||||
```bash
|
||||
wc -l << EOF
|
||||
Hello World!
|
||||
How are you?
|
||||
EOF
|
||||
```
|
||||
Output:
|
||||
```
|
||||
2
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### STDOUT (Standard Output)
|
||||
|
||||
Regular command output typically goes to your terminal. Redirect it to a file.
|
||||
|
||||
**Overwrite (`>`)**:
|
||||
Use `>` to send output to a file. If the file exists, its content is overwritten. Create `file.txt` (or ensure it's empty):
|
||||
|
||||
```bash
|
||||
echo "Hello World!" > file.txt
|
||||
cat file.txt # Output: Hello World!
|
||||
```
|
||||
Running again overwrites:
|
||||
|
||||
```bash
|
||||
echo "How are you?" > file.txt
|
||||
cat file.txt # Output: How are you? (Previous content is gone)
|
||||
```
|
||||
|
||||
**Append (`>>`)**:
|
||||
Use `>>` to add output to the end of a file without overwriting existing content.
|
||||
|
||||
```bash
|
||||
echo "Hello World!" > file.txt # Start fresh
|
||||
echo "How are you?" >> file.txt
|
||||
cat file.txt
|
||||
```
|
||||
Output:
|
||||
```
|
||||
Hello World!
|
||||
How are you?
|
||||
```
|
||||
|
||||
You can also explicitly specify the STDOUT file descriptor (1): `echo "Hello" 1> file.txt`.
|
||||
|
||||
---
|
||||
|
||||
### STDERR (Standard Error)
|
||||
|
||||
Error messages, distinct from standard output, are sent to **STDERR**. Redirect them using file descriptor 2.
|
||||
|
||||
**Redirecting Errors (`2>`)**:
|
||||
Use `2>` to redirect error messages. For example, `ls --invalid-flag` generates an error.
|
||||
|
||||
```bash
|
||||
ls --invalid-flag 2> error.txt
|
||||
cat error.txt # Contains the error message
|
||||
```
|
||||
Use `2>>` to append error messages to a file.
|
||||
|
||||
**Discarding Errors (`2> /dev/null`)**:
|
||||
Send error output to `/dev/null` to completely suppress it. `/dev/null` is a special 'black hole' device that discards all data written to it.
|
||||
|
||||
```bash
|
||||
ls --invalid-flag 2> /dev/null # Error message is hidden
|
||||
```
|
||||
|
||||
**Redirecting Both STDOUT and STDERR**:
|
||||
You can manage both streams simultaneously.
|
||||
|
||||
To separate regular output and errors into different files:
|
||||
|
||||
```bash
|
||||
# Assuming 'install_package.sh' generates both output and errors
|
||||
./install_package.sh > output.txt 2> error.txt
|
||||
```
|
||||
|
||||
To send both to the same file (concise syntax):
|
||||
|
||||
```bash
|
||||
./install_package.sh > combined_output.txt 2>&1
|
||||
```
|
||||
The `2>&1` redirects file descriptor 2 (STDERR) to the same location as file descriptor 1 (STDOUT), which is `combined_output.txt`. Alternatively, an even shorter Bash 4+ syntax: `&> combined_output.txt`.
|
||||
|
||||
---
|
||||
|
||||
### Piping (`|`)
|
||||
|
||||
Pipes connect the standard output of one command directly to the standard input of another, creating powerful command chains.
|
||||
|
||||
**Basic Example:** Find `.txt` files in a directory listing.
|
||||
|
||||
```bash
|
||||
ls | grep ".txt"
|
||||
```
|
||||
This sends `ls`'s output to `grep` for filtering.
|
||||
|
||||
**Chaining Commands:** Analyze file ownership in a directory.
|
||||
|
||||
```bash
|
||||
ls -l /projects/bash_scripts | tail -n +2 | sed 's/\s\s*/ /g' | cut -d ' ' -f 3 | sort | uniq -c
|
||||
```
|
||||
This sequence lists files, removes the header, cleans spacing, extracts owner names, sorts them, and counts unique occurrences.
|
||||
|
||||
---
|
||||
|
||||
### Here-Documents (`<< DELIMITER`)
|
||||
|
||||
Here-documents (`<<`) provide multi-line input directly within your script or terminal, ideal for commands that read from STDIN without needing a separate temporary file.
|
||||
|
||||
Specify a custom delimiter (e.g., `EOF`):
|
||||
|
||||
```bash
|
||||
cat << END_MESSAGE
|
||||
This text will be passed as input to cat.
|
||||
It spans multiple lines.
|
||||
END_MESSAGE
|
||||
```
|
||||
Output:
|
||||
```
|
||||
This text will be passed as input to cat.
|
||||
It spans multiple lines.
|
||||
```
|
||||
You can also pipe the output of a here-document to another command:
|
||||
|
||||
```bash
|
||||
wc -l << MESSAGE_LINES
|
||||
Line one.
|
||||
Line two.
|
||||
Line three.
|
||||
MESSAGE_LINES
|
||||
```
|
||||
Output: `3` (counts the lines). Variables are expanded within here-documents.
|
||||
|
||||
---
|
||||
|
||||
### Here-Strings (`<<<`)
|
||||
|
||||
For piping a single string into a command's STDIN, use a here-string (`<<<`). This is cleaner than a here-document for single lines.
|
||||
|
||||
```bash
|
||||
wc -w <<<"This is a sample string for word count."
|
||||
```
|
||||
Output: `7` (counts words).
|
||||
Variables are also supported in here-strings.
|
||||
|
||||
---
|
||||
|
||||
### Summary of Redirection and Piping Operators
|
||||
|
||||
| **Operator** | **Description** |
|
||||
| :--- | :--- |
|
||||
| `>` | Redirect STDOUT to a file, overwriting existing content. |
|
||||
| `>>` | Redirect STDOUT to a file, appending to existing content. |
|
||||
| `<` | Redirect STDIN from a file. |
|
||||
| `2>` | Redirect STDERR to a file, overwriting existing content. |
|
||||
| `|` | Pipe STDOUT of one command to STDIN of another. |
|
||||
| `<<` | Here-document: Provide multi-line STDIN from the script. |
|
||||
| `<<<` | Here-string: Provide single-line STDIN from the command line. |
|
||||
Reference in New Issue
Block a user