automated terminal push
All checks were successful
learn org at code.softwareshinobi.com/git.softwareshinobi.com/pipeline/head This commit looks good
All checks were successful
learn org at code.softwareshinobi.com/git.softwareshinobi.com/pipeline/head This commit looks good
This commit is contained in:
BIN
.recycle/introduction-to-git-and-github-ebook-main.zip
Normal file
BIN
.recycle/introduction-to-git-and-github-ebook-main.zip
Normal file
Binary file not shown.
@@ -2,8 +2,6 @@ FROM titom73/mkdocs AS MKDOCS_BUILD
|
||||
|
||||
RUN pip install markupsafe==2.0.1
|
||||
|
||||
RUN pip install mkdocs-blog-plugin
|
||||
|
||||
WORKDIR /docs
|
||||
|
||||
COPY . .
|
||||
|
||||
@@ -16,7 +16,7 @@ services:
|
||||
|
||||
ports:
|
||||
|
||||
- 8000:8000
|
||||
- 8000:80
|
||||
|
||||
volumes:
|
||||
|
||||
|
||||
@@ -1,91 +0,0 @@
|
||||
# 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.
|
||||
@@ -1,11 +0,0 @@
|
||||
# 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.
|
||||
@@ -1,32 +0,0 @@
|
||||
# Bash Structure
|
||||
|
||||
Let's start by creating a new file with a `.sh` extension. As an example, we could create a file called `devdojo.sh`.
|
||||
|
||||
To create that file, you can use the `touch` command:
|
||||
|
||||
```bash
|
||||
touch devdojo.sh
|
||||
```
|
||||
|
||||
Or you can use your text editor instead:
|
||||
|
||||
```bash
|
||||
nano devdojo.sh
|
||||
```
|
||||
|
||||
In order to execute/run a bash script file with the bash shell interpreter, the first line of a script file must indicate the absolute path to the bash executable:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
```
|
||||
|
||||
This is also called a [Shebang](https://en.wikipedia.org/wiki/Shebang_(Unix)).
|
||||
|
||||
All that the shebang does is to instruct the operating system to run the script with the `/bin/bash` executable.
|
||||
|
||||
However, bash is not always in `/bin/bash` directory, particularly on non-Linux systems or due to installation as an optional package. Thus, you may want to use:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
```
|
||||
It searches for bash executable in directories, listed in PATH environmental variable.
|
||||
@@ -1,41 +0,0 @@
|
||||
# Bash Hello World
|
||||
|
||||
Once we have our `devdojo.sh` file created and we've specified the bash shebang on the very first line, we are ready to create our first `Hello World` bash script.
|
||||
|
||||
To do that, open the `devdojo.sh` file again and add the following after the `#!/bin/bash` line:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
echo "Hello World!"
|
||||
```
|
||||
|
||||
Save the file and exit.
|
||||
|
||||
After that make the script executable by running:
|
||||
|
||||
```bash
|
||||
chmod +x devdojo.sh
|
||||
```
|
||||
|
||||
After that execute the file:
|
||||
|
||||
```bash
|
||||
./devdojo.sh
|
||||
```
|
||||
|
||||
You will see a "Hello World" message on the screen.
|
||||
|
||||
Another way to run the script would be:
|
||||
|
||||
```bash
|
||||
bash devdojo.sh
|
||||
```
|
||||
|
||||
As bash can be used interactively, you could run the following command directly in your terminal and you would get the same result:
|
||||
|
||||
```bash
|
||||
echo "Hello DevDojo!"
|
||||
```
|
||||
|
||||
Putting a script together is useful once you have to combine multiple commands together.
|
||||
@@ -1,131 +0,0 @@
|
||||
# Bash Variables
|
||||
|
||||
As in any other programming language, you can use variables in Bash Scripting as well. However, there are no data types, and a variable in Bash can contain numbers as well as characters.
|
||||
|
||||
To assign a value to a variable, all you need to do is use the `=` sign:
|
||||
|
||||
```bash
|
||||
name="DevDojo"
|
||||
```
|
||||
|
||||
>{notice} as an important note, you can not have spaces before and after the `=` sign.
|
||||
|
||||
After that, to access the variable, you have to use the `$` and reference it as shown below:
|
||||
|
||||
```bash
|
||||
echo $name
|
||||
```
|
||||
|
||||
Wrapping the variable name between curly brackets is not required, but is considered a good practice, and I would advise you to use them whenever you can:
|
||||
|
||||
```bash
|
||||
echo ${name}
|
||||
```
|
||||
|
||||
The above code would output: `DevDojo` as this is the value of our `name` variable.
|
||||
|
||||
Next, let's update our `devdojo.sh` script and include a variable in it.
|
||||
|
||||
Again, you can open the file `devdojo.sh` with your favorite text editor, I'm using nano here to open the file:
|
||||
|
||||
```bash
|
||||
nano devdojo.sh
|
||||
```
|
||||
|
||||
Adding our `name` variable here in the file, with a welcome message. Our file now looks like this:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
name="DevDojo"
|
||||
|
||||
echo "Hi there $name"
|
||||
```
|
||||
|
||||
Save it and run the file using the command below:
|
||||
|
||||
```bash
|
||||
./devdojo.sh
|
||||
```
|
||||
|
||||
You would see the following output on your screen:
|
||||
|
||||
```bash
|
||||
Hi there DevDojo
|
||||
```
|
||||
|
||||
Here is a rundown of the script written in the file:
|
||||
|
||||
* `#!/bin/bash` - At first, we specified our shebang.
|
||||
* `name=DevDojo` - Then, we defined a variable called `name` and assigned a value to it.
|
||||
* `echo "Hi there $name"` - Finally, we output the content of the variable on the screen as a welcome message by using `echo`
|
||||
|
||||
You can also add multiple variables in the file as shown below:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
name="DevDojo"
|
||||
greeting="Hello"
|
||||
|
||||
echo "$greeting $name"
|
||||
```
|
||||
|
||||
Save the file and run it again:
|
||||
|
||||
```bash
|
||||
./devdojo.sh
|
||||
```
|
||||
|
||||
You would see the following output on your screen:
|
||||
|
||||
```bash
|
||||
Hello DevDojo
|
||||
```
|
||||
Note that you don't necessarily need to add semicolon `;` at the end of each line. It works both ways, a bit like other programming language such as JavaScript!
|
||||
|
||||
|
||||
You can also add variables in the Command Line outside the Bash script and they can be read as parameters:
|
||||
|
||||
```bash
|
||||
./devdojo.sh Bobby buddy!
|
||||
```
|
||||
This script takes in two parameters `Bobby`and `buddy!` separated by space. In the `devdojo.sh` file we have the following:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
echo "Hello there" $1
|
||||
|
||||
```
|
||||
`$1` is the first input (`Bobby`) in the Command Line. Similarly, there could be more inputs and they are all referenced to by the `$` sign and their respective order of input. This means that `buddy!` is referenced to using `$2`. Another useful method for reading variables is the `$@` which reads all inputs.
|
||||
|
||||
So now let's change the `devdojo.sh` file to better understand:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
echo "Hello there" $1
|
||||
|
||||
# $1 : first parameter
|
||||
|
||||
echo "Hello there" $2
|
||||
|
||||
# $2 : second parameter
|
||||
|
||||
echo "Hello there" $@
|
||||
|
||||
# $@ : all
|
||||
```
|
||||
The output for:
|
||||
|
||||
```bash
|
||||
./devdojo.sh Bobby buddy!
|
||||
```
|
||||
Would be the following:
|
||||
|
||||
```bash
|
||||
Hello there Bobby
|
||||
Hello there buddy!
|
||||
Hello there Bobby buddy!
|
||||
```
|
||||
@@ -1,54 +0,0 @@
|
||||
# Bash User Input
|
||||
|
||||
With the previous script, we defined a variable, and we output the value of the variable on the screen with the `echo $name`.
|
||||
|
||||
Now let's go ahead and ask the user for input instead. To do that again, open the file with your favorite text editor and update the script as follows:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
echo "What is your name?"
|
||||
read name
|
||||
|
||||
echo "Hi there $name"
|
||||
echo "Welcome to DevDojo!"
|
||||
```
|
||||
|
||||
The above will prompt the user for input and then store that input as a string/text in a variable.
|
||||
|
||||
We can then use the variable and print a message back to them.
|
||||
|
||||
The output of the above script would be:
|
||||
|
||||
* First run the script:
|
||||
|
||||
```bash
|
||||
./devdojo.sh
|
||||
```
|
||||
|
||||
* Then, you would be prompted to enter your name:
|
||||
|
||||
```
|
||||
What is your name?
|
||||
Bobby
|
||||
```
|
||||
|
||||
* Once you've typed your name, just hit enter, and you will get the following output:
|
||||
|
||||
```
|
||||
Hi there Bobby
|
||||
Welcome to DevDojo!
|
||||
```
|
||||
|
||||
To reduce the code, we could change the first `echo` statement with the `read -p`, the `read` command used with `-p` flag will print a message before prompting the user for their input:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
read -p "What is your name? " name
|
||||
|
||||
echo "Hi there $name"
|
||||
echo "Welcome to DevDojo!"
|
||||
```
|
||||
|
||||
Make sure to test this out yourself as well!
|
||||
@@ -1,27 +0,0 @@
|
||||
# Bash Comments
|
||||
|
||||
As with any other programming language, you can add comments to your script. Comments are used to leave yourself notes through your code.
|
||||
|
||||
To do that in Bash, you need to add the `#` symbol at the beginning of the line. Comments will never be rendered on the screen.
|
||||
|
||||
Here is an example of a comment:
|
||||
|
||||
```bash
|
||||
# This is a comment and will not be rendered on the screen
|
||||
```
|
||||
|
||||
Let's go ahead and add some comments to our script:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
# Ask the user for their name
|
||||
|
||||
read -p "What is your name? " name
|
||||
|
||||
# Greet the user
|
||||
echo "Hi there $name"
|
||||
echo "Welcome to DevDojo!"
|
||||
```
|
||||
|
||||
Comments are a great way to describe some of the more complex functionality directly in your scripts so that other people could find their way around your code with ease.
|
||||
@@ -1,81 +0,0 @@
|
||||
# Bash Arguments
|
||||
|
||||
You can pass arguments to your shell script when you execute it. To pass an argument, you just need to write it right after the name of your script. For example:
|
||||
|
||||
```bash
|
||||
./devdojo.com your_argument
|
||||
```
|
||||
|
||||
In the script, we can then use `$1` in order to reference the first argument that we specified.
|
||||
|
||||
If we pass a second argument, it would be available as `$2` and so on.
|
||||
|
||||
Let's create a short script called `arguments.sh` as an example:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
echo "Argument one is $1"
|
||||
echo "Argument two is $2"
|
||||
echo "Argument three is $3"
|
||||
```
|
||||
|
||||
Save the file and make it executable:
|
||||
|
||||
```bash
|
||||
chmod +x arguments.sh
|
||||
```
|
||||
|
||||
Then run the file and pass **3** arguments:
|
||||
|
||||
```bash
|
||||
./arguments.sh dog cat bird
|
||||
```
|
||||
|
||||
The output that you would get would be:
|
||||
|
||||
```bash
|
||||
Argument one is dog
|
||||
Argument two is cat
|
||||
Argument three is bird
|
||||
```
|
||||
|
||||
To reference all arguments, you can use `$@`:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
echo "All arguments: $@"
|
||||
```
|
||||
|
||||
If you run the script again:
|
||||
|
||||
```bash
|
||||
./arguments.sh dog cat bird
|
||||
```
|
||||
|
||||
You will get the following output:
|
||||
|
||||
```
|
||||
All arguments: dog cat bird
|
||||
```
|
||||
|
||||
Another thing that you need to keep in mind is that `$0` is used to reference the script itself.
|
||||
|
||||
This is an excellent way to create self destruct the file if you need to or just get the name of the script.
|
||||
|
||||
For example, let's create a script that prints out the name of the file and deletes the file after that:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
echo "The name of the file is: $0 and it is going to be self-deleted."
|
||||
|
||||
rm -f $0
|
||||
```
|
||||
|
||||
You need to be careful with the self deletion and ensure that you have your script backed up before you self-delete it.
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,112 +0,0 @@
|
||||
# Bash Arrays
|
||||
|
||||
If you have ever done any programming, you are probably already familiar with arrays.
|
||||
|
||||
But just in case you are not a developer, the main thing that you need to know is that unlike variables, arrays can hold several values under one name.
|
||||
|
||||
You can initialize an array by assigning values divided by space and enclosed in `()`. Example:
|
||||
|
||||
```bash
|
||||
my_array=("value 1" "value 2" "value 3" "value 4")
|
||||
```
|
||||
|
||||
To access the elements in the array, you need to reference them by their numeric index.
|
||||
|
||||
>{notice} keep in mind that you need to use curly brackets.
|
||||
|
||||
* Access a single element, this would output: `value 2`
|
||||
|
||||
```bash
|
||||
echo ${my_array[1]}
|
||||
```
|
||||
|
||||
* This would return the last element: `value 4`
|
||||
|
||||
```bash
|
||||
echo ${my_array[-1]}
|
||||
```
|
||||
|
||||
* As with command line arguments using `@` will return all arguments in the array, as follows: `value 1 value 2 value 3 value 4`
|
||||
|
||||
```bash
|
||||
echo ${my_array[@]}
|
||||
```
|
||||
|
||||
* Prepending the array with a hash sign (`#`) would output the total number of elements in the array, in our case it is `4`:
|
||||
|
||||
```bash
|
||||
echo ${#my_array[@]}
|
||||
```
|
||||
|
||||
Make sure to test this and practice it at your end with different values.
|
||||
|
||||
## Substring in Bash :: Slicing
|
||||
|
||||
Let's review the following example of slicing in a string in Bash:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
letters=( "A""B""C""D""E" )
|
||||
echo ${letters[@]}
|
||||
```
|
||||
|
||||
This command will print all the elements of an array.
|
||||
|
||||
Output:
|
||||
|
||||
```bash
|
||||
$ ABCDE
|
||||
```
|
||||
|
||||
|
||||
Let's see a few more examples:
|
||||
|
||||
- Example 1
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
letters=( "A""B""C""D""E" )
|
||||
b=${letters:0:2}
|
||||
echo "${b}"
|
||||
```
|
||||
|
||||
This command will print array from starting index 0 to 2 where 2 is exclusive.
|
||||
|
||||
```bash
|
||||
$ AB
|
||||
```
|
||||
|
||||
- Example 2
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
letters=( "A""B""C""D""E" )
|
||||
b=${letters::5}
|
||||
echo "${b}"
|
||||
```
|
||||
|
||||
This command will print from base index 0 to 5, where 5 is exclusive and starting index is default set to 0 .
|
||||
|
||||
```bash
|
||||
$ ABCDE
|
||||
```
|
||||
|
||||
- Example 3
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
letters=( "A""B""C""D""E" )
|
||||
b=${letters:3}
|
||||
echo "${b}"
|
||||
```
|
||||
|
||||
This command will print from starting index
|
||||
3 to end of array inclusive .
|
||||
|
||||
```bash
|
||||
$ DE
|
||||
```
|
||||
@@ -1,186 +0,0 @@
|
||||
# Bash Conditional Expressions
|
||||
|
||||
In computer science, conditional statements, conditional expressions, and conditional constructs are features of a programming language, which perform different computations or actions depending on whether a programmer-specified boolean condition evaluates to true or false.
|
||||
|
||||
In Bash, conditional expressions are used by the `[[` compound command and the `[`built-in commands to test file attributes and perform string and arithmetic comparisons.
|
||||
|
||||
Here is a list of the most popular Bash conditional expressions. You do not have to memorize them by heart. You can simply refer back to this list whenever you need it!
|
||||
|
||||
## File expressions
|
||||
|
||||
* True if file exists.
|
||||
|
||||
```bash
|
||||
[[ -a ${file} ]]
|
||||
```
|
||||
|
||||
* True if file exists and is a block special file.
|
||||
|
||||
```bash
|
||||
[[ -b ${file} ]]
|
||||
```
|
||||
|
||||
* True if file exists and is a character special file.
|
||||
|
||||
```bash
|
||||
[[ -c ${file} ]]
|
||||
```
|
||||
|
||||
* True if file exists and is a directory.
|
||||
|
||||
```bash
|
||||
[[ -d ${file} ]]
|
||||
```
|
||||
|
||||
* True if file exists.
|
||||
|
||||
```bash
|
||||
[[ -e ${file} ]]
|
||||
```
|
||||
|
||||
* True if file exists and is a regular file.
|
||||
|
||||
```bash
|
||||
[[ -f ${file} ]]
|
||||
```
|
||||
|
||||
* True if file exists and is a symbolic link.
|
||||
|
||||
```bash
|
||||
[[ -h ${file} ]]
|
||||
```
|
||||
|
||||
* True if file exists and is readable.
|
||||
|
||||
```bash
|
||||
[[ -r ${file} ]]
|
||||
```
|
||||
|
||||
* True if file exists and has a size greater than zero.
|
||||
|
||||
```bash
|
||||
[[ -s ${file} ]]
|
||||
```
|
||||
|
||||
* True if file exists and is writable.
|
||||
|
||||
```bash
|
||||
[[ -w ${file} ]]
|
||||
```
|
||||
|
||||
* True if file exists and is executable.
|
||||
|
||||
```bash
|
||||
[[ -x ${file} ]]
|
||||
```
|
||||
|
||||
* True if file exists and is a symbolic link.
|
||||
|
||||
```bash
|
||||
[[ -L ${file} ]]
|
||||
```
|
||||
|
||||
## String expressions
|
||||
|
||||
* True if the shell variable varname is set (has been assigned a value).
|
||||
|
||||
```bash
|
||||
[[ -v ${varname} ]]
|
||||
```
|
||||
|
||||
True if the length of the string is zero.
|
||||
|
||||
```bash
|
||||
[[ -z ${string} ]]
|
||||
```
|
||||
|
||||
True if the length of the string is non-zero.
|
||||
|
||||
```bash
|
||||
[[ -n ${string} ]]
|
||||
```
|
||||
|
||||
* True if the strings are equal. `=` should be used with the test command for POSIX conformance. When used with the `[[` command, this performs pattern matching as described above (Compound Commands).
|
||||
|
||||
```bash
|
||||
[[ ${string1} == ${string2} ]]
|
||||
```
|
||||
|
||||
* True if the strings are not equal.
|
||||
|
||||
```bash
|
||||
[[ ${string1} != ${string2} ]]
|
||||
```
|
||||
|
||||
* True if string1 sorts before string2 lexicographically.
|
||||
|
||||
```bash
|
||||
[[ ${string1} < ${string2} ]]
|
||||
```
|
||||
|
||||
* True if string1 sorts after string2 lexicographically.
|
||||
|
||||
```bash
|
||||
[[ ${string1} > ${string2} ]]
|
||||
```
|
||||
|
||||
## Arithmetic operators
|
||||
|
||||
* Returns true if the numbers are **equal**
|
||||
|
||||
```bash
|
||||
[[ ${arg1} -eq ${arg2} ]]
|
||||
```
|
||||
|
||||
* Returns true if the numbers are **not equal**
|
||||
|
||||
```bash
|
||||
[[ ${arg1} -ne ${arg2} ]]
|
||||
```
|
||||
|
||||
* Returns true if arg1 is **less than** arg2
|
||||
|
||||
```bash
|
||||
[[ ${arg1} -lt ${arg2} ]]
|
||||
```
|
||||
|
||||
* Returns true if arg1 is **less than or equal** arg2
|
||||
|
||||
```bash
|
||||
[[ ${arg1} -le ${arg2} ]]
|
||||
```
|
||||
|
||||
* Returns true if arg1 is **greater than** arg2
|
||||
|
||||
```bash
|
||||
[[ ${arg1} -gt ${arg2} ]]
|
||||
```
|
||||
|
||||
* Returns true if arg1 is **greater than or equal** arg2
|
||||
|
||||
```bash
|
||||
[[ ${arg1} -ge ${arg2} ]]
|
||||
```
|
||||
|
||||
As a side note, arg1 and arg2 may be positive or negative integers.
|
||||
|
||||
As with other programming languages you can use `AND` & `OR` conditions:
|
||||
|
||||
```bash
|
||||
[[ test_case_1 ]] && [[ test_case_2 ]] # And
|
||||
[[ test_case_1 ]] || [[ test_case_2 ]] # Or
|
||||
```
|
||||
|
||||
## Exit status operators
|
||||
|
||||
* returns true if the command was successful without any errors
|
||||
|
||||
```bash
|
||||
[[ $? -eq 0 ]]
|
||||
```
|
||||
|
||||
* returns true if the command was not successful or had errors
|
||||
|
||||
```bash
|
||||
[[ $? -gt 0 ]]
|
||||
```
|
||||
@@ -1,187 +0,0 @@
|
||||
# Bash Conditionals
|
||||
|
||||
In the last section, we covered some of the most popular conditional expressions. We can now use them with standard conditional statements like `if`, `if-else` and `switch case` statements.
|
||||
|
||||
## If statement
|
||||
|
||||
The format of an `if` statement in Bash is as follows:
|
||||
|
||||
```bash
|
||||
if [[ some_test ]]
|
||||
then
|
||||
<commands>
|
||||
fi
|
||||
```
|
||||
|
||||
Here is a quick example which would ask you to enter your name in case that you've left it empty:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
# Bash if statement example
|
||||
|
||||
read -p "What is your name? " name
|
||||
|
||||
if [[ -z ${name} ]]
|
||||
then
|
||||
echo "Please enter your name!"
|
||||
fi
|
||||
```
|
||||
|
||||
## If Else statement
|
||||
|
||||
With an `if-else` statement, you can specify an action in case that the condition in the `if` statement does not match. We can combine this with the conditional expressions from the previous section as follows:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
# Bash if statement example
|
||||
|
||||
read -p "What is your name? " name
|
||||
|
||||
if [[ -z ${name} ]]
|
||||
then
|
||||
echo "Please enter your name!"
|
||||
else
|
||||
echo "Hi there ${name}"
|
||||
fi
|
||||
```
|
||||
|
||||
You can use the above if statement with all of the conditional expressions from the previous chapters:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
admin="devdojo"
|
||||
|
||||
read -p "Enter your username? " username
|
||||
|
||||
# Check if the username provided is the admin
|
||||
|
||||
if [[ "${username}" == "${admin}" ]] ; then
|
||||
echo "You are the admin user!"
|
||||
else
|
||||
echo "You are NOT the admin user!"
|
||||
fi
|
||||
```
|
||||
|
||||
Here is another example of an `if` statement which would check your current `User ID` and would not allow you to run the script as the `root` user:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
if (( $EUID == 0 )); then
|
||||
echo "Please do not run as root"
|
||||
exit
|
||||
fi
|
||||
```
|
||||
|
||||
If you put this on top of your script it would exit in case that the EUID is 0 and would not execute the rest of the script. This was discussed on [the DigitalOcean community forum](https://www.digitalocean.com/community/questions/how-to-check-if-running-as-root-in-a-bash-script).
|
||||
|
||||
You can also test multiple conditions with an `if` statement. In this example we want to make sure that the user is neither the admin user nor the root user to ensure the script is incapable of causing too much damage. We'll use the `or` operator in this example, noted by `||`. This means that either of the conditions needs to be true. If we used the `and` operator of `&&` then both conditions would need to be true.
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
admin="devdojo"
|
||||
|
||||
read -p "Enter your username? " username
|
||||
|
||||
# Check if the username provided is the admin
|
||||
|
||||
if [[ "${username}" != "${admin}" ]] || [[ $EUID != 0 ]] ; then
|
||||
echo "You are not the admin or root user, but please be safe!"
|
||||
else
|
||||
echo "You are the admin user! This could be very destructive!"
|
||||
fi
|
||||
```
|
||||
|
||||
If you have multiple conditions and scenarios, then can use `elif` statement with `if` and `else` statements.
|
||||
|
||||
```bash
|
||||
#!/bin/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
|
||||
```
|
||||
|
||||
## Switch case statements
|
||||
|
||||
As in other programming languages, you can use a `case` statement to simplify complex conditionals when there are multiple different choices. So rather than using a few `if`, and `if-else` statements, you could use a single `case` statement.
|
||||
|
||||
The Bash `case` statement syntax looks like this:
|
||||
|
||||
```bash
|
||||
case $some_variable in
|
||||
|
||||
pattern_1)
|
||||
commands
|
||||
;;
|
||||
|
||||
pattern_2| pattern_3)
|
||||
commands
|
||||
;;
|
||||
|
||||
*)
|
||||
default commands
|
||||
;;
|
||||
esac
|
||||
```
|
||||
|
||||
A quick rundown of the structure:
|
||||
|
||||
* All `case` statements start with the `case` keyword.
|
||||
* On the same line as the `case` keyword, you need to specify a variable or an expression followed by the `in` keyword.
|
||||
* After that, you have your `case` patterns, where you need to use `)` to identify the end of the pattern.
|
||||
* You can specify multiple patterns divided by a pipe: `|`.
|
||||
* After the pattern, you specify the commands that you would like to be executed in case that the pattern matches the variable or the expression that you've specified.
|
||||
* All clauses have to be terminated by adding `;;` at the end.
|
||||
* You can have a default statement by adding a `*` as the pattern.
|
||||
* To close the `case` statement, use the `esac` (case typed backwards) keyword.
|
||||
|
||||
Here is an example of a Bash `case` statement:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
read -p "Enter the name of your car brand: " car
|
||||
|
||||
case $car in
|
||||
|
||||
Tesla)
|
||||
echo -n "${car}'s car factory is in the USA."
|
||||
;;
|
||||
|
||||
BMW | Mercedes | Audi | Porsche)
|
||||
echo -n "${car}'s car factory is in Germany."
|
||||
;;
|
||||
|
||||
Toyota | Mazda | Mitsubishi | Subaru)
|
||||
echo -n "${car}'s car factory is in Japan."
|
||||
;;
|
||||
|
||||
*)
|
||||
echo -n "${car} is an unknown car brand"
|
||||
;;
|
||||
|
||||
esac
|
||||
```
|
||||
|
||||
With this script, we are asking the user to input a name of a car brand like Telsa, BMW, Mercedes and etc.
|
||||
|
||||
Then with a `case` statement, we check the brand name and if it matches any of our patterns, and if so, we print out the factory's location.
|
||||
|
||||
If the brand name does not match any of our `case` statements, we print out a default message: `an unknown car brand`.
|
||||
|
||||
## Conclusion
|
||||
|
||||
I would advise you to try and modify the script and play with it a bit so that you could practice what you've just learned in the last two chapters!
|
||||
|
||||
For more examples of Bash `case` statements, make sure to check chapter 16, where we would create an interactive menu in Bash using a `cases` statement to process the user input.
|
||||
@@ -1,197 +0,0 @@
|
||||
# Bash Loops
|
||||
|
||||
As with any other language, loops are very convenient. With Bash you can use `for` loops, `while` loops, and `until` loops.
|
||||
|
||||
## For loops
|
||||
|
||||
Here is the structure of a for loop:
|
||||
|
||||
```bash
|
||||
for var in ${list}
|
||||
do
|
||||
your_commands
|
||||
done
|
||||
```
|
||||
|
||||
Example:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
users="devdojo bobby tony"
|
||||
|
||||
for user in ${users}
|
||||
do
|
||||
echo "${user}"
|
||||
done
|
||||
```
|
||||
|
||||
A quick rundown of the example:
|
||||
|
||||
* First, we specify a list of users and store the value in a variable called `$users`.
|
||||
* After that, we start our `for` loop with the `for` keyword.
|
||||
* Then we define a new variable which would represent each item from the list that we give. In our case, we define a variable called `user`, which would represent each user from the `$users` variable.
|
||||
* Then we specify the `in` keyword followed by our list that we will loop through.
|
||||
* On the next line, we use the `do` keyword, which indicates what we will do for each iteration of the loop.
|
||||
* Then we specify the commands that we want to run.
|
||||
* Finally, we close the loop with the `done` keyword.
|
||||
|
||||
You can also use `for` to process a series of numbers. For example here is one way to loop through from 1 to 10:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
for num in {1..10}
|
||||
do
|
||||
echo ${num}
|
||||
done
|
||||
```
|
||||
|
||||
## While loops
|
||||
|
||||
The structure of a while loop is quite similar to the `for` loop:
|
||||
|
||||
```bash
|
||||
while [ your_condition ]
|
||||
do
|
||||
your_commands
|
||||
done
|
||||
```
|
||||
|
||||
Here is an example of a `while` loop:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
counter=1
|
||||
while [[ $counter -le 10 ]]
|
||||
do
|
||||
echo $counter
|
||||
((counter++))
|
||||
done
|
||||
```
|
||||
|
||||
First, we specified a counter variable and set it to `1`, then inside the loop, we added counter by using this statement here: `((counter++))`. That way, we make sure that the loop will run 10 times only and would not run forever. The loop will complete as soon as the counter becomes 10, as this is what we've set as the condition: `while [[ $counter -le 10 ]]`.
|
||||
|
||||
Let's create a script that asks the user for their name and not allow an empty input:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
read -p "What is your name? " name
|
||||
|
||||
while [[ -z ${name} ]]
|
||||
do
|
||||
echo "Your name can not be blank. Please enter a valid name!"
|
||||
read -p "Enter your name again? " name
|
||||
done
|
||||
|
||||
echo "Hi there ${name}"
|
||||
```
|
||||
|
||||
Now, if you run the above and just press enter without providing input, the loop would run again and ask you for your name again and again until you actually provide some input.
|
||||
|
||||
## Until Loops
|
||||
|
||||
The difference between `until` and `while` loops is that the `until` loop will run the commands within the loop until the condition becomes true.
|
||||
|
||||
Structure:
|
||||
|
||||
```bash
|
||||
until [[ your_condition ]]
|
||||
do
|
||||
your_commands
|
||||
done
|
||||
```
|
||||
|
||||
Example:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
count=1
|
||||
until [[ $count -gt 10 ]]
|
||||
do
|
||||
echo $count
|
||||
((count++))
|
||||
done
|
||||
```
|
||||
|
||||
## Continue and Break
|
||||
As with other languages, you can use `continue` and `break` with your bash scripts as well:
|
||||
|
||||
* `continue` tells your bash script to stop the current iteration of the loop and start the next iteration.
|
||||
|
||||
The syntax of the continue statement is as follows:
|
||||
|
||||
```bash
|
||||
continue [n]
|
||||
```
|
||||
|
||||
The [n] argument is optional and can be greater than or equal to 1. When [n] is given, the n-th enclosing loop is resumed. continue 1 is equivalent to continue.
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
for i in 1 2 3 4 5
|
||||
do
|
||||
if [[ $i –eq 2 ]]
|
||||
then
|
||||
echo "skipping number 2"
|
||||
continue
|
||||
fi
|
||||
echo "i is equal to $i"
|
||||
done
|
||||
```
|
||||
|
||||
We can also use continue command in similar way to break command for controlling multiple loops.
|
||||
|
||||
* `break` tells your bash script to end the loop straight away.
|
||||
|
||||
The syntax of the break statement takes the following form:
|
||||
|
||||
```bash
|
||||
break [n]
|
||||
```
|
||||
[n] is an optional argument and must be greater than or equal to 1. When [n] is provided, the n-th enclosing loop is exited. break 1 is equivalent to break.
|
||||
|
||||
Example:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
num=1
|
||||
while [[ $num –lt 10 ]]
|
||||
do
|
||||
if [[ $num –eq 5 ]]
|
||||
then
|
||||
break
|
||||
fi
|
||||
((num++))
|
||||
done
|
||||
echo "Loop completed"
|
||||
```
|
||||
|
||||
We can also use break command with multiple loops. If we want to exit out of current working loop whether inner or outer loop, we simply use break but if we are in inner loop & want to exit out of outer loop, we use break 2.
|
||||
|
||||
Example:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
for (( a = 1; a < 10; a++ ))
|
||||
do
|
||||
echo "outer loop: $a"
|
||||
for (( b = 1; b < 100; b++ ))
|
||||
do
|
||||
if [[ $b –gt 5 ]]
|
||||
then
|
||||
break 2
|
||||
fi
|
||||
echo "Inner loop: $b "
|
||||
done
|
||||
done
|
||||
```
|
||||
|
||||
The bash script will begin with a=1 & will move to inner loop and when it reaches b=5, it will break the outer loop.
|
||||
We can use break only instead of break 2, to break inner loop & see how it affects the output.
|
||||
@@ -1,66 +0,0 @@
|
||||
# Bash Functions
|
||||
|
||||
Functions are a great way to reuse code. The structure of a function in bash is quite similar to most languages:
|
||||
|
||||
```bash
|
||||
function function_name() {
|
||||
your_commands
|
||||
}
|
||||
```
|
||||
|
||||
You can also omit the `function` keyword at the beginning, which would also work:
|
||||
|
||||
```bash
|
||||
function_name() {
|
||||
your_commands
|
||||
}
|
||||
```
|
||||
|
||||
I prefer putting it there for better readability. But it is a matter of personal preference.
|
||||
|
||||
Example of a "Hello World!" function:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
function hello() {
|
||||
echo "Hello World Function!"
|
||||
}
|
||||
|
||||
hello
|
||||
```
|
||||
|
||||
>{notice} One thing to keep in mind is that you should not add the parenthesis when you call the function.
|
||||
|
||||
Passing arguments to a function work in the same way as passing arguments to a script:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
function hello() {
|
||||
echo "Hello $1!"
|
||||
}
|
||||
|
||||
hello DevDojo
|
||||
```
|
||||
|
||||
Functions should have comments mentioning description, global variables, arguments, outputs, and returned values, if applicable
|
||||
|
||||
```bash
|
||||
#######################################
|
||||
# Description: Hello function
|
||||
# Globals:
|
||||
# None
|
||||
# Arguments:
|
||||
# Single input argument
|
||||
# Outputs:
|
||||
# Value of input argument
|
||||
# Returns:
|
||||
# 0 if successful, non-zero on error.
|
||||
#######################################
|
||||
function hello() {
|
||||
echo "Hello $1!"
|
||||
}
|
||||
```
|
||||
|
||||
In the next few chapters we will be using functions a lot!
|
||||
@@ -1,83 +0,0 @@
|
||||
# Debugging, testing and shortcuts
|
||||
|
||||
In order to debug your bash scripts, you can use `-x` when executing your scripts:
|
||||
|
||||
```bash
|
||||
bash -x ./your_script.sh
|
||||
```
|
||||
|
||||
Or you can add `set -x` before the specific line that you want to debug, `set -x` enables a mode of the shell where all executed commands are printed to the terminal.
|
||||
|
||||
Another way to test your scripts is to use this fantastic tool here:
|
||||
|
||||
[https://www.shellcheck.net/](https://www.shellcheck.net/)
|
||||
|
||||
Just copy and paste your code into the textbox, and the tool will give you some suggestions on how you can improve your script.
|
||||
|
||||
You can also run the tool directly in your terminal:
|
||||
|
||||
[https://github.com/koalaman/shellcheck](https://github.com/koalaman/shellcheck)
|
||||
|
||||
If you like the tool, make sure to star it on GitHub and contribute!
|
||||
|
||||
As a SysAdmin/DevOps, I spend a lot of my day in the terminal. Here are my favorite shortcuts that help me do tasks quicker while writing Bash scripts or just while working in the terminal.
|
||||
|
||||
The below two are particularly useful if you have a very long command.
|
||||
|
||||
* Delete everything from the cursor to the end of the line:
|
||||
|
||||
```
|
||||
Ctrl + k
|
||||
```
|
||||
|
||||
* Delete everything from the cursor to the start of the line:
|
||||
|
||||
```
|
||||
Ctrl + u
|
||||
```
|
||||
|
||||
* Delete one word backward from cursor:
|
||||
|
||||
```
|
||||
Ctrl + w
|
||||
```
|
||||
|
||||
* Search your history backward. This is probably the one that I use the most. It is really handy and speeds up my work-flow a lot:
|
||||
|
||||
```
|
||||
Ctrl + r
|
||||
```
|
||||
|
||||
* Clear the screen, I use this instead of typing the `clear` command:
|
||||
|
||||
```
|
||||
Ctrl + l
|
||||
```
|
||||
|
||||
* Stops the output to the screen:
|
||||
|
||||
```
|
||||
Ctrl + s
|
||||
```
|
||||
|
||||
* Enable the output to the screen in case that previously stopped by `Ctrl + s`:
|
||||
|
||||
```
|
||||
Ctrl + q
|
||||
```
|
||||
|
||||
* Terminate the current command
|
||||
|
||||
```
|
||||
Ctrl + c
|
||||
```
|
||||
|
||||
* Throw the current command to background:
|
||||
|
||||
```
|
||||
Ctrl + z
|
||||
```
|
||||
|
||||
I use those regularly every day, and it saves me a lot of time.
|
||||
|
||||
If you think that I've missed any feel free to join the discussion on [the DigitalOcean community forum](https://www.digitalocean.com/community/questions/what-are-your-favorite-bash-shortcuts)!
|
||||
@@ -1,83 +0,0 @@
|
||||
# Creating custom bash commands
|
||||
|
||||
As a developer or system administrator, you might have to spend a lot of time in your terminal. I always try to look for ways to optimize any repetitive tasks.
|
||||
|
||||
One way to do that is to either write short bash scripts or create custom commands also known as aliases. For example, rather than typing a really long command every time you could just create a shortcut for it.
|
||||
|
||||
## Example
|
||||
|
||||
Let's start with the following scenario, as a system admin, you might have to check the connections to your web server quite often, so I will use the `netstat` command as an example.
|
||||
|
||||
What I would usually do when I access a server that is having issues with the connections to port 80 or 443 is to check if there are any services listening on those ports and the number of connections to the ports.
|
||||
|
||||
The following `netstat` command would show us how many TCP connections on port 80 and 443 we currently have:
|
||||
|
||||
```bash
|
||||
netstat -plant | grep '80\|443' | grep -v LISTEN | wc -l
|
||||
```
|
||||
This is quite a lengthy command so typing it every time might be time-consuming in the long run especially when you want to get that information quickly.
|
||||
|
||||
To avoid that, we can create an alias, so rather than typing the whole command, we could just type a short command instead. For example, lets say that we wanted to be able to type `conn` (short for connections) and get the same information. All we need to do in this case is to run the following command:
|
||||
|
||||
```bash
|
||||
alias conn="netstat -plant | grep '80\|443' | grep -v LISTEN | wc -l"
|
||||
```
|
||||
|
||||
That way we are creating an alias called `conn` which would essentially be a 'shortcut' for our long `netstat` command. Now if you run just `conn`:
|
||||
|
||||
```bash
|
||||
conn
|
||||
```
|
||||
|
||||
You would get the same output as the long `netstat` command.
|
||||
You can get even more creative and add some info messages like this one here:
|
||||
|
||||
```bash
|
||||
alias conn="echo 'Total connections on port 80 and 443:' ; netstat -plant | grep '80\|443' | grep -v LISTEN | wc -l"
|
||||
```
|
||||
|
||||
Now if you run `conn` you would get the following output:
|
||||
|
||||
```bash
|
||||
Total connections on port 80 and 443:
|
||||
12
|
||||
```
|
||||
Now if you log out and log back in, your alias would be lost. In the next step you will see how to make this persistent.
|
||||
|
||||
## Making the change persistent
|
||||
|
||||
In order to make the change persistent, we need to add the `alias` command in our shell profile file.
|
||||
|
||||
By default on Ubuntu this would be the `~/.bashrc` file, for other operating systems this might be the `~/.bash_profle`. With your favorite text editor open the file:
|
||||
|
||||
```bash
|
||||
nano ~/.bashrc
|
||||
```
|
||||
|
||||
Go to the bottom and add the following:
|
||||
|
||||
```bash
|
||||
alias conn="echo 'Total connections on port 80 and 443:' ; netstat -plant | grep '80\|443' | grep -v LISTEN | wc -l"
|
||||
```
|
||||
|
||||
Save and then exit.
|
||||
|
||||
That way now even if you log out and log back in again your change would be persisted and you would be able to run your custom bash command.
|
||||
|
||||
## Listing all of the available aliases
|
||||
|
||||
To list all of the available aliases for your current shell, you have to just run the following command:
|
||||
|
||||
```bash
|
||||
alias
|
||||
```
|
||||
|
||||
This would be handy in case that you are seeing some weird behavior with some commands.
|
||||
|
||||
## Conclusion
|
||||
|
||||
This is one way of creating custom bash commands or bash aliases.
|
||||
|
||||
Of course, you could actually write a bash script and add the script inside your `/usr/bin` folder, but this would not work if you don't have root or sudo access, whereas with aliases you can do it without the need of root access.
|
||||
|
||||
>{notice} This was initially posted on [DevDojo.com](https://devdojo.com/bobbyiliev/how-to-create-custom-bash-commands)
|
||||
@@ -1,180 +0,0 @@
|
||||
# Write your first Bash script
|
||||
|
||||
Let's try to put together what we've learned so far and create our first Bash script!
|
||||
|
||||
## Planning the script
|
||||
|
||||
As an example, we will write a script that would gather some useful information about our server like:
|
||||
|
||||
* Current Disk usage
|
||||
* Current CPU usage
|
||||
* Current RAM usage
|
||||
* Check the exact Kernel version
|
||||
|
||||
Feel free to adjust the script by adding or removing functionality so that it matches your needs.
|
||||
|
||||
## Writing the script
|
||||
|
||||
The first thing that you need to do is to create a new file with a `.sh` extension. I will create a file called `status.sh` as the script that we will create would give us the status of our server.
|
||||
|
||||
Once you've created the file, open it with your favorite text editor.
|
||||
|
||||
As we've learned in chapter 1, on the very first line of our Bash script we need to specify the so-called [Shebang](https://en.wikipedia.org/wiki/Shebang_(Unix)):
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
```
|
||||
|
||||
All that the shebang does is to instruct the operating system to run the script with the /bin/bash executable.
|
||||
|
||||
## Adding comments
|
||||
|
||||
Next, as discussed in chapter 6, let's start by adding some comments so that people could easily figure out what the script is used for. To do that right after the shebang you can just add the following:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
# Script that returns the current server status
|
||||
```
|
||||
|
||||
## Adding your first variable
|
||||
|
||||
Then let's go ahead and apply what we've learned in chapter 4 and add some variables which we might want to use throughout the script.
|
||||
|
||||
To assign a value to a variable in bash, you just have to use the `=` sign. For example, let's store the hostname of our server in a variable so that we could use it later:
|
||||
|
||||
```bash
|
||||
server_name=$(hostname)
|
||||
```
|
||||
|
||||
By using `$()` we tell bash to actually interpret the command and then assign the value to our variable.
|
||||
|
||||
Now if we were to echo out the variable we would see the current hostname:
|
||||
|
||||
```bash
|
||||
echo $server_name
|
||||
```
|
||||
|
||||
## Adding your first function
|
||||
|
||||
As you already know after reading chapter 12, in order to create a function in bash you need to use the following structure:
|
||||
|
||||
```bash
|
||||
function function_name() {
|
||||
your_commands
|
||||
}
|
||||
```
|
||||
|
||||
Let's create a function that returns the current memory usage on our server:
|
||||
|
||||
```bash
|
||||
function memory_check() {
|
||||
echo ""
|
||||
echo "The current memory usage on ${server_name} is: "
|
||||
free -h
|
||||
echo ""
|
||||
}
|
||||
```
|
||||
|
||||
Quick run down of the function:
|
||||
|
||||
* `function memory_check() {` - this is how we define the function
|
||||
* `echo ""` - here we just print a new line
|
||||
* `echo "The current memory usage on ${server_name} is: "` - here we print a small message and the `$server_name` variable
|
||||
* `}` - finally this is how we close the function
|
||||
|
||||
Then once the function has been defined, in order to call it, just use the name of the function:
|
||||
|
||||
```bash
|
||||
# Define the function
|
||||
function memory_check() {
|
||||
echo ""
|
||||
echo "The current memory usage on ${server_name} is: "
|
||||
free -h
|
||||
echo ""
|
||||
}
|
||||
|
||||
# Call the function
|
||||
memory_check
|
||||
```
|
||||
|
||||
## Adding more functions challenge
|
||||
|
||||
Before checking out the solution, I would challenge you to use the function from above and write a few functions by yourself.
|
||||
|
||||
The functions should do the following:
|
||||
|
||||
* Current Disk usage
|
||||
* Current CPU usage
|
||||
* Current RAM usage
|
||||
* Check the exact Kernel version
|
||||
|
||||
Feel free to use google if you are not sure what commands you need to use in order to get that information.
|
||||
|
||||
Once you are ready, feel free to scroll down and check how we've done it and compare the results!
|
||||
|
||||
Note that there are multiple correct ways of doing it!
|
||||
|
||||
## The sample script
|
||||
|
||||
Here's what the end result would look like:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
##
|
||||
# BASH 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} is: "
|
||||
free -h
|
||||
echo ""
|
||||
}
|
||||
|
||||
function cpu_check() {
|
||||
echo ""
|
||||
echo "CPU load on ${server_name} is: "
|
||||
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} is: "
|
||||
echo ""
|
||||
uname -r
|
||||
echo ""
|
||||
}
|
||||
|
||||
function all_checks() {
|
||||
memory_check
|
||||
cpu_check
|
||||
tcp_check
|
||||
kernel_check
|
||||
}
|
||||
|
||||
all_checks
|
||||
```
|
||||
|
||||
## Conclusion
|
||||
|
||||
Bash scripting is awesome! 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 boring and repetitive daily tasks, so that you can focus on more productive and fun things!
|
||||
|
||||
>{notice} This was initially posted on [DevDojo.com](https://devdojo.com/bobbyiliev/introduction-to-bash-scripting)
|
||||
@@ -1,305 +0,0 @@
|
||||
# Creating an interactive menu in Bash
|
||||
|
||||
In this tutorial, I will show you how to create a multiple-choice menu in Bash so that your users could choose between what action should be executed!
|
||||
|
||||
We would reuse some of the code from the previous chapter, so if you have not read it yet make sure to do so.
|
||||
|
||||
## Planning the functionality
|
||||
|
||||
Let's start again by going over the main functionality of the script:
|
||||
|
||||
* Checks the current Disk usage
|
||||
* Checks the current CPU usage
|
||||
* Checks the current RAM usage
|
||||
* Checks the check the exact Kernel version
|
||||
|
||||
In case that you don't have it on hand, here is the script itself:
|
||||
|
||||
```bash
|
||||
#!/bin/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} is: "
|
||||
free -h
|
||||
echo ""
|
||||
}
|
||||
|
||||
function cpu_check() {
|
||||
echo ""
|
||||
echo "CPU load on ${server_name} is: "
|
||||
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} is: "
|
||||
echo ""
|
||||
uname -r
|
||||
echo ""
|
||||
}
|
||||
|
||||
function all_checks() {
|
||||
memory_check
|
||||
cpu_check
|
||||
tcp_check
|
||||
kernel_check
|
||||
}
|
||||
```
|
||||
|
||||
We will then build a menu that allows the user to choose which function to be executed.
|
||||
|
||||
Of course, you can adjust the function or add new ones depending on your needs.
|
||||
|
||||
## Adding some colors
|
||||
|
||||
In order to make the menu a bit more 'readable' and easy to grasp at first glance, we will add some color functions.
|
||||
|
||||
At the beginning of your script add the following color functions:
|
||||
|
||||
```bash
|
||||
##
|
||||
# Color Variables
|
||||
##
|
||||
green='\e[32m'
|
||||
blue='\e[34m'
|
||||
clear='\e[0m'
|
||||
|
||||
##
|
||||
# Color Functions
|
||||
##
|
||||
|
||||
ColorGreen(){
|
||||
echo -ne $green$1$clear
|
||||
}
|
||||
ColorBlue(){
|
||||
echo -ne $blue$1$clear
|
||||
}
|
||||
```
|
||||
|
||||
You can use the color functions as follows:
|
||||
|
||||
```bash
|
||||
echo -ne $(ColorBlue 'Some text here')
|
||||
```
|
||||
|
||||
The above would output the `Some text here` string and it would be blue!
|
||||
|
||||
# Adding the menu
|
||||
|
||||
Finally, to add our menu, we will create a separate function with a case switch for our menu options:
|
||||
|
||||
```bash
|
||||
menu(){
|
||||
echo -ne "
|
||||
My First Menu
|
||||
$(ColorGreen '1)') Memory usage
|
||||
$(ColorGreen '2)') CPU load
|
||||
$(ColorGreen '3)') Number of TCP connections
|
||||
$(ColorGreen '4)') Kernel version
|
||||
$(ColorGreen '5)') Check All
|
||||
$(ColorGreen '0)') Exit
|
||||
$(ColorBlue 'Choose an option:') "
|
||||
read 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 $red"Wrong option."$clear; WrongCommand;;
|
||||
esac
|
||||
}
|
||||
```
|
||||
|
||||
### A quick rundown of the code
|
||||
|
||||
First we just echo out the menu options with some color:
|
||||
|
||||
```
|
||||
echo -ne "
|
||||
My First Menu
|
||||
$(ColorGreen '1)') Memory usage
|
||||
$(ColorGreen '2)') CPU load
|
||||
$(ColorGreen '3)') Number of TCP connections
|
||||
$(ColorGreen '4)') Kernel version
|
||||
$(ColorGreen '5)') Check All
|
||||
$(ColorGreen '0)') Exit
|
||||
$(ColorBlue 'Choose an option:') "
|
||||
```
|
||||
|
||||
Then we read the answer of the user and store it in a variable called `$a`:
|
||||
|
||||
```bash
|
||||
read a
|
||||
```
|
||||
|
||||
Finally, we have a switch case which triggers a different function depending on the value of `$a`:
|
||||
|
||||
```bash
|
||||
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 $red"Wrong option."$clear; WrongCommand;;
|
||||
esac
|
||||
```
|
||||
|
||||
At the end we need to call the menu function to actually print out the menu:
|
||||
|
||||
```bash
|
||||
# Call the menu function
|
||||
menu
|
||||
```
|
||||
|
||||
## Testing the script
|
||||
|
||||
In the end, your script will look like this:
|
||||
|
||||
```bash
|
||||
#!/bin/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} is: "
|
||||
free -h
|
||||
echo ""
|
||||
}
|
||||
|
||||
function cpu_check() {
|
||||
echo ""
|
||||
echo "CPU load on ${server_name} is: "
|
||||
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} is: "
|
||||
echo ""
|
||||
uname -r
|
||||
echo ""
|
||||
}
|
||||
|
||||
function all_checks() {
|
||||
memory_check
|
||||
cpu_check
|
||||
tcp_check
|
||||
kernel_check
|
||||
}
|
||||
|
||||
##
|
||||
# Color Variables
|
||||
##
|
||||
green='\e[32m'
|
||||
blue='\e[34m'
|
||||
clear='\e[0m'
|
||||
|
||||
##
|
||||
# Color Functions
|
||||
##
|
||||
|
||||
ColorGreen(){
|
||||
echo -ne $green$1$clear
|
||||
}
|
||||
ColorBlue(){
|
||||
echo -ne $blue$1$clear
|
||||
}
|
||||
|
||||
menu(){
|
||||
echo -ne "
|
||||
My First Menu
|
||||
$(ColorGreen '1)') Memory usage
|
||||
$(ColorGreen '2)') CPU load
|
||||
$(ColorGreen '3)') Number of TCP connections
|
||||
$(ColorGreen '4)') Kernel version
|
||||
$(ColorGreen '5)') Check All
|
||||
$(ColorGreen '0)') Exit
|
||||
$(ColorBlue 'Choose an option:') "
|
||||
read 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 $red"Wrong option."$clear; WrongCommand;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Call the menu function
|
||||
menu
|
||||
```
|
||||
|
||||
To test the script, create a new filed with a `.sh` extension, for example: `menu.sh` and then run it:
|
||||
|
||||
```bash
|
||||
bash menu.sh
|
||||
```
|
||||
|
||||
The output that you would get will look like this:
|
||||
|
||||
```bash
|
||||
My First Menu
|
||||
1) Memory usage
|
||||
2) CPU load
|
||||
3) Number of TCP connections
|
||||
4) Kernel version
|
||||
5) Check All
|
||||
0) Exit
|
||||
Choose an option:
|
||||
```
|
||||
|
||||
You will be able to choose a different option from the list and each number will call a different function from the script:
|
||||
|
||||

|
||||
|
||||
## Conclusion
|
||||
|
||||
You now know how to create a Bash menu and implement it in your scripts so that users could select different values!
|
||||
|
||||
>{notice} This content was initially posted on [DevDojo.com](https://devdojo.com/bobbyiliev/how-to-work-with-json-in-bash-using-jq)
|
||||
@@ -1,129 +0,0 @@
|
||||
# Executing BASH scripts on Multiple Remote Servers
|
||||
|
||||
Any command that you can run from the command line can be used in a bash script. Scripts are used to run a series of commands. Bash is available by default on Linux and macOS operating systems.
|
||||
|
||||
Let's have a hypothetical scenario where you need to execute a BASH script on multiple remote servers, but you don't want to manually copy the script to each server, then again login to each server individually and only then execute the script.
|
||||
|
||||
Of course you could use a tool like Ansible but let's learn how to do that with Bash!
|
||||
|
||||
## Prerequisites
|
||||
|
||||
For this example I will use 3 remote Ubuntu servers deployed on DigitalOcean. If you don't have a Digital Ocean account yet, you can sign up for DigitalOcean and get $100 free credit via this referral link here:
|
||||
|
||||
[https://m.do.co/c/2a9bba940f39](https://m.do.co/c/2a9bba940f39)
|
||||
|
||||
Once you have your Digital Ocean account ready go ahead and deploy 3 droplets.
|
||||
|
||||
I've gone ahead and created 3 Ubuntu servers:
|
||||
|
||||

|
||||
|
||||
I'll put a those servers IP's in a `servers.txt` file which I would use to loop though with our Bash script.
|
||||
|
||||
If you are new to DigitalOcean you can follow the steps on how to create a Droplet here:
|
||||
|
||||
* [How to Create a Droplet from the DigitalOcean Control Panel](https://www.digitalocean.com/docs/droplets/how-to/create/)
|
||||
|
||||
You can also follow the steps from this video here on how to do your initial server setup:
|
||||
|
||||
* [How to do your Initial Server Setup with Ubuntu](https://youtu.be/7NL2_4HIgKU)
|
||||
|
||||
Or even better, you can follow this article here on how to automate your initial server setup with Bash:
|
||||
|
||||
[Automating Initial Server Setup with Ubuntu 18.04 with Bash](https://www.digitalocean.com/community/tutorials/automating-initial-server-setup-with-ubuntu-18-04)
|
||||
|
||||
With the 3 new servers in place, we can go ahead and focus on running our Bash script on all of them with a single command!
|
||||
|
||||
## The BASH Script
|
||||
|
||||
I will reuse the demo script from the previous chapter with some slight changes. It simply executes a few checks like the current memory usage, the current CPU usage, the number of TCP connections and the version of the kernel.
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
##
|
||||
# BASH script that checks the following:
|
||||
# - Memory usage
|
||||
# - CPU load
|
||||
# - Number of TCP connections
|
||||
# - Kernel version
|
||||
##
|
||||
|
||||
##
|
||||
# Memory check
|
||||
##
|
||||
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
|
||||
```
|
||||
|
||||
Copy the code bellow and add this in a file called `remote_check.sh`. You can also get the script from [here](https://devdojo.com/bobbyiliev/executing-bash-script-on-multiple-remote-server).
|
||||
|
||||
## Running the Script on all Servers
|
||||
|
||||
Now that we have the script and the servers ready and that we've added those servers in our servers.txt file we can run the following command to loop though all servers and execute the script remotely without having to copy the script to each server and individually connect to each server.
|
||||
|
||||
```bash
|
||||
for server in $(cat servers.txt) ; do ssh your_user@${server} 'bash -s' < ./remote_check.sh ; done
|
||||
```
|
||||
|
||||
What this for loop does is, it goes through each server in the servers.txt file and then it runs the following command for each item in the list:
|
||||
|
||||
```bash
|
||||
ssh your_user@the_server_ip 'bash -s' < ./remote_check.sh
|
||||
```
|
||||
|
||||
You would get the following output:
|
||||
|
||||

|
||||
|
||||
## Conclusion
|
||||
|
||||
This is just a really simple example on how to execute a simple script on multiple servers without having to copy the script to each server and without having to access the servers individually.
|
||||
|
||||
Of course you could run a much more complex script and on many more servers.
|
||||
|
||||
If you are interested in automation, I would recommend checking out the Ansible resources page on the DigitalOcean website:
|
||||
|
||||
[Ansible Resources](https://www.digitalocean.com/community/tags/ansible)
|
||||
|
||||
>{notice} This content was initially posted on [DevDojo](https://devdojo.com/bobbyiliev/bash-script-to-summarize-your-nginx-and-apache-access-logs)
|
||||
@@ -1,225 +0,0 @@
|
||||
# Work with JSON in BASH using jq
|
||||
|
||||
The `jq` command-line tool is a lightweight and flexible command-line **JSON** processor. It is great for parsing JSON output in BASH.
|
||||
|
||||
One of the great things about `jq` is that it is written in portable C, and it has zero runtime dependencies. All you need to do is to download a single binary or use a package manager like apt and install it with a single command.
|
||||
|
||||
## Planning the script
|
||||
|
||||
For the demo in this tutorial, I would use an external REST API that returns a simple JSON output called the [QuizAPI](https://quizapi.io/):
|
||||
|
||||
> [https://quizapi.io/](https://quizapi.io/)
|
||||
|
||||
If you want to follow along make sure to get a free API key here:
|
||||
|
||||
> [https://quizapi.io/clientarea/settings/token](https://quizapi.io/clientarea/settings/token)
|
||||
|
||||
The QuizAPI is free for developers.
|
||||
|
||||
## Installing jq
|
||||
|
||||
There are many ways to install `jq` on your system. One of the most straight forward ways to do so is to use the package manager depending on your OS.
|
||||
|
||||
Here is a list of the commands that you would need to use depending on your OS:
|
||||
|
||||
* Install jq on Ubuntu/Debian:
|
||||
|
||||
```bash
|
||||
sudo apt-get install jq
|
||||
```
|
||||
|
||||
* Install jq on Fedora:
|
||||
|
||||
```bash
|
||||
sudo dnf install jq
|
||||
```
|
||||
|
||||
* Install jq on openSUSE:
|
||||
|
||||
```bash
|
||||
sudo zypper install jq
|
||||
```
|
||||
|
||||
- Install jq on Arch:
|
||||
|
||||
```bash
|
||||
sudo pacman -S jq
|
||||
```
|
||||
|
||||
* Installing on Mac with Homebrew:
|
||||
|
||||
```bash
|
||||
brew install jq
|
||||
```
|
||||
|
||||
* Install on Mac with MacPort:
|
||||
|
||||
```bash
|
||||
port install jq
|
||||
```
|
||||
|
||||
If you are using other OS, I would recommend taking a look at the official documentation here for more information:
|
||||
|
||||
> [https://stedolan.github.io/jq/download/](https://stedolan.github.io/jq/download/)
|
||||
|
||||
Once you have jq installed you can check your current version by running this command:
|
||||
|
||||
```bash
|
||||
jq --version
|
||||
```
|
||||
|
||||
## Parsing JSON with jq
|
||||
|
||||
Once you have `jq` installed and your QuizAPI API Key, you can parse the JSON output of the QuizAPI directly in your terminal.
|
||||
|
||||
First, create a variable that stores your API Key:
|
||||
|
||||
```bash
|
||||
API_KEY=YOUR_API_KEY_HERE
|
||||
```
|
||||
|
||||
In order to get some output from one of the endpoints of the QuizAPI you can use the curl command:
|
||||
|
||||
```bash
|
||||
curl "https://quizapi.io/api/v1/questions?apiKey=${API_KEY}&limit=10"
|
||||
```
|
||||
|
||||
For a more specific output, you can use the QuizAPI URL Generator here:
|
||||
|
||||
> [https://quizapi.io/api-config](https://quizapi.io/api-config)
|
||||
|
||||
After running the curl command, the output which you would get would look like this:
|
||||
|
||||

|
||||
|
||||
This could be quite hard to read, but thanks to the jq command-line tool, all we need to do is pipe the curl command to jq and we would see a nice formatted JSON output:
|
||||
|
||||
```bash
|
||||
curl "https://quizapi.io/api/v1/questions?apiKey=${API_KEY}&limit=10" | jq
|
||||
```
|
||||
|
||||
> Note the `| jq` at the end.
|
||||
|
||||
In this case the output that you would get would look something like this:
|
||||
|
||||

|
||||
|
||||
Now, this looks much nicer! The jq command-line tool formatted the output for us and added some nice coloring!
|
||||
|
||||
## Getting the first element with jq
|
||||
|
||||
Let's say that we only wanted to get the first element from the JSON output, in order to do that we have to just specify the index that we want to see with the following syntax:
|
||||
|
||||
```bash
|
||||
jq .[0]
|
||||
```
|
||||
|
||||
Now, if we run the curl command again and pipe the output to jq .[0] like this:
|
||||
|
||||
```bash
|
||||
curl "https://quizapi.io/api/v1/questions?apiKey=${API_KEY}&limit=10" | jq.[0]
|
||||
```
|
||||
|
||||
You will only get the first element and the output will look like this:
|
||||
|
||||

|
||||
|
||||
## Getting a value only for specific key
|
||||
|
||||
Sometimes you might want to get only the value of a specific key only, let's say in our example the QuizAPI returns a list of questions along with the answers, description and etc. but what if you wanted to get the Questions only without the additional information?
|
||||
|
||||
This is going to be quite straight forward with `jq`, all you need to do is add the key after jq command, so it would look something like this:
|
||||
|
||||
```bash
|
||||
jq .[].question
|
||||
```
|
||||
|
||||
We have to add the `.[]` as the QuizAPI returns an array and by specifying `.[]` we tell jq that we want to get the .question value for all of the elements in the array.
|
||||
|
||||
The output that you would get would look like this:
|
||||
|
||||

|
||||
|
||||
As you can see we now only get the questions without the rest of the values.
|
||||
|
||||
## Using jq in a BASH script
|
||||
|
||||
Let's go ahead and create a small bash script which should output the following information for us:
|
||||
|
||||
* Get only the first question from the output
|
||||
* Get all of the answers for that question
|
||||
* Assign the answers to variables
|
||||
* Print the question and the answers
|
||||
* To do that I've put together the following script:
|
||||
|
||||
>{notice} make sure to change the API_KEY part with your actual QuizAPI key:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
##
|
||||
# Make an API call to QuizAPI and store the output in a variable
|
||||
##
|
||||
output=$(curl 'https://quizapi.io/api/v1/questions?apiKey=API_KEY&limit=10' 2>/dev/null)
|
||||
|
||||
##
|
||||
# Get only the first question
|
||||
##
|
||||
output=$(echo $output | jq .[0])
|
||||
|
||||
##
|
||||
# Get the question
|
||||
##
|
||||
question=$(echo $output | jq .question)
|
||||
|
||||
##
|
||||
# Get the answers
|
||||
##
|
||||
|
||||
answer_a=$(echo $output | jq .answers.answer_a)
|
||||
answer_b=$(echo $output | jq .answers.answer_b)
|
||||
answer_c=$(echo $output | jq .answers.answer_c)
|
||||
answer_d=$(echo $output | jq .answers.answer_d)
|
||||
|
||||
##
|
||||
# Output the question
|
||||
##
|
||||
|
||||
echo "
|
||||
Question: ${question}
|
||||
|
||||
A) ${answer_a}
|
||||
B) ${answer_b}
|
||||
C) ${answer_c}
|
||||
D) ${answer_d}
|
||||
|
||||
"
|
||||
```
|
||||
|
||||
If you run the script you would get the following output:
|
||||
|
||||

|
||||
|
||||
We can even go further by making this interactive so that we could actually choose the answer directly in our terminal.
|
||||
|
||||
There is already a bash script that does this by using the QuizAPI and `jq`:
|
||||
|
||||
You can take a look at that script here:
|
||||
|
||||
* [https://github.com/QuizApi/QuizAPI-BASH/blob/master/quiz.sh](https://github.com/QuizApi/QuizAPI-BASH/blob/master/quiz.sh)
|
||||
|
||||
## Conclusion
|
||||
|
||||
The `jq` command-line tool is an amazing tool that gives you the power to work with JSON directly in your BASH terminal.
|
||||
|
||||
That way you can easily interact with all kinds of different REST APIs with BASH.
|
||||
|
||||
For more information, you could take a look at the official documentation here:
|
||||
|
||||
* [https://stedolan.github.io/jq/manual/](https://stedolan.github.io/jq/manual/)
|
||||
|
||||
And for more information on the **QuizAPI**, you could take a look at the official documentation here:
|
||||
|
||||
* [https://quizapi.io/docs/1.0/overview](https://quizapi.io/docs/1.0/overview)
|
||||
|
||||
>{notice} This content was initially posted on [DevDojo.com](https://devdojo.com/bobbyiliev/how-to-work-with-json-in-bash-using-jq)
|
||||
@@ -1,104 +0,0 @@
|
||||
# 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)
|
||||
@@ -1,83 +0,0 @@
|
||||
# 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)
|
||||
@@ -1,95 +0,0 @@
|
||||
# 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).
|
||||
@@ -1,126 +0,0 @@
|
||||
# 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)
|
||||
@@ -1,228 +0,0 @@
|
||||
# Redirection in Bash
|
||||
|
||||
A Linux superuser must have a good knowledge of pipes and redirection in Bash. It is an essential component of the system and is often helpful in the field of Linux System Administration.
|
||||
|
||||
When you run a command like ``ls``, ``cat``, etc, you get some output on the terminal. If you write a wrong command, pass a wrong flag or a wrong command-line argument, you get error output on the terminal.
|
||||
In both the cases, you are given some text. It may seem like "just text" to you, but the system treats this text differently. This identifier is known as a File Descriptor (fd).
|
||||
|
||||
In Linux, there are 3 File Descriptors, **STDIN** (0); **STDOUT** (1) and **STDERR** (2).
|
||||
|
||||
* **STDIN** (fd: 0): Manages the input in the terminal.
|
||||
* **STDOUT** (fd: 1): Manages the output text in the terminal.
|
||||
* **STDERR** (fd: 2): Manages the error text in the terminal.
|
||||
|
||||
# Difference between Pipes and Redirections
|
||||
|
||||
Both *pipes* and *redidertions* redirect streams `(file descriptor)` of process being executed. The main difference is that *redirections* deal with `files stream`, sending the output stream to a file or sending the content of a given file to the input stream of the process.
|
||||
|
||||
On the other hand a pipe connects two commands by sending the output stream of the first one to the input stream of the second one. without any redidertions specified.
|
||||
|
||||
# Redirection in Bash
|
||||
|
||||
## STDIN (Standard Input)
|
||||
When you enter some input text for a command that asks for it, you are actually entering the text to the **STDIN** file descriptor. Run the ``cat`` command without any command-line arguments.
|
||||
It may seem that the process has paused but in fact it's ``cat`` asking for **STDIN**. ``cat`` is a simple program and will print the text passed to **STDIN**. However, you can extend the use case by redirecting the input to the commands that take **STDIN**.
|
||||
|
||||
Example with ``cat``:
|
||||
```
|
||||
cat << EOF
|
||||
Hello World!
|
||||
How are you?
|
||||
EOF
|
||||
```
|
||||
This will simply print the provided text on the terminal screen:
|
||||
```
|
||||
Hello World!
|
||||
How are you?
|
||||
```
|
||||
|
||||
The same can be done with other commands that take input via STDIN. Like, ``wc``:
|
||||
```
|
||||
wc -l << EOF
|
||||
Hello World!
|
||||
How are you?
|
||||
EOF
|
||||
```
|
||||
The ``-l`` flag with ``wc`` counts the number of lines.
|
||||
This block of bash code will print the number of lines to the terminal screen:
|
||||
```
|
||||
2
|
||||
```
|
||||
|
||||
## STDOUT (Standard Output)
|
||||
The normal non-error text on your terminal screen is printed via the **STDOUT** file descriptor. The **STDOUT** of a command can be redirected into a file, in such a way that the output of the command is written to a file instead of being printed on the terminal screen.
|
||||
This is done simply with the help of ``>`` and ``>>`` operators.
|
||||
|
||||
Example:
|
||||
```
|
||||
echo "Hello World!" > file.txt
|
||||
```
|
||||
The above command will not print "Hello World" on the terminal screen, it will instead create a file called ``file.txt`` and will write the "Hello World" string to it.
|
||||
This can be verified by running the ``cat`` command on the ``file.txt`` file.
|
||||
```
|
||||
cat file.txt
|
||||
```
|
||||
|
||||
However, everytime you redirect the **STDOUT** of any command multiple times to the same file, it will remove the existing contents of the file to write the new ones.
|
||||
|
||||
Example:
|
||||
```
|
||||
echo "Hello World!" > file.txt
|
||||
echo "How are you?" > file.txt
|
||||
```
|
||||
|
||||
On running ``cat`` on ``file.txt`` file:
|
||||
```
|
||||
cat file.txt
|
||||
```
|
||||
|
||||
You will only get the "How are you?" string printed.
|
||||
```
|
||||
How are you?
|
||||
```
|
||||
|
||||
This is because the "Hello World" string has been overwritten.
|
||||
This behaviour can be avoided using the ``>>`` operator.
|
||||
|
||||
The above example can be written as:
|
||||
```
|
||||
echo "Hello World!" > file.txt
|
||||
echo "How are you?" >> file.txt
|
||||
```
|
||||
|
||||
On running ``cat`` on the ``file.txt`` file, you will get the desired result.
|
||||
```
|
||||
Hello World!
|
||||
How are you?
|
||||
```
|
||||
|
||||
Alternatively, the redirection operator for **STDOUT** can also be written as ``1>``. Like,
|
||||
```
|
||||
echo "Hello World!" 1> file.txt
|
||||
```
|
||||
|
||||
## STDERR (Standard Error)
|
||||
|
||||
The error text on the terminal screen is printed via the **STDERR** of the command. For example:
|
||||
```
|
||||
ls --hello
|
||||
```
|
||||
would give an error messages. This error message is the **STDERR** of the command.
|
||||
|
||||
**STDERR** can be redirected using the ``2>`` operator.
|
||||
|
||||
```
|
||||
ls --hello 2> error.txt
|
||||
```
|
||||
|
||||
This command will redirect the error message to the ``error.txt`` file and write it to it. This can be verified by running the ``cat`` command on the ``error.txt`` file.
|
||||
|
||||
You can also use the ``2>>`` operator for **STDERR** just like you used ``>>`` for **STDOUT**.
|
||||
|
||||
Error messages in Bash Scripts can be undesirable sometimes. You can choose to ignore them by redirecting the error message to the ``/dev/null`` file.
|
||||
``/dev/null`` is pseudo-device that takes in text and then immediately discards it.
|
||||
|
||||
The above example can be written follows to ignore the error text completely:
|
||||
```
|
||||
ls --hello 2> /dev/null
|
||||
```
|
||||
|
||||
Of course, you can redirect both **STDOUT** and **STDERR** for the same command or script.
|
||||
```
|
||||
./install_package.sh > output.txt 2> error.txt
|
||||
```
|
||||
|
||||
Both of them can be redirected to the same file as well.
|
||||
```
|
||||
./install_package.sh > file.txt 2> file.txt
|
||||
```
|
||||
|
||||
There is also a shorter way to do this.
|
||||
```
|
||||
./install_package.sh > file.txt 2>&1
|
||||
```
|
||||
|
||||
# Piping
|
||||
|
||||
So far we have seen how to redirect the **STDOUT**, **STDIN** and **STDOUT** to and from a file.
|
||||
To concatenate the output of program *(command)* as the input of another program *(command)* you can use a vertical bar `|`.
|
||||
|
||||
Example:
|
||||
```
|
||||
ls | grep ".txt"
|
||||
```
|
||||
This command will list the files in the current directory and pass output to *`grep`* command which then filter the output to only show the files that contain the string ".txt".
|
||||
|
||||
Syntax:
|
||||
```
|
||||
[time [-p]] [!] command1 [ | or |& command2 ] …
|
||||
```
|
||||
|
||||
You can also build arbitrary chains of commands by piping them together to achieve a powerful result.
|
||||
|
||||
This example creates a listing of every user which owns a file in a given directory as well as how many files and directories they own:
|
||||
```
|
||||
ls -l /projects/bash_scripts | tail -n +2 | sed 's/\s\s*/ /g' | cut -d ' ' -f 3 | sort | uniq -c
|
||||
```
|
||||
Output:
|
||||
```
|
||||
8 anne
|
||||
34 harry
|
||||
37 tina
|
||||
18 ryan
|
||||
```
|
||||
|
||||
# HereDocument
|
||||
|
||||
The symbol `<<` can be used to create a temporary file [heredoc] and redirect from it at the command line.
|
||||
```
|
||||
COMMAND << EOF
|
||||
ContentOfDocument
|
||||
...
|
||||
...
|
||||
EOF
|
||||
```
|
||||
Note here that `EOF` represents the delimiter (end of file) of the heredoc. In fact, we can use any alphanumeric word in its place to signify the start and the end of the file. For instance, this is a valid heredoc:
|
||||
```
|
||||
cat << randomword1
|
||||
This script will print these lines on the terminal.
|
||||
Note that cat can read from standard input. Using this heredoc, we can
|
||||
create a temporary file with these lines as it's content and pipe that
|
||||
into cat.
|
||||
randomword1
|
||||
```
|
||||
|
||||
Effectively it will appear as if the contents of the heredoc are piped into the command. This can make the script very clean if multiple lines need to be piped into a program.
|
||||
|
||||
Further, we can attach more pipes as shown:
|
||||
```
|
||||
cat << randomword1 | wc
|
||||
This script will print these lines on the terminal.
|
||||
Note that cat can read from standard input. Using this heredoc, we can
|
||||
create a temporary file with these lines as it's content and pipe that
|
||||
into cat.
|
||||
randomword1
|
||||
```
|
||||
|
||||
Also, pre-defined variables can be used inside the heredocs.
|
||||
|
||||
# HereString
|
||||
|
||||
Herestrings are quite similar to heredocs but use `<<<`. These are used for single line strings that have to be piped into some program. This looks cleaner that heredocs as we don't have to specify the delimiter.
|
||||
|
||||
```
|
||||
wc <<<"this is an easy way of passing strings to the stdin of a program (here wc)"
|
||||
```
|
||||
|
||||
Just like heredocs, herestrings can contain variables.
|
||||
|
||||
## Summary
|
||||
|**Operator** |**Description** |
|
||||
|:---|:---|
|
||||
|`>`|`Save output to a file`|
|
||||
|`>>`|`Append output to a file`|
|
||||
|`<`|`Read input from a file`|
|
||||
|`2>`|`Redirect error messages`|
|
||||
|`\|`|`Send the output from one program as input to another program`|
|
||||
|`<<`|`Pipe multiple lines into a program cleanly`|
|
||||
|`<<<`|`Pipe a single line into a program cleanly`|
|
||||
@@ -1,336 +0,0 @@
|
||||
# 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).
|
||||
@@ -1,15 +0,0 @@
|
||||
# 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!
|
||||
@@ -1,82 +0,0 @@
|
||||
# A Linux Learning Playground Situation
|
||||
|
||||

|
||||
|
||||
wanna play with the application in this picture? connect to the server using the instructions below and run the command `hollywood`
|
||||
|
||||
## Introduction:
|
||||
|
||||
Welcome, aspiring Linux ninjas! This tutorial will guide you through accessing Shinobi Academy Linux, a custom-built server designed to provide a safe and engaging environment for you to learn and experiment with Linux. Brought to you by Softwareshinobi ([https://softwareshinobi.digital/](https://softwareshinobi.digital/)), this server is your gateway to the exciting world of open-source exploration.
|
||||
|
||||
## What You'll Learn:
|
||||
|
||||
* Connecting to a Linux server (using SSH)
|
||||
* Basic Linux commands (navigation, listing files, etc.)
|
||||
* Exploring pre-installed tools like cmatrix and hollywood
|
||||
|
||||
## What You'll Need:
|
||||
|
||||
* A computer with internet access
|
||||
* An SSH client (built-in on most Linux and macOS systems, downloadable for Windows)
|
||||
|
||||
## About Shinobi Academy:
|
||||
|
||||
Shinobi Academy, the online learning platform brought to you by Softwareshinobi!
|
||||
|
||||
Designed to empower aspiring tech enthusiasts, Shinobi Academy offers a comprehensive range of courses and resources to equip you with the skills you need to excel in the ever-evolving world of technology.
|
||||
|
||||
## Connecting to Shinobi Academy Linux:
|
||||
|
||||
1. Open your SSH client.
|
||||
2. Enter the following command (including the port number):
|
||||
|
||||
```
|
||||
ssh -p 2222 shinobi@linux.softwareshinobi.digital
|
||||
```
|
||||
|
||||
3. When prompted, enter the password "shinobi".
|
||||
|
||||
```
|
||||
username / shinobi
|
||||
```
|
||||
|
||||
```
|
||||
password / shinobi
|
||||
```
|
||||
|
||||
**Congratulations!** You're now connected to Shinobi Academy Linux.
|
||||
|
||||
## Exploring the Server:
|
||||
|
||||
Once connected, you can use basic Linux commands to navigate the system and explore its features. Here are a few examples:
|
||||
|
||||
* **`ls`:** Lists files and directories in the current directory.
|
||||
* **`cd`:** Changes directory. For example, `cd Desktop` will move you to the Desktop directory (if it exists).
|
||||
* **`pwd`:** Shows the current working directory.
|
||||
* **`man` followed by a command name:** Provides detailed information on a specific command (e.g., `man ls`).
|
||||
|
||||
## Pre-installed Goodies:
|
||||
|
||||
Shinobi Academy Linux comes pre-installed with some interesting tools to enhance your learning experience:
|
||||
|
||||
* **`cmatrix`:** Simulates the iconic falling code effect from the movie "The Matrix".
|
||||
* **`hollywood`:** Creates a variety of dynamic text effects on your terminal.
|
||||
|
||||
**Experimenting with these tools is a great way to explore the possibilities of Linux.**
|
||||
|
||||
## Conclusion:
|
||||
|
||||
By following these steps, you've successfully connected to Shinobi Academy Linux and begun your journey into the world of Linux. Use this platform to explore, experiment, and build your Linux skills!
|
||||
|
||||
A big thanks to Gemini for putting together these awesome docs!
|
||||
|
||||
## Master Linux Like a Pro: 1-on-1 Tutoring:
|
||||
|
||||
**Tired of fumbling in the terminal?** Imagine wielding Linux commands with ease, managing servers like a corporate ninja – just like my government and corporate gigs.
|
||||
|
||||
**1-on-1 tutoring unlocks your potential:**
|
||||
|
||||
* **Terminal mastery:** Conquer the command line and automate tasks like a pro.
|
||||
* **Become a command jedi:** Craft commands with lightning speed, streamlining your workflow.
|
||||
|
||||
**Ready to transform your skills?** [Learn More!](tutor.softwareshinobi.digital/linux)
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 10 KiB |
Binary file not shown.
22
docs/002-version-control.md
Normal file
22
docs/002-version-control.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# Version Control
|
||||
|
||||
*Version control*, also called *Source control*, allows you to track and manage all of the changes to your code.
|
||||
|
||||
### Why Use Version Control?
|
||||
|
||||
* Multiple people could work on the same project simultaneously.
|
||||
* Serves simultaneously as a repository, project narrative, communication medium, and team and product management tool.
|
||||
* Records all changes in a log
|
||||
* Allows team members to work concurrently and provides the facility to merge that work back together.
|
||||
* Traces each change made to the software.
|
||||
* Data is transitory and can be lost easily.
|
||||
|
||||
### What is Version Control System?
|
||||
|
||||
Also known as a source code manager (SCM) or a revision control system (RCS), it is a system that keeps track of changes to a file or set of files and in case of any problems, lets you go back in history, comparing changes over time, and easily revert to a working state of your source code. SVN, Mercurial, and the massively popular Git are popular version control systems for developers. All of these are free and open-source.
|
||||
|
||||

|
||||
|
||||
With distributed version control systems like Git, you would have your source code stored on a remote repository like GitHub and also a local repository stored on your computer.
|
||||
|
||||
You will learn more about remote and local repositories in the next few chapters. Still, one of the main points for the moment is that your source code would be stored on a remote repository, so in case that something goes wrong with your laptop, you would not lose all of your changes, but they will be safely stored on GitHub.
|
||||
63
docs/003-installing-git.md
Normal file
63
docs/003-installing-git.md
Normal file
@@ -0,0 +1,63 @@
|
||||
# Installing Git
|
||||
|
||||
In order for you to be able to use Git on your local machine, you would need to install it.
|
||||
|
||||
Depending on the operating system that you are using, you can follow the steps here.
|
||||
|
||||
### Install Git on Linux
|
||||
|
||||
With most Linux distributions, the Git command-line tool comes installed out of the box.
|
||||
|
||||
If this is not the case for you, you can install Git with the following command:
|
||||
|
||||
* On RHEL Linux:
|
||||
|
||||
```bash
|
||||
sudo dnf install git-all
|
||||
```
|
||||
|
||||
* On Debian based distributions including Ubuntu:
|
||||
|
||||
```bash
|
||||
sudo apt install git-all
|
||||
```
|
||||
|
||||
### Install Git on Mac
|
||||
|
||||
If you are using Mac, Git should be available out of the box as well. However, if this is not the case, there are 2 main ways of installing Git on your Mac:
|
||||
|
||||
* Using Homebrew: in case that you are using Homebrew, you can open your terminal and run the following:
|
||||
|
||||
```bash
|
||||
brew install git
|
||||
```
|
||||
|
||||
* Git installer: Alternatively, you could use the following installer:
|
||||
|
||||
[git-osx-installer](https://sourceforge.net/projects/git-osx-installer/)
|
||||
|
||||
I would personally stick to Homebrew.
|
||||
|
||||
### Install Git on Windows
|
||||
|
||||
If you have a Windows PC, you can follow the steps on how to install Git on Windows here:
|
||||
|
||||
[Install Git on Windows](https://git-scm.com/download/win)
|
||||
|
||||
During the installation, make sure to choose the Git Bash option, as this would provide you with a Git Bash terminal which you will use while following along.
|
||||
|
||||
### Check Git version
|
||||
|
||||
Once you have installed Git, in order to check the version of Git that you have installed on your machine, you could use the following command:
|
||||
|
||||
```bash
|
||||
git --version
|
||||
```
|
||||
|
||||
Example output:
|
||||
|
||||
```bash
|
||||
git version 2.25.1
|
||||
```
|
||||
|
||||
In my case, I have Git 2.25.1 installed on my laptop.
|
||||
109
docs/004-basic-shell-commands.md
Normal file
109
docs/004-basic-shell-commands.md
Normal file
@@ -0,0 +1,109 @@
|
||||
# Basic Shell Commands
|
||||
|
||||
As throughout this eBook, we will be using mainly Git via the command line. It is important to know basic shell commands so that you could find your way around the terminal.
|
||||
|
||||
So before we get started, let's go over a few basic shell commands!
|
||||
|
||||
### The `ls` command
|
||||
|
||||
The `ls` command allows you to list the contents of a folder/directory. All that you need to do in order to run the command is to open a terminal and run the following:
|
||||
|
||||
```bash
|
||||
ls
|
||||
```
|
||||
|
||||
The output will show you all of the files and folders that are located in your current directory. In my case, starting from the root directory of this project, the output is the following:
|
||||
|
||||
```
|
||||
CONTRIBUTING.md LICENSE README.md ebook index.html
|
||||
```
|
||||
|
||||
From the output, we can see that `CONTRIBUTING.md`, `LICENSE`, `README.md`, `index.html` are files, while `ebook` is a subdirectory/subfolder.
|
||||
|
||||
For more information about the `ls` command, make sure to check out this page [here](https://devdojo.com/tnylea/ls-command?ref=bobbyiliev).
|
||||
|
||||
> Note: This will work on a Linux/UNIX based systems. If you are on Windows and if you are using the built-in CMD, you would have to use the `dir` command.
|
||||
|
||||
### The `cd` command
|
||||
|
||||
The `cd` command stands for `Change Directory` and allows you to navigate through the filesystem of your computer or server. Let's say that I wanted to go inside the `ebook` directory from the output above. What I would need to do is to run the `cd` command followed by the directory that I want to access:
|
||||
|
||||
```bash
|
||||
cd ebook
|
||||
```
|
||||
|
||||
If I wanted to go back one level up, I would use the `cd ..` command. After doing so, I should be one level up from the `ebook` directory and back in the root directory of my project.
|
||||
|
||||
### The `pwd` command
|
||||
|
||||
The `pwd` command stands for `Print Working Directory` which essentially means that when you run the command, it will show you the current directory that you are in.
|
||||
|
||||
Let's take the example from above. If I run the `pwd` command, I would get the full path to the folder that I'm currently in:
|
||||
|
||||
```bash
|
||||
pwd
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
/home/bobby/introduction-to-git
|
||||
```
|
||||
|
||||
Then I could use the `cd` command and access the `ebook` directory:
|
||||
|
||||
```bash
|
||||
cd ebook
|
||||
```
|
||||
|
||||
And finally, if I was to run the `pwd` command again, I would see the following output:
|
||||
|
||||
```
|
||||
/home/bobby/introduction-to-git/ebook
|
||||
```
|
||||
|
||||
Essentially what happened was that thanks to the `pwd` command, I was able to see that I'm at the `/home/bobby/introduction-to-git` directory and then after accessing the `ebook` directory, again by using `pwd` I was able to see that my new current directory is `/home/bobby/introduction-to-git/ebook`.
|
||||
|
||||
### The `rm` command
|
||||
|
||||
The `rm` command stands for `remove` and allows you to delete files and folders. Let's say that I wanted to delete the `README.md` file, what I would have to do is run the following command:
|
||||
|
||||
```bash
|
||||
rm README.md
|
||||
```
|
||||
|
||||
In case that I had to delete a folder/directory, I would need to specify the `-r` flag:
|
||||
|
||||
```bash
|
||||
rm -r ebook
|
||||
```
|
||||
|
||||
> Note: keep in mind that the `rm` command would completely delete the files and folders, and the action is irreversible, meaning that you can't get them back.
|
||||
|
||||
### The `mkdir` command
|
||||
The `mkdir` command stands for `make directory` and is used for creating one or more new directories. All you need to do in order to create a new directory using this command is to open a terminal, `cd` into desired location and run the following:
|
||||
|
||||
```bash
|
||||
mkdir My_New_Directory
|
||||
```
|
||||
|
||||
The above command will create a new, empty directory called `My_New_Directory`.
|
||||
|
||||
You can also create serveral new directories by placing the names of desired directories after each other:
|
||||
|
||||
```bash
|
||||
mkdir My_New_Directory My_Another_New_Directory
|
||||
```
|
||||
|
||||
### The `touch` command
|
||||
|
||||
The `touch` command is used to update timestamps on files. A useful feature of the touch command is that it will create an empty file. This is useful if you want to create file in your directory that doesn't currently exist:
|
||||
|
||||
```bash
|
||||
touch README.md
|
||||
```
|
||||
The above will create a new, empty file with the name README.md
|
||||
|
||||
One thing that you need to keep in mind is that all shell commands are case sensitive, so if you type `LS` it would not work.
|
||||
|
||||
With that, now you know some basic shell commands which will be beneficial for your day-to-day activities.
|
||||
109
docs/005-git-configuration.md
Normal file
109
docs/005-git-configuration.md
Normal file
@@ -0,0 +1,109 @@
|
||||
# Git Configuration
|
||||
|
||||
The first time you set up Git on your machine, you would need to do some initial configuration.
|
||||
|
||||
There are a few main things that you would need to configure:
|
||||
|
||||
* Your details: like your name and email address
|
||||
* Your Git Editor
|
||||
* The default branch name: we will learn more about branches later on
|
||||
|
||||
We can change all of those things by using the `git config` command.
|
||||
|
||||
Let's get started with the initial configuration!
|
||||
|
||||
### The `git config` command
|
||||
|
||||
In order to configure your Git details like your user name and your email address, you need to use the following command:
|
||||
|
||||
* Configuring your Git user name:
|
||||
|
||||
```bash
|
||||
git config --global user.name "Your Name"
|
||||
```
|
||||
|
||||
* Configuring your Git email address:
|
||||
|
||||
```bash
|
||||
git config --global user.email johndoe@example.com
|
||||
```
|
||||
|
||||
> Usually, it is good to have a matching user name and email for your local Git configuration and your GitHub profile details
|
||||
|
||||
* Configuring your Git default editor
|
||||
|
||||
In some cases, when running Git commands via your terminal, an editor will open where you could type a commit message, for example. To specify your default editor, you need to run the following command:
|
||||
|
||||
```bash
|
||||
git config --global core.editor nano
|
||||
```
|
||||
|
||||
You can change the `nano` editor with another editor like `vim` or `emacs` based on your personal preferences.
|
||||
|
||||
* Configuring the default branch name
|
||||
|
||||
Whenever creating a new repository on your local machine, it gets initialized with a specific branch name which might be different from the default branch on GitHub. To make sure that the branch name on your local machine matches the default branch name on GitHub, you can use the following command:
|
||||
|
||||
```bash
|
||||
git config --global init.defaultBranch main
|
||||
```
|
||||
|
||||
Finally, once you are done with all changes, you can check your current Git configuration with the following command:
|
||||
|
||||
```bash
|
||||
git config --list
|
||||
```
|
||||
|
||||
Example output:
|
||||
|
||||
```
|
||||
user.name=Bobby Iliev
|
||||
user.email=bobby@bobbyiliev.com
|
||||
core.repositoryformatversion=0
|
||||
core.filemode=true
|
||||
core.bare=false
|
||||
core.logallrefupdates=true
|
||||
```
|
||||
|
||||
### The `~/.gitconfig` file
|
||||
|
||||
As we used the `--global` option in our commands, all of those Global Git settings would be stored in a .gitconfig` file inside your home directory.
|
||||
|
||||
We can use the `cat` command to check the content of the file:
|
||||
|
||||
```bash
|
||||
cat ~/.gitconfig
|
||||
```
|
||||
|
||||
Example output:
|
||||
|
||||
```
|
||||
[user]
|
||||
name = Bobby Iliev
|
||||
email = bobby@bobbyiliev.com
|
||||
```
|
||||
|
||||
You can even change the file manually with your favorite text editor, but I personally prefer to use the `git config` command to prevent any syntax problems.
|
||||
|
||||
### Repository specific git configurations
|
||||
|
||||
So far we have been using the `--global` option with all of our changes to our git configurations and this results in any configuration changes applying to all repositories. You might however want to change the configuration for only one specific repository.
|
||||
You can do this easily by running the same git config commands mentioned earlier but with out the `--global` option. This will save the changes for only the respository you are crrently in and leave your global settings the same as they were before.
|
||||
|
||||
### The `.git` directory
|
||||
|
||||
Whenever you initialize a new project or clone one from GitHub, it would have a `.git` directory where all of the Git commits would be recorded at and also a `config` file where the configuration settings for the particular project would be stored at.
|
||||
|
||||
You could use the `ls` command to check the contents of the `.git` folder:
|
||||
|
||||
```bash
|
||||
ls .git
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
COMMIT_EDITMSG HEAD branches config description hooks index info logs objects refs
|
||||
```
|
||||
|
||||
> Note: Before running the command, you would need to be inside your project's directory. We will learn about this in the next chapters when we learn more about the `git init` command and cloning an existing repository from GitHub with the `git clone` command.
|
||||
101
docs/006-introduction-to-GitHub.md
Normal file
101
docs/006-introduction-to-GitHub.md
Normal file
@@ -0,0 +1,101 @@
|
||||
# Introduction to GitHub
|
||||
|
||||
Before we deep dive into all of the various Git commands, let's quickly get familiar with GitHub.
|
||||
|
||||
Git is essentially the tool that you use to track your code changes, and GitHub, on the other side, is a website where you can push your local projects to.
|
||||
|
||||
This is essentially needed as it would act as a central hub where you would store your projects and all of your teammates or other people working on the same project as you would push their changes to.
|
||||
|
||||
### GitHub Registration
|
||||
|
||||
Before you get started, you would need to create an account with GitHub. You can do so via this link here:
|
||||
|
||||
* [Join GitHub](https://github.com/join)
|
||||
|
||||
You will get to the following page where you will need to add your new account details:
|
||||
|
||||

|
||||
|
||||
### GitHub Profile
|
||||
|
||||
Once you've registered, you can go to https://github.com/YOUR_USER_NAME, and you will be able to see your public profile where you can add some information about yourself. Here is an example profile which you can check: [GitHub Profile](https://github.com/bobbyiliev)
|
||||
|
||||

|
||||
|
||||
### Creating a new repository
|
||||
|
||||
If you are not familiar with the word repository, you can think of it as a project. It would hold all of the files of your application or website that you are building. People usually call their repository a repo for short.
|
||||
|
||||
To create a new repository on GitHub, you have to click on the `+` sign on the top right corner or click on the green `NEW` button in the top-left where repositories are mentioned and then click on the `New Repository` button:
|
||||
|
||||

|
||||
|
||||
After that, you'll get to a page where you can specify the information for your new repository like:
|
||||
|
||||
* The name of the project: Here, make sure to use something descriptive
|
||||
* Some general description about the project and what it is about
|
||||
* Choose whether you want the repository to be Public or Private
|
||||
|
||||

|
||||
|
||||
Once you've added the necessary information and hit the create button, you will get to a page with some instructions on how to push your local project to GitHub:
|
||||
|
||||

|
||||
|
||||
We will go over those steps more in-depth in the next few chapters.
|
||||
|
||||
### Public vs. Private repositories
|
||||
|
||||
Depending on the project and whether or not it is open source, you can set your repository to be **public** or **private**.
|
||||
|
||||
The main difference is that, with a public repository anyone on the internet can see that repository. Even though they'll be able to see the repository and read the code, you will be the maintainer of the project, and you will choose who can commit.
|
||||
|
||||
Whereas a private repository will only be accessible to you and those you have invited.
|
||||
|
||||
Public repositories are used for open source projects.
|
||||
|
||||
### Add colaborators to your projects
|
||||
|
||||
Colaborators are the people who actively work on the project, for example if a company has taken up a project for which some x, y, z are supposed to work, so these people are added as a colaborator by the the company.
|
||||
|
||||
Select a GitHub repository and navigate to the settings tab, in the left side menu bar there is an option `Manage access`, there you can add the collaborators for your project.
|
||||
|
||||
### The README.md file
|
||||
|
||||
The `README.md` file is an essential part of each project. The `.md` extension stands for Markdown.
|
||||
|
||||
You can think of the `README.md` file as the introduction to your repository. It's beneficial because while looking at someone's repo, you can just scroll down to their README file and have a look at what their project is all about.
|
||||
|
||||
And it is crucial that your project is properly introduced. Because if the project itself isn't introduced properly, no one will spend their time helping to improve it and try to develop it further.
|
||||
|
||||
That's why having a good README file is necessary and it shouldn't be overlooked, and you should spend a considerable amount of your time on it.
|
||||
|
||||
In this post, I am going to share some tips with you about how you can improve your README file, and hopefully, it will help you with your repositories.
|
||||
|
||||
For more information, make sure to check out this post on [how to write a good README.md file](https://devdojo.com/bobbyiliev/quick-tips-for-writing-a-good-readme-file).
|
||||
|
||||
## GitHub Stars
|
||||
|
||||
Let's start by answering the question why do we star a repository?
|
||||
|
||||
Firstly people star a repository for later use or maybe just to keep track of it. I would basically star a repository because I might be needing it for later use.
|
||||
|
||||
For instance repository like the [introduction-to-git-and-github-ebook](https://github.com/bobbyiliev/introduction-to-git-and-github-ebook) is essential because you might get stuck on Git as a beginner and you can just simply refer to it easily.
|
||||
|
||||
And secondly its used to show support to the creator and the maintainers of the repository.
|
||||
|
||||
So lets use this eBook [introduction-to-git-and-github-ebook](https://github.com/bobbyiliev/introduction-to-git-and-github-ebook) as an example to actually star a repository.
|
||||
|
||||
You have visit GitHub and find the [introduction-to-git-and-github-ebook](https://github.com/bobbyiliev/introduction-to-git-and-github-ebook) reposotory via the search, or access the repository directly at:
|
||||
|
||||
[https://github.com/bobbyiliev/introduction-to-git-and-github-ebook](https://github.com/bobbyiliev/introduction-to-git-and-github-ebook)
|
||||
|
||||

|
||||
|
||||
Now while you are on the repository page on GitHub, at the top of the page where the `USERNAME/THE REPOSITORY NAME` lies, you will find some couple of icon:
|
||||
|
||||

|
||||
|
||||
Click on the star icon and you have successfuly starred the project.
|
||||
|
||||
Whenever you like a project and want to suport the creator, make sure to click star the repository! Just like you would enjoy a video on YouTube and hit the like button.
|
||||
37
docs/007-initializing-a-project.md
Normal file
37
docs/007-initializing-a-project.md
Normal file
@@ -0,0 +1,37 @@
|
||||
# Initializing a Git project
|
||||
|
||||
If you are starting a new project or if you have an existing project which you would like to add to Git and then push to GitHub, you need to initialize a new Git project with the `git init` command.
|
||||
|
||||
To keep things simple, let's say that we want to start building a fresh new project. The first thing that I would usually do is to create a new folder where I would store my project files at. To do that, I can use the `mkdir` command followed by the name of the folder, which will create a new empty directory/folder:
|
||||
|
||||
```bash
|
||||
mkdir new-project
|
||||
```
|
||||
|
||||
The above command will create a folder called `new-project`. Then as we learned in chapter 4, we can use the `cd` command to access the directory:
|
||||
|
||||
```bash
|
||||
cd new-project
|
||||
```
|
||||
|
||||
After that, by using the `ls` command, we will be able to verify that the directory is completely empty:
|
||||
|
||||
```bash
|
||||
ls -lah
|
||||
```
|
||||
|
||||
Then with that, we are ready to initialize a new Git project:
|
||||
|
||||
```bash
|
||||
git init
|
||||
```
|
||||
|
||||
You will get the following output:
|
||||
|
||||
```
|
||||
Initialized empty Git repository in /home/devdojo/new-project/.git/
|
||||
```
|
||||
|
||||
As you can see, what the `git init` command does is to create a new `.git` folder which we already discussed in chapter 5.
|
||||
|
||||
With that, you've successfully created a new empty Git project! Let's move to the next chapter, where you will learn how to use the `git status` command to check the current status of your repository.
|
||||
34
docs/008-git-status.md
Normal file
34
docs/008-git-status.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# Git Status
|
||||
|
||||
Whenever you make changes to your Git project, you would want to verify what has changed before making a commit or before pushing your changes to GitHub, for example.
|
||||
|
||||
To check the current status of your project, you can use the `git status` command. If you run the `git status` command in the same directory where you initialized your Git project from the last chapter, you will see the following output:
|
||||
|
||||
```
|
||||
On branch main
|
||||
|
||||
No commits yet
|
||||
|
||||
nothing to commit (create/copy files and use "git add" to track)
|
||||
```
|
||||
|
||||
As this is a fresh new repository, there are no commits and no changes yet. So let's go ahead and create a `README.md` file with some generic content. We can run the following command to do so:
|
||||
|
||||
```bash
|
||||
echo "# Demo Project" >> README.md
|
||||
```
|
||||
|
||||
What this would do is to output the `# Demo Project` and store it in the `README.md` file.
|
||||
|
||||
If you run `git status` again, you will then see the following output:
|
||||
|
||||
```
|
||||
Untracked files:
|
||||
(use "git add <file>..." to include in what will be committed)
|
||||
README.md
|
||||
nothing added to commit but untracked files present (use "git add" to track)
|
||||
```
|
||||
|
||||
As you can see, Git is detecting that there is 1 new file that is not tracked at the moment called `README.md`, which we just created. And already, Git is prompting us to use the `git add` command to start tracking the file. We will learn more about the `git add` command in the next chapter!
|
||||
|
||||
We are going to be using the `git status` command throughout the next few chapters a lot! This is particularly helpful, especially when you've modified a lot of files and you want to check the current status and see all of the modified, updated, or deleted files.
|
||||
43
docs/009-git-add.md
Normal file
43
docs/009-git-add.md
Normal file
@@ -0,0 +1,43 @@
|
||||
# Git Add
|
||||
|
||||
By default, when you create a new file inside your Git project, it is not being tracked by Git. So to tell git that it should start tracking the file, you need to use the `git add` command.
|
||||
|
||||
The syntax is the following:
|
||||
|
||||
```bash
|
||||
git add NAME_OF_FILE
|
||||
```
|
||||
|
||||
In our case, we have only 1 filed inside our project called `README.md`, so to add this file to Git, we can use the following command:
|
||||
|
||||
```bash
|
||||
git add README.md
|
||||
```
|
||||
|
||||
If you then run `git status` again, you will see a different output:
|
||||
|
||||
```
|
||||
Changes to be committed:
|
||||
(use "git rm --cached <file>..." to unstage)
|
||||
new file: README.md
|
||||
```
|
||||
|
||||
Here you would see that there are now some changes staged and ready to be committed. Also, Git tells us that the `README.md` is a new file that was just staged and has not been tracked before.
|
||||
|
||||
In case that you have a couple of files, you could list them all divided by space after the `git add` command to stage them all rather than running `git add` multiple times for each individual file:
|
||||
|
||||
```bash
|
||||
git add file1.html file2.html file3.html
|
||||
```
|
||||
|
||||
With the above, we will add the 3 files by running `git add` just once, however in some cases, you might have a lot of new files, and adding them one by one could be highly time-consuming.
|
||||
|
||||
So there is a way to stage absolutely all files in your current project, and this is by specifying a dot after the `git add` command as follows:
|
||||
|
||||
```bash
|
||||
git add .
|
||||
```
|
||||
|
||||
> Note: You need to be careful with this as in some cases, there might be some files that you don't want to add to Git.
|
||||
|
||||
With that, we are ready to move on and learn about the `git commit` command.
|
||||
123
docs/010-git-commit.md
Normal file
123
docs/010-git-commit.md
Normal file
@@ -0,0 +1,123 @@
|
||||
# Git Commit
|
||||
|
||||
Once you have added/staged your files, the next step is actually to commit the changes. So if you run `git status` again, you will be able to see that Git tells us that there are changes to be committed:
|
||||
|
||||
```
|
||||
Changes to be committed:
|
||||
(use "git rm --cached <file>..." to unstage)
|
||||
new file: README.md
|
||||
```
|
||||
|
||||
In this case, it is only the `README.md` file that will be committed. So in order to do so, we can run the following command:
|
||||
|
||||
```bash
|
||||
git commit -m "Your Commit Message Here"
|
||||
```
|
||||
|
||||
Rundown of the command:
|
||||
|
||||
* `git commit`: here, we are telling git that we want to commit the changes that we've staged with the `git add` command
|
||||
* `-m`: this flag indicates that we will specify our commit message directly after that
|
||||
* Finally, in the quotes we've got our commit message, it is important to write short and descriptive commit messages
|
||||
|
||||
In our case we could set our commit message to something like `"Initial commit"` or `"Add README.md"` file, for example.
|
||||
|
||||
If you don't specify the `-m` flag, Git will open the default text editor that we've configured in chapter 5 where you will be able to type the commit message directly.
|
||||
|
||||
Committing directly without staging files:
|
||||
|
||||
If you have not already staged your changes using `git add` command you can still directly commit all your changes using the following command.
|
||||
```
|
||||
git commit -a -m "Your Commit Message Here"
|
||||
```
|
||||
The `-a` flag here will automatically stage all the changes and commit them.
|
||||
|
||||
## Signing Commits
|
||||
Git allows you to sign your commits. Commits signed with a verified signature in GitHub and GitLab display a verified label as shown below.
|
||||

|
||||

|
||||
|
||||
To sign commits, first you need to:
|
||||
* make sure that you have GNU GPG installed on your host.
|
||||
* Generate a GPG signing key pair if you don't already have
|
||||
```bash
|
||||
gpg --full-generate-key
|
||||
```
|
||||
* Use the `gpg --list-secret-keys --keyid-format=long` command to list the long form of the GPG keys
|
||||
```bash
|
||||
gpg --list-secret-keys --keyid-format=long
|
||||
/Users/bobby/.gnupg/pubring.kbx
|
||||
---------------------------------
|
||||
sec rsa4096/E630A0A00CAA7AAA 2021-10-01 [SC] [expires: 2026-10-01]
|
||||
5F1F417F8A043C8888888888E630F6D35CFA7ECD
|
||||
uid [ultimate] Bobby Illiev (For signing git commits) <bobby@bobbyiliev.com>
|
||||
ssb rsa4096/46EE4AA180001AA6 2021-10-01 [E] [expires: 2026-10-01]
|
||||
```
|
||||
* Copy the long form of the GPG key ID you'd like to use. In this sample, the GPG key ID is `E630A0A00CAA7AAA`.
|
||||
* Export the public key:
|
||||
```bash
|
||||
gpg --armor --export E630A0A00CAA7AAA
|
||||
```
|
||||
* Copy your GPG key, beginning with `-----BEGIN PGP PUBLIC KEY BLOCK-----` and ending with `-----END PGP PUBLIC KEY BLOCK-----`.
|
||||
* Login to GitHub or GitLab and add a new GPG key under settings:
|
||||

|
||||

|
||||
* Set your GPG signing key in Git: (If you intend to add the signing key per repository, the omit the `--global` flag)
|
||||
```bash
|
||||
git config --global user.signingkey E630A0A00CAA7AAA
|
||||
```
|
||||
* Enable automatic signing for all commits:
|
||||
```bash
|
||||
git config --global commit.gpgsign true
|
||||
```
|
||||
* Or Sign per commit by passing `-S` option to `git commit`:
|
||||
```bash
|
||||
git commit -S -m "your commit message"
|
||||
```
|
||||
|
||||
After running the `git commit` command, we can use the `git status` command again to check the current status:
|
||||
|
||||
```bash
|
||||
git status
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
On branch main
|
||||
nothing to commit, working tree clean
|
||||
```
|
||||
|
||||
As you can see, Git is telling us that there are no changes to be committed as we've already committed them.
|
||||
|
||||
Let's go ahead and make another change to the `README.md` file. You can open the file with your favorite text editor and make the change directly, or you can run the following command:
|
||||
|
||||
```bash
|
||||
echo "Git is awesome!" >> README.md
|
||||
```
|
||||
|
||||
The above would add a new line at the bottom of the `README.md` file. So if we were to run `git status` again, we will see the following output:
|
||||
|
||||
```
|
||||
On branch main
|
||||
Changes not staged for commit:
|
||||
(use "git add <file>..." to update what will be committed)
|
||||
(use "git restore <file>..." to discard changes in working directory)
|
||||
modified: README.md
|
||||
|
||||
no changes added to commit (use "git add" and/or "git commit -a")
|
||||
```
|
||||
|
||||
As you can see, Git has detected that the `README.md` file has been modified and is also prompting us to use the command that we've learned to first stage/add the file!
|
||||
|
||||
In case that you wanted to change your last commit message, you can run the `git commit --amend` command. This will open the default editor where you can change your commit message. Also, this allows you to change the commit changes.
|
||||
|
||||
The `git status` command gives us a great overview of the files that have changed, but it does not show us what the changes actually are. In the next chapter, we are going to learn how to check the differences between the last commit and the current changes.
|
||||
|
||||
To check for commits that changed particular file you can use the `--follow` flag:
|
||||
|
||||
```bash
|
||||
git log --follow [file]
|
||||
```
|
||||
|
||||
The above shows the commits that changed the file, even across renames.
|
||||
62
docs/011-git-diff.md
Normal file
62
docs/011-git-diff.md
Normal file
@@ -0,0 +1,62 @@
|
||||
# Git Diff
|
||||
|
||||
As mentioned in the last chapter, the `git status` command gives us a great overview of the files that have changed, but it does not show us what the changes actually are.
|
||||
|
||||
You can check the actual changes that were made with the `git diff` command. If we were to run the command in our repository, we would see the following output:
|
||||
|
||||
```
|
||||
diff --git a/README.md b/README.md
|
||||
index 9366068..2b14655 100644
|
||||
--- a/README.md
|
||||
+++ b/README.md
|
||||
@@ -1 +1,2 @@
|
||||
# Demo Project
|
||||
+Git is awesome
|
||||
```
|
||||
|
||||
As we only changed the `README.md` file, Git is showing us the following:
|
||||
|
||||
* `diff --git a/README.md b/README.md`: here git indicates that it shows the changes made to the `README.md` file since the last commit compared to the current version of the file.
|
||||
* `@@ -1 +1,2 @@`: here git indicates that 1 new line was added
|
||||
* `+Git is awesome`: here, the important part is the `+`, which indicates that this is a new line that was added. In case that we remove a line, you would see a `-` sign instead.
|
||||
|
||||
In our case, as we only added 1 new line to the file, Git indicates that only 1 file was changed and that only 1 new line was added.
|
||||
|
||||
Next, let's go ahead and stage that change and commit it with the comments that we've learned from the previous chapters!
|
||||
|
||||
* Stage the changed file:
|
||||
|
||||
```bash
|
||||
git add README.md
|
||||
```
|
||||
|
||||
* Then again run `git status` to check the current status:
|
||||
|
||||
```bash
|
||||
git status
|
||||
```
|
||||
|
||||
The output would look like this, indicating that there is 1 modified file:
|
||||
|
||||
```
|
||||
On branch main
|
||||
Changes to be committed:
|
||||
(use "git restore --staged <file>..." to unstage)
|
||||
modified: README.md
|
||||
```
|
||||
|
||||
* Commit the changes:
|
||||
|
||||
```bash
|
||||
git commit -m "Update README.md"
|
||||
```
|
||||
|
||||
Finally, if you run `git status` again you will see that there are no changes to be committed.
|
||||
|
||||
I always run `git status` and `git diff` before making any commits, just so that I'm sure what has changed.
|
||||
|
||||
> Note 1 : `git diff --staged` will only show the changes to the file in "staged" area.
|
||||
|
||||
> Note 2 : `git diff HEAD` will show all changes to tracked files(file in last snapshot), if you have all the changes staged for commit then both the commands give same output.
|
||||
|
||||
In some cases, you would like to see a list of the previous commits. We will learn how to do that in the next chapter.
|
||||
67
docs/012-git-log.md
Normal file
67
docs/012-git-log.md
Normal file
@@ -0,0 +1,67 @@
|
||||
# Git Log
|
||||
|
||||
In order to list all of the previous commits, you can use the following command:
|
||||
|
||||
```bash
|
||||
git log
|
||||
```
|
||||
|
||||
This will provide you with your commit history, the output would look like this:
|
||||
|
||||
```
|
||||
commit da46ce39a3fd663ff802d013f834431d4b4159a5 (HEAD -> main)
|
||||
Author: Bobby Iliev <bobby@bobbyiliev.com>
|
||||
Date: Fri Mar 12 17:14:02 2021 +0000
|
||||
|
||||
Update README.md
|
||||
|
||||
commit fa583473b4be2807b45f35b755aa84ac78922259
|
||||
Author: Bobby Iliev <bobby@bobbyiliev.com>
|
||||
Date: Fri Mar 12 17:01:17 2021 +0000
|
||||
|
||||
Initial commit
|
||||
```
|
||||
|
||||
The entries are listed, in order, from most recent to oldest.
|
||||
|
||||
Rundown of the output:
|
||||
|
||||
* `commit da46ce39a3fd663ff802d013f834431d4b4159a5`: Here you can see the specific commit ID
|
||||
* `Author: Bobby Iliev... `: Then you can see who created the changes
|
||||
* `Date: Fri Mar 12...`: After that, you've got the exact time and date when the commit was created
|
||||
* Finally, you have the commit message. This is one of the reasons why it is important to write short and descriptive commit messages so that later on, you could tell what changes were introduced by the particular commit.
|
||||
|
||||
If you want to check the differences between the current state of your repository and a particular commit, what you could do is use the `git diff` command followed by the commit ID:
|
||||
|
||||
```bash
|
||||
git diff fa583473b4be2807b45f35b755aa84ac78922259
|
||||
```
|
||||
|
||||
In my case the output will be the following:
|
||||
|
||||
```
|
||||
diff --git a/README.md b/README.md
|
||||
index 9366068..2b14655 100644
|
||||
--- a/README.md
|
||||
+++ b/README.md
|
||||
@@ -1 +1,2 @@
|
||||
# Demo Project
|
||||
+Git is awesome
|
||||
```
|
||||
|
||||
So the difference between that specific commit and the current state of the repository is the change in the `README.md` file.
|
||||
|
||||
In case that you wanted to see only the commit IDs and commit messages on one line, you could add the `--oneline` argument:
|
||||
|
||||
```bash
|
||||
git log --oneline
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
* da46ce3 (HEAD -> main) Update README.md
|
||||
* fa58347 Initial commit
|
||||
```
|
||||
|
||||
With that, you now know how to check your commit history! Next, let's go ahead and learn how to exclude specific files from Git!
|
||||
279
docs/013-gitignore-file.md
Normal file
279
docs/013-gitignore-file.md
Normal file
@@ -0,0 +1,279 @@
|
||||
# Gitignore
|
||||
|
||||
While working on a Git repository, you will often have files and directories that you do not want to commit, so that they are not available to others using the repository.
|
||||
|
||||
In some cases, you might not want to commit some of your files to Git due to security reasons.
|
||||
|
||||
For example, if you have a config file that stores all of your database credentials and other sensitive information, you should never add it to Git and push it to GitHub as other people will be able to get hold of that sensitive information.
|
||||
|
||||
Another case where you may not want to commit a file or directory, is when those files are automatically generated and do not contain source code, so that you don't clutter your repository. Also, sometimes it makes sense not to commit certain files that contain environment information, so that other people can use your code with their environment files.
|
||||
|
||||
To prevent these types of files from being committed, you can create a `gitignore` file which includes a list of all of the files and directories that should be excluded from your Git repository. In this chapter, you will learn how to do that!
|
||||
|
||||
### Ignoring a specific file
|
||||
|
||||
Let's have a look at the following example if you had a `PHP` project and a file called `config.php`, which stores your database connection string details like username, password, host, etc.
|
||||
|
||||
To exclude that file from your git project, you could create a file called `.gitignore` inside your project's directory:
|
||||
|
||||
```bash
|
||||
touch .gitignore
|
||||
```
|
||||
|
||||
Then inside that file, all that you need to add is the name of the file that you want to ignore, so the content of the `.gitignore` file would look like this:
|
||||
|
||||
```
|
||||
config.php
|
||||
```
|
||||
|
||||
That way, the next time you run `git add .` and then run `git commit` and `git push`, the `config.php` file will be ignored and will not be added nor pushed to your Github repository.
|
||||
|
||||
That way, you would keep your database credentials safe!
|
||||
|
||||
### Ignoring a whole directory
|
||||
|
||||
In some cases, you might want to ignore a whole folder. For example, if you have a huge `node_modules` folder, there is no need to add it and commit it to your Git project, as that directory is generated automatically whenever you run `npm install`.
|
||||
|
||||
The same would go for the `vendor` folder in Laravel. You should not add the `vendor` folder to your Git project, as all of the content of that folder is generated automatically whenever you run `composer install`.
|
||||
|
||||
So to ignore the `vendors` and `node_modules` folders, you could just add them to your `.gitignore` file:
|
||||
|
||||
```
|
||||
# Ignored folders
|
||||
/vendor/
|
||||
node_modules/
|
||||
```
|
||||
### Ignoring a whole directory except for a specific file
|
||||
|
||||
Sometimes, you want to ignore a directory except for one or a couple of other files within that directory. It could be that the directory is required for your application to run but the files created is not supposed to be pushed to the remote repository or maybe you want to have a `README.md` file inside the directory for some purpose. To achieve this, your `.gitignore` file should like like this:
|
||||
|
||||
```
|
||||
data/*
|
||||
!data/README.md
|
||||
```
|
||||
|
||||
The first line indicates that you want to ignore the `data` directory and all files inside it. However, the second line provides the instruction that the `README.md` is an exception.
|
||||
|
||||
Take note that the ordering is important in this case. Otherwise, it will not work.
|
||||
|
||||
### Getting a gitignore file for Laravel
|
||||
|
||||
To get a `gitignore` file for Laravel, you could get the file from [the official Laravel Github repository] here(https://github.com/laravel/laravel/).
|
||||
|
||||
The file would look something like this:
|
||||
|
||||
```
|
||||
/node_modules
|
||||
/public/hot
|
||||
/public/storage
|
||||
/storage/*.key
|
||||
/vendor
|
||||
.env
|
||||
.env.backup
|
||||
.phpunit.result.cache
|
||||
Homestead.json
|
||||
Homestead.yaml
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
```
|
||||
|
||||
It essentially includes all of the files and folders that are not needed to get the application up and running.
|
||||
|
||||
### Using gitignore.io
|
||||
|
||||
As the number of frameworks and application grows day by day, it might be hard to keep your `.gitignore` files up to date or it could be intimidating if you had to search for the correct `.gitignore` file for every specific framework that you use.
|
||||
|
||||
I recently discovered an open-source project called [gitignore.io](https://www.toptal.com/developers/gitignore/). It is a site and a CLI tool with a huge list of predefined `gitignore` files for different frameworks.
|
||||
|
||||
All that you need to do is visit the site and search for the specific framework that you are using.
|
||||
|
||||
For example, let's search for a `.gitignore` file for Node.js:
|
||||
|
||||

|
||||
|
||||
Then just hit the **Create button** and you would instantly get a well documented `.gitignore` file for your Node.js project, which will look like this:
|
||||
|
||||
```
|
||||
# Created by https://www.toptal.com/developers/gitignore/api/node
|
||||
# Edit at https://www.toptal.com/developers/gitignore?templates=node
|
||||
|
||||
### Node ###
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# TypeScript v1 declaration files
|
||||
typings/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Microbundle cache
|
||||
.rpt2_cache/
|
||||
.rts2_cache_cjs/
|
||||
.rts2_cache_es/
|
||||
.rts2_cache_umd/
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
.env.test
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
|
||||
# Next.js build output
|
||||
.next
|
||||
|
||||
# Nuxt.js build / generate output
|
||||
.nuxt
|
||||
dist
|
||||
|
||||
# Gatsby files
|
||||
.cache/
|
||||
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||
# public
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
||||
# TernJS port file
|
||||
.tern-port
|
||||
|
||||
# Stores VSCode versions used for testing VSCode extensions
|
||||
.vscode-test
|
||||
|
||||
# End of https://www.toptal.com/developers/gitignore/api/node
|
||||
```
|
||||
|
||||
### Using gitignore.io CLI
|
||||
|
||||
If you are a fan of the command-line, the gitignore.io project offers a CLI version as well.
|
||||
|
||||
To get it installed on Linux, just run the following command:
|
||||
|
||||
```bash
|
||||
git config --global alias.ignore \
|
||||
'!gi() { curl -sL https://www.toptal.com/developers/gitignore/api/$@ ;}; gi'
|
||||
```
|
||||
|
||||
If you are using a different OS, I would recommend checking out the documentation [here](https://docs.gitignore.io/install/command-line) on how to get it installed for your specific Shell or OS.
|
||||
|
||||
Once you have the `gi` command installed, you could list all of the available `.gitignore` files from gitignore.io by running the following command:
|
||||
|
||||
```bash
|
||||
gi list
|
||||
```
|
||||
|
||||
For example, if you quickly needed a `.gitignore` file for Laravel, you could just run:
|
||||
|
||||
```bash
|
||||
gi laravel
|
||||
```
|
||||
|
||||
And you would get a response back with a well-documented Laravel `.gitignore` file:
|
||||
|
||||
```
|
||||
# Created by https://www.toptal.com/developers/gitignore/api/laravel
|
||||
# Edit at https://www.toptal.com/developers/gitignore?templates=laravel
|
||||
|
||||
### Laravel ###
|
||||
/vendor/
|
||||
node_modules/
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
|
||||
# Laravel 4 specific
|
||||
bootstrap/compiled.php
|
||||
app/storage/
|
||||
|
||||
# Laravel 5 & Lumen specific
|
||||
public/storage
|
||||
public/hot
|
||||
|
||||
# Laravel 5 & Lumen specific with changed public path
|
||||
public_html/storage
|
||||
public_html/hot
|
||||
|
||||
storage/*.key
|
||||
.env
|
||||
Homestead.yaml
|
||||
Homestead.json
|
||||
/.vagrant
|
||||
.phpunit.result.cache
|
||||
|
||||
# Laravel IDE helper
|
||||
*.meta.*
|
||||
_ide_*
|
||||
|
||||
# End of https://www.toptal.com/developers/gitignore/api/laravel
|
||||
```
|
||||
|
||||
### Conclusion
|
||||
|
||||
Having a `gitignore` file is essential, it is great that you could use a tool like the [gitignore.io](gitignore.io) to generate your `gitignore` file automatically, depending on your project!
|
||||
|
||||
If you like the gitignore.io project, make sure to check out and contribute to the project [here](https://github.com/toptal/gitignore.io).
|
||||
102
docs/014-ssh-keys.md
Normal file
102
docs/014-ssh-keys.md
Normal file
@@ -0,0 +1,102 @@
|
||||
# SSH Keys
|
||||
|
||||
There are a few ways to authenticate with GitHub. Essentially you would need this so that you could push your local changes from your laptop to your GitHub repository.
|
||||
|
||||
You could use one of the following methods:
|
||||
|
||||
* HTTPS: Essentially, this would require your GitHub username and password each time you try to push your changes
|
||||
* SSH: With SSH, you could generate an SSH Key pair and add your public key to GitHub. That way, you would not be asked for your username and password every time you push your changes to GitHub.
|
||||
|
||||

|
||||
|
||||
One thing that you need to keep in mind is that the GitHub repository URL is different depending on whether you are using SSH or HTTPS:
|
||||
|
||||
* HTTPS: `https://github.com/bobbyiliev/demo-repo.git`
|
||||
* SSH: `git@github.com:bobbyiliev/demo-repo.git`
|
||||
|
||||
Note that when you choose SSH, the `https://` part is changed with `git@`, and you have `:` after `github.com` rather than `/`. This is important as this defines how you would like to authenticate each time.
|
||||
|
||||
### Generating SSH Keys
|
||||
|
||||
To generate a new SSH key pair in case that you don't have one, you can run the following command:
|
||||
|
||||
```bash
|
||||
ssh-keygen
|
||||
```
|
||||
|
||||
For security reasons you can specify a passphrase, which essentially is the password for your private SSH key.
|
||||
|
||||
The above would generate 2 files:
|
||||
|
||||
* 1 **private** SSH key and 1 public SSH key. The private key should always be stored safely on your laptop, and you should not share it with anyone.
|
||||
* 1 **public** SSH key, which you need to upload to GitHub.
|
||||
|
||||
The two files will be automatically generated at the following folder:
|
||||
|
||||
```
|
||||
~/.ssh
|
||||
```
|
||||
|
||||
You can use the `cd` command to access the folder:
|
||||
|
||||
```bash
|
||||
cd ~/.ssh
|
||||
```
|
||||
|
||||
Then with `ls` you can check the content:
|
||||
|
||||
```bash
|
||||
ls
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
id_rsa id_rsa.pub
|
||||
```
|
||||
|
||||
The `id_rsa` is your private key, and again you should not share it with anyone.
|
||||
|
||||
The `id_rsa.pub` is the public key that would need to be uploaded to GitHub.
|
||||
|
||||
### Adding the public SSH key to GitHub
|
||||
|
||||
Once you've created your SSH keys, you need to upload the **public** SSH key to your GitHub account. To do so, you first need to get the content of the file.
|
||||
|
||||
To get the content of the file, you can use the `cat` command:
|
||||
|
||||
```bash
|
||||
cat ~/.ssh/id_rsa.pub
|
||||
```
|
||||
|
||||
The output will look like this:
|
||||
|
||||
```
|
||||
ssh-rsa AAB3NzaC1yc2EAAAADAQAB...... your_user@your_host
|
||||
```
|
||||
|
||||
Copy the whole thing and then visit [GitHub](https://github.com) and follow these steps:
|
||||
|
||||
* Click on your profile picture on the right top
|
||||
|
||||
* Then click on settings
|
||||
|
||||

|
||||
|
||||
* On the left, click on `SSH and GPG Keys`:
|
||||
|
||||

|
||||
|
||||
* After that, click on the `New SSH Key` button
|
||||
|
||||
* Then specify a title of the SSH key, it should be something descriptive, for example: `Work Laptop SSH Key`. And in the `Key` area, paste your public SSH key:
|
||||
|
||||

|
||||
|
||||
* Finally click the `Add SSH Key` button at the bottom of the page
|
||||
|
||||
### Conclusion
|
||||
|
||||
With that, you now have your SSH Keys generated and added to GitHub. That way, you will be able to push your changes without having to type your GitHub password and user each time.
|
||||
|
||||
For more information about SSH keys, make sure to check this tutorial [here](https://www.digitalocean.com/community/tutorials/how-to-set-up-ssh-keys-2).
|
||||
64
docs/015-git-push.md
Normal file
64
docs/015-git-push.md
Normal file
@@ -0,0 +1,64 @@
|
||||
# Git Push
|
||||
|
||||
Then finally, once you've made all of your changes, staged them with the `git add .` command, and committed the changes with the `git commit` command, you must push the committed changes from your local repository to your remote GitHub repository. This ensures that the remote repository is brought up-to-date with your local repository.
|
||||
|
||||
## Creating and Linking a Remote Repository
|
||||
|
||||
Before you can push to your remote GitHub repository, you need to first create your remote repository via GitHub as per Chapter 6.
|
||||
|
||||
Once you have your remote GitHub repository ready, you can add it to your local project with the following command:
|
||||
|
||||
```bash
|
||||
git remote add origin git@github.com:your_username/your_repo_name.git
|
||||
```
|
||||
|
||||
> Note: Make sure to change the `your_username` and `your_repo_name` details accordingly.
|
||||
|
||||
This is how you can link your local Git project with your remote GitHub repository.
|
||||
|
||||
If you've read the previous chapter, you will most likely notice we are using SSH as the authentication method.
|
||||
|
||||
However, if you did not follow the steps from the previous chapter, you can use HTTPS rather than SSH:
|
||||
|
||||
```bash
|
||||
git remote add origin https://github.com/your_username/your_repo_name.git
|
||||
```
|
||||
|
||||
To verify your remote repository, you can run the following command:
|
||||
|
||||
```bash
|
||||
git remote -v
|
||||
```
|
||||
|
||||
## Pushing Commits
|
||||
|
||||
To push your committed changes to the linked remote repository, you can use the `git push` command:
|
||||
|
||||
```bash
|
||||
git push -u origin main
|
||||
```
|
||||
> Note: In this command, `-u origin main` tells Git to set the main branch of the remote repository as the upstream branch within the `git push` command. This is the best practice when using Git as it allows the `git push` and `git pull` commands to work as intended. Alternatively, you can use `--set-upstream origin main` for this as well.
|
||||
|
||||
If you are using SSH with your SSH key uploaded to GitHub, the push command will not ask you for a password and will push your changes to GitHub straight away.
|
||||
|
||||
In case that you did not run the `git remote add` command as outlined in earlier in this chapter, you will receive the following error:
|
||||
|
||||
```
|
||||
fatal: 'origin' does not appear to be a git repository
|
||||
fatal: Could not read from remote repository.
|
||||
|
||||
Please make sure you have the correct access rights
|
||||
and the repository exists.
|
||||
```
|
||||
|
||||
This would mean that you've not added your GitHub repository as the remote repository. This is why we run the `git remote add` command to create that connection between your local repository and the remote GitHub repository.
|
||||
|
||||
Note that the connection would be in place if you used the `git clone` command to clone an existing repository from GitHub to your local machine. We will go through the `git pull` command in the next few chapters as well.
|
||||
|
||||
## Checking the Remote Repository
|
||||
|
||||
After running the `git push` command, you can head over to your GitHub project and you will be able to see the commits that you've made locally present in remote repository on GitHub. If you were to click on the `commits` link, you would be able to see all commits just as if you were to run the `git log` command:
|
||||
|
||||

|
||||
|
||||
Now that you know how to push your latest changes from your local Git project to your GitHub repository, it's time to learn how to pull the latest changes from GitHub to your local project.
|
||||
58
docs/016-git-pull.md
Normal file
58
docs/016-git-pull.md
Normal file
@@ -0,0 +1,58 @@
|
||||
# Git Pull
|
||||
|
||||
If you are working on a project with multiple people, the chances are that the codebase will change very often. So you would need to have a way to get the latest changes from the GitHub repository to your local machine.
|
||||
|
||||
You already know that you can use the `git push` command to push your latest commits, so to do the opposite and pull the latest commits from GitHub to your local project, you need to use the `git pull` command.
|
||||
|
||||
To test this, let's go ahead and make a change directly on GitHub directly. Once you are there, click on the `README.md` file and then click on the pencil icon to edit the file:
|
||||
|
||||

|
||||
|
||||
Make a minor change to the file, add a descriptive commit message and click on the `Commit Changes` button:
|
||||
|
||||

|
||||
|
||||
With that, you've now made a commit directly on GitHub, so your local repository will be behind the remote GitHub repository.
|
||||
|
||||
If you were to try and push a change now to that same branch, it would fail with the following error:
|
||||
|
||||
```
|
||||
! [rejected] main -> main (fetch first)
|
||||
error: failed to push some refs to 'git@github.com:bobbyiliev/demo-repo.git'
|
||||
hint: Updates were rejected because the remote contains work that you do
|
||||
hint: not have locally. This is usually caused by another repository pushing
|
||||
hint: to the same ref. You may want to first integrate the remote changes
|
||||
hint: (e.g., 'git pull ...') before pushing again.
|
||||
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
|
||||
```
|
||||
|
||||
As stated in the output, the remote repository is ahead of your local one, so you need to run the `git pull` command to get the latest changes:
|
||||
|
||||
```bash
|
||||
git pull origin main
|
||||
```
|
||||
|
||||
The output that you will get will look like this:
|
||||
|
||||
```
|
||||
remote: Enumerating objects: 5, done.
|
||||
remote: Counting objects: 100% (5/5), done.
|
||||
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
|
||||
Unpacking objects: 100% (3/3), 646 bytes | 646.00 KiB/s, done.
|
||||
From github.com:bobbyiliev/demo-repo
|
||||
* branch main -> FETCH_HEAD
|
||||
da46ce3..442afa5 main -> origin/main
|
||||
|
||||
README.md | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
```
|
||||
|
||||
We can see that the `README.md` file was changed and that there were 2 new lines added and 1 line deleted.
|
||||
|
||||
Now, if you were to run `git log`, you will see the commit that you've made on GitHub available locally.
|
||||
|
||||
Of course, this is a simplified scenario. In the real world, you would not make any changes directly to GitHub, but you would most likely work with other people on the same project, and you would have to pull their latest changes regularly.
|
||||
|
||||
You need to make sure that you pull the latest changes every time before you try to push your changes.
|
||||
|
||||
Now that you know the basic Git commands let's go ahead and learn what Git Branches are.
|
||||
193
docs/017-git-branching.md
Normal file
193
docs/017-git-branching.md
Normal file
@@ -0,0 +1,193 @@
|
||||
# Git Branches
|
||||
|
||||
So far, we have been working only on our Main branch, which is created by default when creating a new GitHub repository. In this chapter, you will learn more about Git Branches. Why you need them and how to work with them.
|
||||
|
||||
The official definition of a Git branch from the git-scm.com website is the following:
|
||||
|
||||
> A branch in Git is simply a lightweight movable pointer to one of these commits.
|
||||
|
||||
This might be a bit confusing in case that you are just getting started. So you could think of branches as a way to work on your project by adding a new feature of bug fixes without affecting the Main branch.
|
||||
|
||||
That way, each new feature or bug fix that you are developing could live on a separate branch, and later on, once you are ready and have fully tested the changes, you can merge the new branch to your main branch. You will learn more about merging in the next chapter!
|
||||
|
||||
If we look into the following illustration where we have a few branches, you can see that it looks like a tree, hence the term branching:
|
||||
|
||||

|
||||
|
||||
Thanks to the multiple branches, you can have multiple people working on different features or fixes at the same time each one working on their own branch.
|
||||
|
||||
The image shows 3 branches:
|
||||
|
||||
* The main branch
|
||||
* New Branch 1
|
||||
* New Branch 2
|
||||
|
||||
The main branch is the default branch that you are already familiar with. We can consider the other two branches as two new features that are being developed. One developer could be working on a new contact form for your web application on branch #1, and another developer could be working on a user registration form feature on branch #2.
|
||||
|
||||
Thanks to the separate branches, both developers can work on the same project without getting into each others way.
|
||||
|
||||
Next, let's go ahead and learn how to create new branches and see this in action!
|
||||
|
||||
### Creating a new branch
|
||||
|
||||
Let's start by creating a new branch called `newFeature`. In order to create the branch, you could use the following command:
|
||||
|
||||
```bash
|
||||
git branch newFeature
|
||||
```
|
||||
|
||||
Now, in order to switch to that new branch, you would need to run the following command:
|
||||
|
||||
```bash
|
||||
git checkout newFeature
|
||||
```
|
||||
|
||||
> Note: You can use the `git checkout` command to switch between different branches.
|
||||
|
||||
The above two commands could be combined into 1, so that you don't have to create the branch first and then switch to the new branch. You could use this command instead, which would do both:
|
||||
|
||||
```bash
|
||||
git checkout -b newFeature
|
||||
```
|
||||
|
||||
Once you run this command, you will see the following output:
|
||||
|
||||
```
|
||||
Switched to a new branch 'newFeature'
|
||||
```
|
||||
|
||||
In order to check what branch you are currently on, you can use the following command:
|
||||
|
||||
```bash
|
||||
git branch
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
main
|
||||
* newFeature
|
||||
```
|
||||
|
||||
We can tell that we have 2 branches: the `main` one and the `newFeature` one that we just created. The star before the `newFeature` branch name indicates that we are currently on the `newFeature` branch.
|
||||
|
||||
If you were to use the `git checkout` command to switch to the `main` branch:
|
||||
|
||||
```bash
|
||||
git checkout main
|
||||
```
|
||||
|
||||
And then run `git branch` again. You will see the following output indicating that you are now on the `main` branch:
|
||||
|
||||
```
|
||||
* main
|
||||
newFeature
|
||||
```
|
||||
|
||||
### Making changes to the new branch
|
||||
|
||||
Now let's go ahead and make a change on the new feature branch. First switch to the branch with the `git checkout` command:
|
||||
|
||||
```bash
|
||||
git checkout newFeature
|
||||
```
|
||||
|
||||
> Note: we only need to add the `-b` argument when creating new branches
|
||||
|
||||
Check that you've actually switched to the correct branch:
|
||||
|
||||
```bash
|
||||
git branch
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
main
|
||||
* newFeature
|
||||
```
|
||||
|
||||
Now let's create a new file with some demo content. You can do that with the following command:
|
||||
|
||||
```bash
|
||||
echo "<h1>My First Feature Branch</h1>" > feature1.html
|
||||
```
|
||||
|
||||
The above will echo out the `<h1>My First Feature Branch</h1>` string and store it in a new file called `feature1.html`.
|
||||
|
||||
After that, stage the file and commit the change:
|
||||
|
||||
```bash
|
||||
git add feature1.html
|
||||
git commit -m "Add feature1.html"
|
||||
```
|
||||
|
||||
The new `feature1.html` file will only be present on the `newFeature` branch. If you were to switch to the `main` branch and run the `ls` command or check the `git log`, you will be able to see that the file is not there.
|
||||
|
||||
You can check that by using the `git log` command:
|
||||
|
||||
```bash
|
||||
git log
|
||||
```
|
||||
|
||||
With that, we've used quite a bit of the commands that we've covered in the previous chapters!
|
||||
|
||||
### Compare branches
|
||||
|
||||
You can also compare two branches with the following commands.
|
||||
|
||||
* Shows the commits on `branchA` that are not on `branchB`:
|
||||
|
||||
```bash
|
||||
git log BranchA..BranchB
|
||||
```
|
||||
|
||||
* Shows the difference of what is in `branchA` but not in `branchB`:
|
||||
|
||||
```bash
|
||||
git diff BranchB...BranchA
|
||||
```
|
||||
|
||||
### Renaming a branch
|
||||
|
||||
In case that you've created a branch with the wrong name or if you think that the name could be improved as it is not descriptive enough, you can rename a branch by running the following command:
|
||||
|
||||
```bash
|
||||
git branch -m wrong-branch-name correct-branch-name
|
||||
```
|
||||
|
||||
If you want to rename your **current branch**, you could just run the following:
|
||||
|
||||
```bash
|
||||
git branch -m my-branch-name
|
||||
```
|
||||
|
||||
After that, if you run `git branch` again you will be able to see the correct branch name.
|
||||
|
||||
### Deleting a branch
|
||||
|
||||
If you wanted to completely delete a specific branch you could run the following command:
|
||||
|
||||
```bash
|
||||
git branch -d name_of_the_branch
|
||||
```
|
||||
|
||||
This would only delete the branch from your local repository, in case that you've already pushed the branch to GitHub, you can use the following command to delete the remote branch:
|
||||
|
||||
```bash
|
||||
git push origin --delete name_of_the_branch
|
||||
```
|
||||
|
||||
If you wanted to synchronize your local branches with the remote branches you could run the following command:
|
||||
|
||||
```bash
|
||||
git fetch
|
||||
```
|
||||
|
||||
### Conclusion
|
||||
|
||||
With that, our `newFeature` branch is now ahead of the main branch with 1 commit. So in order to get that new changes over to the main branch, we need to merge the `newFeature` branch into our `main` branch.
|
||||
|
||||
In the next chapter, you will learn how to merge your changes from one branch to another!
|
||||
|
||||
One thing that you might want to keep in mind is that in the past when creating a new GitHub repository the default branch name was called `master`. However, new repositories created on GitHub use `main` instead of `master` as the default branch name. This is part of GitHub's effort to remove unnecessary references to slavery and replace them with more inclusive terms.
|
||||
160
docs/018-git-merge.md
Normal file
160
docs/018-git-merge.md
Normal file
@@ -0,0 +1,160 @@
|
||||
# Git Merge
|
||||
|
||||
Once the developers are ready with their changes, they can merge their feature branches into the main branch and make those features live on the website.
|
||||
|
||||

|
||||
|
||||
If you followed the steps from the previous chapter, then your `newFeature` branch is now ahead of the main branch with 1 commit. So in order to get that new changes over to the main branch, we need to merge the `newFeature` branch into our `main` branch.
|
||||
|
||||
### Merging a branch
|
||||
|
||||
You can do that by following these steps:
|
||||
|
||||
* First switch to your `main` branch:
|
||||
|
||||
```bash
|
||||
git checkout main
|
||||
```
|
||||
|
||||
* After that, in order to merge your `newFeature` branch and the changes that we created in the last chapter, run the following `git merge` command:
|
||||
|
||||
```bash
|
||||
git merge newFeature
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
Updating ab1007b..a281d25
|
||||
Fast-forward
|
||||
feature1.html | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
create mode 100644 feature1.html
|
||||
```
|
||||
|
||||
As you were on the `main` branch when you ran the `git merge` command, Git will take all of the commits from that branch and merge them into the `main` branch.
|
||||
|
||||
Now, if you run the `ls` command, you will be able to see the new `feature1.html` file, and if you check the commit history with the `git log` command, you will see the commit from the `newFeature` branch present on your `main` branch.
|
||||
|
||||
Before doing the merge, you could again use the `git diff` command to check the differences between your current branch and the branch that you want to merge. For example, if you are currently on the `main` branch, you could use the following:
|
||||
|
||||
```bash
|
||||
git diff newFeature
|
||||
```
|
||||
|
||||
In this case, the merge went through smoothly as there were no merge conflicts. However, if you are working on a real project with multiple people making changes, there might be some merge conflicts. Essentially this happens when changes are made to the same line of a file, or when one developer edits a file on one branch and another developer deletes the same file.
|
||||
|
||||
### Resolving conflicts
|
||||
|
||||
Let's simulate a conflict. To do so, create a new branch:
|
||||
|
||||
```bash
|
||||
git checkout -b conflictDemo
|
||||
```
|
||||
|
||||
Then edit the `feature1.html` file:
|
||||
|
||||
```bash
|
||||
echo "<p>Conflict Demo</p>" >> feature1.html
|
||||
```
|
||||
|
||||
The command above will echo out the `<p>Conflict Demo</p>` string, and thanks to the double grater sign `>>`, the string will be added to the bottom of the `feature1.html` file. You can check the content of the file with the `cat` command:
|
||||
|
||||
```bash
|
||||
cat feature1.html
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
<h1>My First Feature Branch</h1>
|
||||
<p>Conflict Demo</p>
|
||||
```
|
||||
|
||||
You can again run `git status` and `git diff` to check what exactly has been modified before committing.
|
||||
|
||||
After that, go ahead and commit the change:
|
||||
|
||||
```bash
|
||||
git commit -am "Conflict Demo 1"
|
||||
```
|
||||
|
||||
Note that we did not run the `git add` command, but instead, we used the `-a` flag, which stands for `add`. You can do that for files that have been added to git and have just been modified. If you've added a new file, then you would have to stage it first with the `git add` command.
|
||||
|
||||
Now go switch back to your `main` branch:
|
||||
|
||||
```bash
|
||||
git checkout main
|
||||
```
|
||||
|
||||
And now, if you check the `feature1.html` file, it will only have the `<h1>My First Feature Branch</h1>` line as the change that we made is still only present on the `conflictDemo` branch.
|
||||
|
||||
Now let's go ahead and make a change to the same file:
|
||||
|
||||
```bash
|
||||
echo "<p>Conflict: change on main branch</p>" >> feature1.html
|
||||
```
|
||||
|
||||
Now we are adding again a line to the bottom of the `feature1.html` file with different content.
|
||||
|
||||
Go ahead and stage this and commit the change:
|
||||
|
||||
```bash
|
||||
git commit -am "Conflict on main"
|
||||
```
|
||||
|
||||
Now your `main` branch and the `conflictDemo` branch have changes to the same file, on the same line. So let's run the `git merge` command and see what happens:
|
||||
|
||||
```bash
|
||||
git merge conflictDemo
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
Auto-merging feature1.html
|
||||
CONFLICT (content): Merge conflict in feature1.html
|
||||
Automatic merge failed; fix conflicts and then commit the result.
|
||||
```
|
||||
|
||||
As we can see from the output, the merge is failing as there were changes to the same file on the same line, so Git is unsure which is the correct change.
|
||||
|
||||
As always, there are multiple ways to fix conflicts. Here we will go through one.
|
||||
|
||||
Now if you were to check the content of the `feature1.html` file you will see the following output:
|
||||
|
||||
```
|
||||
<h1>My First Feature Branch</h1>
|
||||
<<<<<<< HEAD
|
||||
<p>Conflict: change on main branch</p>
|
||||
=======
|
||||
<p>Conflict Demo</p>
|
||||
>>>>>>> conflictDemo
|
||||
```
|
||||
|
||||
Initially, it could be a little bit overwhelming, but let's quickly review it:
|
||||
|
||||
* `<<<<<<< HEAD`: this part here indicates the start of the changes on your current branch. In our case, the `<p>Conflict: change on main branch</p>` line is present on the `main` branch, which is also the branch that we've currently switched to.
|
||||
* `=======`: this line indicates where the changes from the current branch end and where the changes from the new branch are coming from. In our case, the change from the new branch is the `<p>Conflict Demo</p>` line.
|
||||
* `>>>>>>> conflictDemo`: this indicates the name of the branch that the changes are coming from.
|
||||
|
||||
You can resolve the conflict by manually removing the lines that are not needed, so at the end, the file will look like this:
|
||||
|
||||
```
|
||||
<h1>My First Feature Branch</h1>
|
||||
<p>Conflict: change on main branch</p>
|
||||
```
|
||||
|
||||
In case that you are using an IDE like VS Code, for example, it will allow you to choose which changes to keep with a click of a button.
|
||||
|
||||
After resolving the conflict, you will need to make another commit as the conflict is now resolved:
|
||||
|
||||
```bash
|
||||
git commit -am "Resolve merge conflict"
|
||||
```
|
||||
|
||||
### Conclusion
|
||||
|
||||
Git branches and merges allow you to work on a project together with other people. One important thing to keep in mind is to make sure that you pull the changes to your local `main` branch on a regular basis so that it does not get behind the remote one.
|
||||
|
||||
A few more commands which you might find useful once you feel comfortable with what we've covered so far are the `git rebase` command and the `git cherry-pick` command, which lets you pick which commits from a specific branch you would like to carry over to your current branch.
|
||||
76
docs/019-undoing-in-git.md
Normal file
76
docs/019-undoing-in-git.md
Normal file
@@ -0,0 +1,76 @@
|
||||
# Reverting changes
|
||||
|
||||
As with everything, there are multiple ways to do a specific thing. But what I would usually do in this case I want to undo my latest commit and then commit my new changes is the following.
|
||||
|
||||
* Let's say that you made some changes and you committed the changes:
|
||||
|
||||
```bash
|
||||
git commit -m "Committing the wrong changes"
|
||||
```
|
||||
|
||||
* After that if you run `git log`, you will see the history of everything that has been committed to a repository.
|
||||
|
||||
* Unfortunately, after you commit the wrong changes, you realize that you forget to add files to the commit or forget to add a small change to committed files.
|
||||
|
||||
* To solve that all you need to do is make these changes and stage them by running` git add` then you can `amend` the last commit by running the following command:
|
||||
|
||||
```bash
|
||||
git commit --amend
|
||||
```
|
||||
|
||||
**Note:** The above command will also let you change the commit message if you need.
|
||||
|
||||
|
||||
## Resetting Changes (⚠️ Resetting Is Dangerous ⚠️)
|
||||
|
||||
> You need to be careful with resetting commands because this command will erase commits from the repository and delete it from the history.
|
||||
|
||||
Example:
|
||||
```bash
|
||||
git reset --soft HEAD~1
|
||||
```
|
||||
|
||||
The above command will reset back with 1 point.
|
||||
|
||||
**Note:** the above would undo your commit, but it would keep your code changes if you would like to get rid of the changes as well, you need to do a hard reset: `git reset --hard HEAD~1`
|
||||
|
||||
Syntax:
|
||||
```bash
|
||||
git reset [--soft|--hard] [<reference-to-commit>]
|
||||
```
|
||||
|
||||
* After that, make your new changes
|
||||
|
||||
* Once you are done with the changes, run `git add` to add any of the files that you would like to be included in the next commit:
|
||||
|
||||
```bash
|
||||
git add .
|
||||
```
|
||||
|
||||
* Then use `git commit` as normal to commit your new changes:
|
||||
|
||||
```bash
|
||||
git commit -m "Your new commit message"
|
||||
```
|
||||
|
||||
* After that, you could again check your history by running:
|
||||
|
||||
```bash
|
||||
git log
|
||||
```
|
||||
|
||||
Here's a screenshot of the process:
|
||||
|
||||

|
||||
|
||||
**Note:** You can reset your changes by more than one commit by using the following syntax:
|
||||
```bash
|
||||
git reset --soft HEAD~n
|
||||
```
|
||||
where `n` is the number of commits you want to reset back.
|
||||
|
||||
Another approach would be to use `git revert COMMIT_ID` instead.
|
||||
|
||||
Here is a quick video demo on how to do the above:
|
||||
|
||||
[Reverting changes](https://www.youtube.com/watch?v=54Hy6KnfbuY)
|
||||
39
docs/020-git-clone.md
Normal file
39
docs/020-git-clone.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# Git Clone
|
||||
|
||||
More often than not, rather than starting a new project from scratch, you would either join a company and start working on an existing project, or you would contribute to an already established open source project. So in this case, in order to get the repository from GitHub to your local machine, you would need to use the `git clone` command.
|
||||
|
||||
The most straightforward way to clone your GitHub repository is to first visit the repository in your browser, and then click on the green `Code` button and choose the method that you want to use to clone the repository:
|
||||
|
||||

|
||||
|
||||
In my case, I would go for the SSH method as I already have my SSH keys configured as per chapter 14.
|
||||
|
||||
As I am cloning this repository [here](https://github.com/bobbyiliev/introduction-to-bash-scripting), the URL would look like this:
|
||||
|
||||
```
|
||||
git@github.com:bobbyiliev/introduction-to-bash-scripting.git
|
||||
```
|
||||
|
||||
Once you have this in my clipboard, head back to your terminal, go to a directory where you would like to clone the repository to and then run the following command:
|
||||
|
||||
```bash
|
||||
git clone git@github.com:bobbyiliev/introduction-to-bash-scripting.git
|
||||
```
|
||||
|
||||
The output that you would get will look like this:
|
||||
|
||||
```
|
||||
Cloning into 'introduction-to-bash-scripting'...
|
||||
remote: Enumerating objects: 21, done.
|
||||
remote: Counting objects: 100% (21/21), done.
|
||||
remote: Compressing objects: 100% (16/16), done.
|
||||
remote: Total 215 (delta 7), reused 14 (delta 4), pack-reused 194
|
||||
Receiving objects: 100% (215/215), 3.08 MiB | 5.38 MiB/s, done.
|
||||
Resolving deltas: 100% (114/114), done.
|
||||
```
|
||||
|
||||
Essentially what the `git clone` command does is to more or less download the repository from GitHub to your local folder.
|
||||
|
||||
Now you can start making the changes to the project by creating a new branch, writing some code, and finally committing and pushing your changes!
|
||||
|
||||
One important thing to keep in mind is that in case that you are not the maintainer of the repository and do not have the right to push to the repository, you would need to first fork the original repository and then clone the forked repository from your account. In the next chapter, we will go through the full process of forking a repository!
|
||||
35
docs/021-forking-in-git.md
Normal file
35
docs/021-forking-in-git.md
Normal file
@@ -0,0 +1,35 @@
|
||||
# Forking in Git
|
||||
|
||||
When contributing to an open-source project, you will not be able to make the changes directly to the project. Only the repository maintainers have that privilege.
|
||||
|
||||
What you need to do instead is to fork the specific repository, make the changes to the forked project and then submit a pull request to the original project. You will learn more about pull requests in the next chapters.
|
||||
|
||||
If you clone a repository that you don't have the access to and then try to push the changes directly to that repository, you would get the following error:
|
||||
|
||||
```
|
||||
ERROR: Permission to laravel/laravel.git denied to bobbyiliev.
|
||||
Fatal: Could not read from remote repository.
|
||||
|
||||
Please make sure you have the correct access rights
|
||||
and the repository exists.
|
||||
```
|
||||
|
||||
This is where Forks come into play!
|
||||
|
||||
In order to fork a repository, you need to visit the repository via your browser and click on the Fork button on the top right:
|
||||
|
||||

|
||||
|
||||
Then choose the account that you want to fork the repository to:
|
||||
|
||||

|
||||
|
||||
Then it might take a few seconds for the repository to be forked under your account:
|
||||
|
||||

|
||||
|
||||
With that, you would have an exact copy of the repository in question under your account.
|
||||
|
||||
The benefit here is that you can now clone the forked repository under your account, make the changes to that repository as normal, and then once you are ready, you can submit a pull request to the original repository contributing your changes.
|
||||
|
||||
As we've now mentioned submitting pull requests a few times already, let's go ahead and learn more about pull requests in the next chapter!
|
||||
29
docs/022-git-workflow.md
Normal file
29
docs/022-git-workflow.md
Normal file
@@ -0,0 +1,29 @@
|
||||
# Git Workflow
|
||||
|
||||
Now that you know the basic commands, let's put it all together and go through a basic Git workflow.
|
||||
|
||||
Usually, the workflow looks something like this:
|
||||
|
||||
* First, you clone an existing project with the `git clone` command, or if you are starting a new project, you initialize it with the `git init` command.
|
||||
|
||||
* After that, before starting with your code changes, it's best to create a new Git branch where you would work on. You can do that with the `git checkout -b YOUR_BRANCH_NAME` command.
|
||||
|
||||
* Once you have your branch ready, you would start making the changes to your code.
|
||||
|
||||
* Then, once you are ready with the changes, you need to stage them with the `git add` command.
|
||||
|
||||
* Then, to commit/save the changes to your local Git repository, you need to run the `git commit` command and provide a descriptive commit message.
|
||||
|
||||
* To push your local changes to your remote GitHub project, you would use the `git push origin YOUR_BRANCH_NAME` command
|
||||
|
||||
* Finally, once you've pushed your changes, you would need to submit a pull request (PR) from your branch to the main branch of the repository.
|
||||
|
||||
* It is considered good practice to add a couple of people as reviewers and ask them to review the changes.
|
||||
|
||||
* Finally, once the changes have been approved, the PR would get merged into the main branch taking all of your changes from your branch into the main branch.
|
||||
|
||||
The overall process will look like this:
|
||||
|
||||

|
||||
|
||||
My advice is to create a new repository and go over this process a few times until you feel completely comfortable with all of the commands.
|
||||
55
docs/023-pull-requests.md
Normal file
55
docs/023-pull-requests.md
Normal file
@@ -0,0 +1,55 @@
|
||||
# Pull Requests
|
||||
|
||||
You already know how to merge changes from one branch to another on your local Git repository.
|
||||
|
||||
To do the same thing on GitHub, you would need to open a Pull Request (or a Merge Request if you are using GitLab) or a PR for short and request a merge from your feature branch to the `main` branch.
|
||||
|
||||
The steps that you would need to take to open a Pull Request are:
|
||||
|
||||
* If you are working on an open-source project that you are not the maintainer of, first fork the repository as per chapter 21. Skip this step if you are the maintainer of the repository.
|
||||
* Then clone the repository locally with the `git clone` command:
|
||||
|
||||
```bash
|
||||
git clone git@github.com:your_user/your_repo
|
||||
```
|
||||
|
||||
* Create a new branch with the `git checkout` command:
|
||||
|
||||
```bash
|
||||
git checkout -b branch_name
|
||||
```
|
||||
|
||||
* Make your code changes
|
||||
|
||||
* Stage the changes with `git add`
|
||||
|
||||
```bash
|
||||
git add .
|
||||
```
|
||||
|
||||
* And then commit them with `git commit`:
|
||||
|
||||
```bash
|
||||
git commit -m "Commit Message"
|
||||
```
|
||||
|
||||
* Then push your new branch to GitHub with `git push`:
|
||||
|
||||
```bash
|
||||
git push origin branch_name
|
||||
```
|
||||
|
||||
* After that, visit the repository on GitHub and click on the `Pull Requests` button and then click on the green `New pull request` button:
|
||||
|
||||

|
||||
|
||||
* In there, choose the branch that you want to merge to and the branch that you want to merge from:
|
||||
|
||||

|
||||
|
||||
* Then review the changes and add a title and description and hit the create button
|
||||
* If you are working on a project with multiple contributors, make sure to select a few reviewers. Essentially reviewers are people who you would like to review your code before it gets merged to the `main` branch.
|
||||
|
||||
For a visual representation of the whole process, make sure to check out this step by step tutorial as well:
|
||||
|
||||
* [How to Submit Your First Pull Request on GitHub](https://www.digitalocean.com/community/tutorials/hacktoberfest-how-to-submit-your-first-pull-request-on-github)
|
||||
114
docs/024-git-and-VS-Code.md
Normal file
114
docs/024-git-and-VS-Code.md
Normal file
@@ -0,0 +1,114 @@
|
||||
# Git And VS Code
|
||||
|
||||
As much as I love to use the terminal to do my daily tasks in the end, I would rather do multiple tasks within one window (GUI) or perform everything from the terminal itself.
|
||||
|
||||
In the past, I was using the text editors (vim, nano, etc.) in my terminal to edit the code in my repositories and then go along with the git client to commit my changes. Still, then I switched to Visual Studio Code to manage and develop my code.
|
||||
|
||||
I will recommend you to check this article on why you should use Visual Studio. It is an article from Visual Studio's website itself.
|
||||
|
||||
[Why you should use Visual Studio](https://code.visualstudio.com/docs/editor/whyvscode)
|
||||
|
||||
Visual Studio Code has integrated source control management (SCM) and includes Git support in-the-box. Many other source control providers are available through extensions on the VS Code Marketplace. It also has support for handling multiple Source Control providers simultaneously so you can open all of your projects at the same time and make changes whenever this is needed.
|
||||
|
||||
## Installing VS Code
|
||||
|
||||
You need to install Visual Studio Code. It runs on the macOS, Linux, and Windows operating systems.
|
||||
|
||||
Follow the platform-specific guides below:
|
||||
|
||||
- [macOS](https://code.visualstudio.com/docs/setup/mac)
|
||||
- [Linux](https://code.visualstudio.com/docs/setup/linux)
|
||||
- [Windows](https://code.visualstudio.com/docs/setup/windows)
|
||||
|
||||
You need to install Git first before you get these features. Make sure you install at least version 2.0.0. If you do not have git installed on your machine, feel free to check this really useful article on [How to get started with Git](https://www.digitalocean.com/community/tutorials/how-to-contribute-to-open-source-getting-started-with-git)
|
||||
|
||||
You need to set your username and email in the Git configuration, or git will fail back to using information from your local machine when you commit. We need to provide this information because Git embeds this information into each commit we do.
|
||||
|
||||
To set this, you can execute the following commands:
|
||||
|
||||
```bash
|
||||
git config --global user.name "John Doe"
|
||||
git config --global user.email "johnde@domain.com"
|
||||
```
|
||||
|
||||
The information will be saved in your `~/.gitconfig` file.
|
||||
|
||||
```
|
||||
[user]
|
||||
name = John Doe
|
||||
email = johndoe@domain.com
|
||||
```
|
||||
|
||||
With Git installed and set up on your local machine, you are now ready to use Git for version control with Visual Studio or using the terminal.
|
||||
|
||||
## Cloning a repository in VS Code
|
||||
|
||||
The good thing is that Visual Studio will auto-detect if you've opened a folder that is a repository. If you've already opened a repository, it will be visible in the Source Control View.
|
||||
|
||||

|
||||
|
||||
If you haven't opened a folder yet, the Source Control view will give you the option to Open Folder from your local machine or Clone Repository.
|
||||
|
||||
If you select Clone Repository, you will be asked for the URL of the remote repository (for example, on GitHub) and the parent directory under which to put the local repository.
|
||||
|
||||
For a GitHub repository, you would find the URL from the GitHub Code dialog.
|
||||
|
||||
## Create a branch
|
||||
|
||||
To create a branch open the command pallet:
|
||||
|
||||
- Windows: Ctrl + Shift + P
|
||||
- Linux: Ctrl + Shift _ P
|
||||
- MacOS: Shift + CMD + P
|
||||
|
||||
And select `Git Create Branch...`
|
||||
|
||||

|
||||
|
||||
Then you just need to enter a name for the branch. Keep in mind that in the bottom left corner, you can see in which branch you are. The default one will be the main, and if you successfully create the branch, you should see the name of the newly created branch.
|
||||
|
||||

|
||||
|
||||
If you want to switch branches, you can open the command pallet and search for `Git checkout to` and then select the main branch or switch to a different branch.
|
||||

|
||||
|
||||
## Setup a commit message template
|
||||
|
||||
If you want to speed up the process and have a predefined template for your commit messages, you can create a simple file that will contain this information.
|
||||
|
||||
To do that, open your terminal if you're on Linux or macOS and create the following file: .gitmessage in your home directory. To create the file, you can open it in your favorite text editor and then simply put the default content you would like and then just save and exit the file. Example content is:
|
||||
|
||||
```bash
|
||||
cat ~/.gitmessage
|
||||
```
|
||||
|
||||
```
|
||||
#Title
|
||||
|
||||
#Summary of the commit
|
||||
|
||||
#Include Co-authored-by for all contributors.
|
||||
```
|
||||
|
||||
To tell Git to use it as the default message that appears in your editor when you run `git commit` and set the `commit.template` configuration value:
|
||||
|
||||
```bash
|
||||
$ git config --global commit.template ~/.gitmessage
|
||||
$ git commit
|
||||
```
|
||||
|
||||
## Conclusion
|
||||
|
||||
If you prefer to code in Visual Studio Code and you also use version control, I will recommend you to give it a go and interact with the repositories in VS code. I believe that everyone has their own style, and they might do things differently depending on their mood as well. As long as you can add/modify your code and then commit your changes to the repository, there is no exactly correct/wrong way to achieve this. For example, you can edit your code in vim and push the changes using the git client in your terminal or do the coding in Visual Studio and then commit the changes using the terminal as well. You're free to do it the way you want it and the way you find it more convenient as well. I believe that using git within VS code can make your workflow more efficient and robust.
|
||||
|
||||
## Additional sources:
|
||||
|
||||
* [Version Control](https://code.visualstudio.com/docs/editor/versioncontrol) - Read more about integrated Git support.
|
||||
* [Setup Overview](https://code.visualstudio.com/docs/setup/setup-overview) - Set up and start using VS Code.
|
||||
* [GitHub with Visual Studio](https://www.notion.so/Git-version-control-with-Visual-Studio-Code-8de38af5cf324b9d89c4827e32dfe173) - Read more about the GitHub support in VS code
|
||||
* You can also check this mini video tutorial on how to use the basics of Git version control in Visual Studio Code
|
||||
|
||||
Source:
|
||||
|
||||
* Contributed by: [Alex Georgiev](https://twitter.com/AlexGeorgiev17).
|
||||
* Initially posted [here](https://devdojo.com/alexg/version-control-with-visual-studio-code-1).
|
||||
222
docs/025-github-cli.md
Normal file
222
docs/025-github-cli.md
Normal file
@@ -0,0 +1,222 @@
|
||||
# GitHub CLI
|
||||
|
||||
The GitHub CLI or `gh` is basically GitHub on command-line.
|
||||
|
||||
You can interact with your GitHub account directly through your command line and manage things like pull requests, issues, and other GitHub actions.
|
||||
|
||||
In this tutorial, I will give a quick overview of how to install `gh` and how to use it!
|
||||
|
||||
## GitHub CLI Installation
|
||||
|
||||
As I will be using Ubuntu, to install `gh` you need to run the following commands:
|
||||
|
||||
```bash
|
||||
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-key C99B11DEB97541F0
|
||||
sudo apt-add-repository https://cli.github.com/packages
|
||||
sudo apt update
|
||||
sudo apt install gh
|
||||
```
|
||||
|
||||
If you are on a Mac, you can install `gh` using Homebrew:
|
||||
|
||||
```bash
|
||||
brew install gh
|
||||
```
|
||||
|
||||
For any other operating systems, I recommend following the steps from the official documentation [here](https://github.com/cli/cli#installation).
|
||||
|
||||
Once you have `gh` installed, you can verify that it works with the following command:
|
||||
|
||||
```bash
|
||||
gh --version
|
||||
```
|
||||
|
||||
This would output the `gh` version:
|
||||
|
||||
```
|
||||
gh version 1.0.0 (2020-09-16)
|
||||
https://github.com/cli/cli/releases/tag/v1.0.0
|
||||
```
|
||||
|
||||
In my case, I'm running the latest `gh` v1.0.0, which got released just a couple of days ago.
|
||||
|
||||
## Authentication
|
||||
|
||||
Once you have `gh` installed, you need to login to your GitHub account.
|
||||
|
||||
To do so, you need to run the following command:
|
||||
|
||||
```bash
|
||||
gh auth login
|
||||
```
|
||||
|
||||
You will see the following output:
|
||||
|
||||
```
|
||||
? What account do you want to log into? [Use arrows to move, type to filter]
|
||||
> GitHub.com
|
||||
GitHub Enterprise Server
|
||||
```
|
||||
|
||||
You have an option to choose between GitHub.com or GitHub Enterprise. Click enter and then follow the authentication process.
|
||||
|
||||
Another useful command is the `gh help` command. This will give you a list with the available `gh` commands that you could use:
|
||||
|
||||
```
|
||||
USAGE
|
||||
gh <command> <subcommand> [flags]
|
||||
|
||||
CORE COMMANDS
|
||||
gist: Create gists
|
||||
issue: Manage issues
|
||||
pr: Manage pull requests
|
||||
release: Manage GitHub releases
|
||||
repo: Create, clone, fork, and view repositories
|
||||
|
||||
ADDITIONAL COMMANDS
|
||||
alias: Create command shortcuts
|
||||
api: Make an authenticated GitHub API request
|
||||
auth: Login, logout, and refresh your authentication
|
||||
completion: Generate shell completion scripts
|
||||
config: Manage configuration for gh
|
||||
help: Help about any command
|
||||
|
||||
FLAGS
|
||||
--help Show help for command
|
||||
--version Show gh version
|
||||
|
||||
EXAMPLES
|
||||
$ gh issue create
|
||||
$ gh repo clone cli/cli
|
||||
$ gh pr checkout 321
|
||||
|
||||
ENVIRONMENT VARIABLES
|
||||
See 'gh help environment' for the list of supported environment variables.
|
||||
|
||||
LEARN MORE
|
||||
Use 'gh <command> <subcommand> --help' for more information about a command.
|
||||
Read the manual at https://cli.github.com/manual
|
||||
|
||||
FEEDBACK
|
||||
Open an issue using 'gh issue create -R cli/cli'
|
||||
```
|
||||
|
||||
Then let's clone an existing project which we will use to play with. As an example, we can use the [LaraSail](https://github.com/thedevdojo/larasail) repository. Rather than cloning the repository using the standard `git clone` command, we will use `gh` to do so:
|
||||
|
||||
```bash
|
||||
gh repo clone thedevdojo/larasail
|
||||
```
|
||||
|
||||
You will see the following output:
|
||||
|
||||
```
|
||||
Cloning into 'larasail'...
|
||||
```
|
||||
|
||||
After that `cd` into that folder:
|
||||
|
||||
```bash
|
||||
cd larasail
|
||||
```
|
||||
|
||||
We are now ready to move to some of the more useful `gh` commands!
|
||||
|
||||
## Useful GitHub CLI commands
|
||||
|
||||
Using `gh`, you can pretty much get all of the information for your repository on GitHub without having even to leave your terminal.
|
||||
|
||||
Here's a list of some useful commands:
|
||||
|
||||
### Working with GitHub issues
|
||||
|
||||
To list all open issues, run:
|
||||
|
||||
```bash
|
||||
gh issue list
|
||||
```
|
||||
|
||||
The output that you will see is:
|
||||
|
||||
```
|
||||
Showing 4 of 4 open issues in thedevdojo/larasail
|
||||
|
||||
#25 Add option to automatically create database (enhancement) about 3 months ago
|
||||
#22 Remove PHP mcrypt as it is no longer needed about 3 months ago
|
||||
#11 Add redis support about 8 months ago
|
||||
#10 Wondering about the security of storing root MySQL password in /etc/.larasail/tmp/mysqlpass about 3 months ago
|
||||
```
|
||||
|
||||
You can even create a new issue with the following command:
|
||||
|
||||
```bash
|
||||
gh issue create --label bug
|
||||
```
|
||||
|
||||
Or if you wanted to view an existing issue, you could just run:
|
||||
|
||||
```bash
|
||||
gh issue view '#25'
|
||||
```
|
||||
|
||||
This would return all of the information for that specific issue number:
|
||||
|
||||
```
|
||||
Add option to automatically create a database
|
||||
Open • bobbyiliev opened about 3 months ago • 0 comments
|
||||
|
||||
Labels: enhancement
|
||||
|
||||
|
||||
Add an option to automatically create a new database, a database user and
|
||||
possibly update the database details in the .env file for a specific project
|
||||
|
||||
|
||||
|
||||
View this issue on GitHub: https://github.com/thedevdojo/larasail/issues/25
|
||||
```
|
||||
|
||||
### Working with your GitHub repository
|
||||
|
||||
You can use the `gh repo` command to create, clone, or view an existing repository:
|
||||
|
||||
```bash
|
||||
gh repo create
|
||||
gh repo clone cli/cli
|
||||
gh repo view --web
|
||||
```
|
||||
|
||||
For example, if we ran the `gh repo view`, we would see the same README information for our repository directly in our terminal.
|
||||
|
||||
### Working with Pull requests
|
||||
|
||||
You can use the `gh pr` command with a set of arguments to fully manage your pull requests.
|
||||
|
||||
Some of the available options are:
|
||||
|
||||
```
|
||||
checkout: Check out a pull request in git
|
||||
checks: Show CI status for a single pull request
|
||||
close: Close a pull request
|
||||
create: Create a pull request
|
||||
diff: View changes in a pull request
|
||||
list: List and filter pull requests in this repository
|
||||
merge: Merge a pull request
|
||||
ready: Mark a pull request as ready for review
|
||||
reopen: Reopen a pull request
|
||||
review: Add a review to a pull request
|
||||
status: Show status of relevant pull requests
|
||||
view: View a pull request
|
||||
```
|
||||
|
||||
With the above commands, you are ready to execute some of the main GitHub actions you would typically take directly in your terminal!
|
||||
|
||||
### Conclusion
|
||||
|
||||
Now you know what the GitHub CLI tool is and how to use it! For more information, I would recommend checking out the official documentation here:
|
||||
|
||||
[https://cli.github.com/manual/](https://cli.github.com/manual/)
|
||||
|
||||
I'm a big fan of all command-line tools! They can make your life easier and automate a lot of the daily repetitive tasks!
|
||||
|
||||
Initially posted here:
|
||||
[What is GitHub CLI and how to get started](https://devdojo.com/bobbyiliev/what-is-github-cli-and-how-to-get-started)
|
||||
87
docs/026-git-stash.md
Normal file
87
docs/026-git-stash.md
Normal file
@@ -0,0 +1,87 @@
|
||||
# Git Stash
|
||||
|
||||
`git stash` is a handy command that helps you in cases where you might need to stash away your local changes and reset your codebase to the most recent commit in order to work on a more urgent bug/feature.
|
||||
|
||||
In other words, this command allows you to revert your current working directory to match the `HEAD` commit while keeping all the local modifications safe.
|
||||
|
||||
Once you are ready to get back to working on the code you had stashed away, just restore them with a single command!
|
||||
|
||||
## Stashing Your Work
|
||||
|
||||
```bash
|
||||
git stash
|
||||
```
|
||||
|
||||
For example, consider a file named `index.html` which has been modified since the last commit.
|
||||
|
||||

|
||||
|
||||
Notice that the running `git status` command says that there are no new changes once the `git stash` command is executed!
|
||||
|
||||
Here WIP stands for Work-In-Progress and these are used to index the various stashed copies of your work.
|
||||
|
||||
An important thing to keep in mind before stashing all new changes is that, by default, `git stash` **will not stash all the untracked and ignored files.** (Here, _untracked files_ are the files that weren't part of the last commit i.e, new files in your local repo)
|
||||
|
||||
In case you want to include these untracked files in the stash, you'll need to add the **-u** option.
|
||||
|
||||
```bash
|
||||
git stash -u
|
||||
```
|
||||
|
||||
Similarly, all the files in the `.gitignore` file (i.e, _the ignored files_) will also be excluded from your stash. But you can include them by using the **-a option**
|
||||
|
||||
```bash
|
||||
git stash -a
|
||||
```
|
||||
|
||||
The following illustrations depict the behaviour of the `git stash` command when the above two options are included:
|
||||
|
||||

|
||||
|
||||
## Restoring the Stashed Changes
|
||||
|
||||
```bash
|
||||
git stash apply
|
||||
```
|
||||
|
||||
This command is used to reapply all the local modifications done before that copy of the work was stashed.
|
||||
|
||||
Note that another command that can be used to achieve this is the `git stash pop` command. Here _popping_ refers to the process of removing the most recent stash content and reapplying them to your working copy.
|
||||
|
||||
The difference between these two commands is that the `git stash pop` command **will remove these particular changes from the stash** whereas the `git stash apply` command **will retain those changes in the stash** even after restoring them.
|
||||
|
||||
Consider the previous example itself, in which the file `index.html` was stashed. In the following image, you can see how restoring all those changes affects your local repo.
|
||||
|
||||

|
||||
|
||||
But what if you have multiple stashes and aren't sure which one you want to start working on? This is where the next command comes into the picture!
|
||||
|
||||
## Handling Multiple Stashed Copies of Your Work
|
||||
|
||||
Similar to the process involved in resetting the local repository to a particular commit, the first step involved in handling multiple stashes is to **take a look at the various stashes available**.
|
||||
|
||||
```bash
|
||||
git stash list
|
||||
```
|
||||
|
||||
This command shows an indexed list of all the available stashes along with a **message corresponding to their respective recent commits**.
|
||||
|
||||
Consider the following example wherein there are two available stashes. One, when a new script file was added and another when this script file was altered.
|
||||
|
||||

|
||||
|
||||
Note that the most recent stash is always indexed as 0.
|
||||
|
||||
Once you know which stash you want to restore to your local codebase, the command used to restore those modifications is:
|
||||
|
||||
```bash
|
||||
git stash apply n
|
||||
```
|
||||
|
||||
The alternative syntax used to achieve this is as follows:
|
||||
|
||||
```bash
|
||||
git stash apply "stash@{n}"
|
||||
```
|
||||
|
||||
Here **n** is the index of the stash you want to restore.
|
||||
34
docs/027-git-alias.md
Normal file
34
docs/027-git-alias.md
Normal file
@@ -0,0 +1,34 @@
|
||||
|
||||
# Git Alias
|
||||
|
||||
If there is a common but complex Git command that you type frequently, consider setting up a simple Git alias for it. Aliases enable more efficient workflows by requiring fewer keystrokes to execute a command. It is important to note that **there is no direct git alias command**. Aliases are created through the use of the git config command and the Git configuration files.
|
||||
|
||||
```bash
|
||||
git config --global alias.co checkout
|
||||
```
|
||||
|
||||
Now when I use the command git co, it is just as if I had typed that longer git checkout command.
|
||||
|
||||
```bash
|
||||
git co -b branch1
|
||||
```
|
||||
|
||||
Output
|
||||
|
||||
```bash
|
||||
Switched to a new branch 'branch1'
|
||||
```
|
||||
|
||||
Creating the aliases will not modify the source commands. So git checkout will still be available even though we now have the git co alias.
|
||||
|
||||
```bash
|
||||
git checkout -b branch2
|
||||
```
|
||||
|
||||
Output
|
||||
|
||||
```bash
|
||||
Switched to a new branch 'branch2'
|
||||
```
|
||||
|
||||
Aliases can also be used to wrap a sequence of Git commands into new Git command.
|
||||
130
docs/028-git-rebase.md
Normal file
130
docs/028-git-rebase.md
Normal file
@@ -0,0 +1,130 @@
|
||||
|
||||
# Git Rebase
|
||||
|
||||
Rebasing is often used as an alternative to merging. Rebasing a branch updates one branch with another by applying the commits of one branch on top of the commits of another branch. For example, if working on a feature branch that is out of date with a dev branch, rebasing the feature branch onto dev will allow all the new commits from dev to be included in feature. Here’s what this looks like visually:
|
||||
|
||||
### Visualization of the command :
|
||||

|
||||

|
||||
|
||||
|
||||
### Syntax :
|
||||
```bash
|
||||
git rebase feature dev
|
||||
```
|
||||
where branch1 is the branch we want to rebase to the master.
|
||||
|
||||
### Difference between Merge and Rebase :
|
||||
Many people think that `Merge` and `Rebase` commands perform the same job but actually they are completely different and we will discuss this in the following lines.
|
||||
|
||||
- #### Merge :
|
||||
This command is used to integrate changes from some branch to another branch with keeping the merged branch at its base so you can easily return to earlier version of code if you want and the following picture show that :
|
||||

|
||||
|
||||
### typical use of rebasing
|
||||
#### Updating a Feature Branch
|
||||
Lets say you’re working away on a feature branch, minding your own business.
|
||||

|
||||
|
||||
Then you notice some new commits on dev that you’d like to have in your feature branch, since the new commits may affect how you implement the feature.
|
||||
|
||||

|
||||
|
||||
|
||||
You decide to run git rebase dev from your feature branch to get up-to-date with dev.
|
||||
However when you run the rebase command, there are some conflicts between the changes you made on feature and the new commits on dev. Thankfully, the rebase process goes through each commit one at a time and so as soon as it notices a conflict on a commit, git will provide a message in the terminal outlining what files need to be resolved. Once you’ve resolved the conflict, you git add your changes to the commit and run git rebase --continue to continue the rebase process. If there are no more conflicts, you will have successfully rebased your feature branch onto dev.
|
||||
|
||||

|
||||
|
||||
Now you can continue working on your feature with the latest commits from dev included in feature and all is well again in the world. This process can repeat itself if the dev branch is updated with additional commits.
|
||||
|
||||
- #### Rebase :
|
||||
On the other hand `Rebase` command is used to transfer the base of the branch to be based at the last commit of the current branch which make them as one branch as shown in the picture at the top.
|
||||
|
||||
### Rebasing interactively :
|
||||
|
||||
You can also rebase a branche on another `interactively`. This means that you will be prompted for options.
|
||||
The basic command looks like this:
|
||||
|
||||
```bash
|
||||
git rebase -i feature main
|
||||
```
|
||||
|
||||
This will open your favorite editor (probably `vi` or `vscode`).
|
||||
|
||||
Let's create an example:
|
||||
|
||||
```bash
|
||||
git switch main
|
||||
git checkout -b feature-interactive
|
||||
echo "<p>Rebasing interactively is super cool</p>" >> feature1.html
|
||||
git commit -am "Commit to test Interactive Rebase"
|
||||
echo "<p>With interactive rebasing you can do really cool stuff</p>" >> feature1.html
|
||||
git commit -am "Commit to test Interactive Rebase"
|
||||
```
|
||||
|
||||
So you are now on the `feature-interactive` branch with a commit on this branch that doesn't exist on the `main` branch, and there is a new commit on the `main` that is not in your branch.
|
||||
|
||||
Now using the interactive rebase commande:
|
||||
|
||||
```bash
|
||||
git rebase -i main
|
||||
```
|
||||
|
||||
Your favorite editor (`vi` like here or `vscode` if you've set it up correctly) should be open with something like this:
|
||||
|
||||
```
|
||||
pick a21b178 Commit to test Interactive Rebase
|
||||
pick cd3400c Commit to test Interactive Rebase
|
||||
|
||||
# Rebase 1d152d4..a21b178 onto 1d152d4
|
||||
#
|
||||
# p, pick <commit> = use commit
|
||||
# r, reword <commit> = use commit, but edit the commit message
|
||||
# e, edit <commit> = use commit, but stop for amending
|
||||
# s, squash <commit> = use commit, but meld into previous commit
|
||||
# f, fixup <commit> = like "squash", but discard this commit's log message
|
||||
# x, exec <command> = run command (the rest of the line) using shell
|
||||
# b, break = stop here (continue rebase later with 'git rebase --continue')
|
||||
# d, drop <commit> = remove commit
|
||||
# l, label <label> = label current HEAD with a name
|
||||
# t, reset <label> = reset HEAD to a label
|
||||
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
|
||||
# . create a merge commit using the original merge commit's
|
||||
# . message (or the oneline, if no original merge commit was
|
||||
# . specified). Use -c <commit> to reword the commit message.
|
||||
#
|
||||
# These lines can be re-ordered; they are executed from top to bottom.
|
||||
#
|
||||
# If you remove a line here THAT COMMIT WILL BE LOST.
|
||||
#
|
||||
# However, if you remove everything, the rebase will be aborted.
|
||||
#
|
||||
# Note that empty commits are commented out
|
||||
```
|
||||
|
||||
As you can see here, the first lines are the commits you made in this `feature-interactive` branche. Then, the remaining of the file is the help message.
|
||||
If you look at this help message closely, you will notice that there are plenty of options. To use them all you need to do is to prefix the commit line you want to work on by the name of the command or its shortcut letter.
|
||||
|
||||
The basic command is `pick`, meaning that the current rebase will use these two commits to do its work.
|
||||
|
||||
In our case, if you want to update the commit message of the second commit, you would update this file like this (we just show the first lines as the remaining are not updates):
|
||||
|
||||
```
|
||||
pick a21b178 Commit to test Interactive Rebase
|
||||
r cd3400c Commit to test Interactive Rebase
|
||||
|
||||
# Rebase 1d152d4..a21b178 onto 1d152d4
|
||||
#
|
||||
...
|
||||
```
|
||||
|
||||
Then you would save the file, as it is `vi` here, you would hit the key `:` and type `wq`. You should now see another file opened in the same editor, where you can edit your commit message, then save the file and that's it.
|
||||
|
||||
You can look at the result with the following command:
|
||||
|
||||
```bash
|
||||
git log
|
||||
```
|
||||
|
||||
Now that you now the basics on how to use this command, take a look at the help message. There are some usefull commend in there. My favorites are the `reword`, `fixup` and `drop` but feel free to experiment by yourself.
|
||||
31
docs/029-git-switch.md
Normal file
31
docs/029-git-switch.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# Git Switch
|
||||
|
||||
`git switch` is not a new feature but an additional command to switch/change branch feature which is already available in the overloaded git checkout command. That's why, pretty recently, the Git community decided to publish a new command: `git switch`. As the name implies.
|
||||
|
||||
### Syntax :
|
||||
|
||||
```bash
|
||||
git switch <branch-name>
|
||||
```
|
||||
|
||||
### Visualization of the command:
|
||||
|
||||

|
||||
|
||||
### Difference between Switch and Checkout:
|
||||
|
||||
As you can see, its usage is very straightforward and similar to "git checkout". But the huge advantage over the "checkout" command is that "switch" does NOT have a million other meanings and capabilities.
|
||||
|
||||
As it is quite a new member of the Git command family, you should check if your Git installation already includes it.
|
||||
|
||||
### Switch Back and Forth Between Two Branches
|
||||
|
||||
In some scenarios, it might be necessary for you to switch back and forth between two branches repeatedly. Instead of always writing out the branch names in full, you can simply use the following shortcut:
|
||||
|
||||
### Syntax :
|
||||
|
||||
```bash
|
||||
git switch -
|
||||
```
|
||||
|
||||
Using the dash character as its only parameter, the "git switch" command will check out the previously active branch. As said, this can come in very handy if you have to go back and forth between two branches a bunch of times.
|
||||
246
docs/030-github-markdown-cheatsheet.md
Normal file
246
docs/030-github-markdown-cheatsheet.md
Normal file
@@ -0,0 +1,246 @@
|
||||
# GitHub Markdown Cheatsheet
|
||||
|
||||
### Heading 1
|
||||
|
||||
Markup : # Heading 1 #
|
||||
|
||||
-OR-
|
||||
|
||||
Markup : ============= (below H1 text)
|
||||
|
||||
### Heading 2
|
||||
|
||||
Markup : ## Heading 2 ##
|
||||
|
||||
-OR-
|
||||
|
||||
Markup: --------------- (below H2 text)
|
||||
|
||||
### Heading 3 ###
|
||||
|
||||
Markup : ### Heading 3 ###
|
||||
|
||||
#### Heading 4 ####
|
||||
|
||||
Markup : #### Heading 4 ####
|
||||
|
||||
|
||||
### Common text
|
||||
|
||||
Markup : Common text
|
||||
|
||||
### _Emphasized text_
|
||||
|
||||
Markup : _Emphasized text_ or *Emphasized text*
|
||||
|
||||
### ~~Strikethrough text~~
|
||||
|
||||
Markup : ~~Strikethrough text~~
|
||||
|
||||
### __Strong text__
|
||||
|
||||
Markup : __Strong text__ or **Strong text**
|
||||
|
||||
### ___Strong emphasized text___
|
||||
|
||||
Markup : ___Strong emphasized text___ or ***Strong emphasized text***
|
||||
|
||||
### [Named Link](http://www.google.fr/ "Named link title") and http://www.google.fr/ or <http://example.com/>
|
||||
|
||||
Markup : [Named Link](http://www.google.fr/ "Named link title") and http://www.google.fr/ or <http://example.com/>
|
||||
|
||||
### [heading-1](#heading-1 "Goto heading-1")
|
||||
|
||||
Markup: [heading-1](#heading-1 "Goto heading-1")
|
||||
|
||||
### Table, like this one :
|
||||
|
||||
First Header | Second Header
|
||||
------------- | -------------
|
||||
Content Cell | Content Cell
|
||||
Content Cell | Content Cell
|
||||
|
||||
```
|
||||
First Header | Second Header
|
||||
------------- | -------------
|
||||
Content Cell | Content Cell
|
||||
Content Cell | Content Cell
|
||||
```
|
||||
|
||||
#### Adding a pipe `|` in a cell :
|
||||
|
||||
First Header | Second Header
|
||||
------------- | -------------
|
||||
Content Cell | Content Cell
|
||||
Content Cell | \|
|
||||
|
||||
```
|
||||
First Header | Second Header
|
||||
------------- | -------------
|
||||
Content Cell | Content Cell
|
||||
Content Cell | \|
|
||||
```
|
||||
|
||||
#### Left, right and center aligned table
|
||||
|
||||
Left aligned Header | Right aligned Header | Center aligned Header
|
||||
| :--- | ---: | :---:
|
||||
Content Cell | Content Cell | Content Cell
|
||||
Content Cell | Content Cell | Content Cell
|
||||
|
||||
```
|
||||
Left aligned Header | Right aligned Header | Center aligned Header
|
||||
| :--- | ---: | :---:
|
||||
Content Cell | Content Cell | Content Cell
|
||||
Content Cell | Content Cell | Content Cell
|
||||
```
|
||||
|
||||
### `code()`
|
||||
|
||||
Markup : `code()`
|
||||
|
||||
```javascript
|
||||
var specificLanguage_code =
|
||||
{
|
||||
"data": {
|
||||
"lookedUpPlatform": 1,
|
||||
"query": "Kasabian+Test+Transmission",
|
||||
"lookedUpItem": {
|
||||
"name": "Test Transmission",
|
||||
"artist": "Kasabian",
|
||||
"album": "Kasabian",
|
||||
"picture": null,
|
||||
"link": "http://open.spotify.com/track/5jhJur5n4fasblLSCOcrTp"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Markup : ```javascript
|
||||
```
|
||||
### Unordered List
|
||||
|
||||
* Bullet list
|
||||
* Nested bullet
|
||||
* Sub-nested bullet etc
|
||||
* Bullet list item 2
|
||||
|
||||
~~~
|
||||
Markup : * Bullet list
|
||||
* Nested bullet
|
||||
* Sub-nested bullet etc
|
||||
* Bullet list item 2
|
||||
-OR-
|
||||
Markup : - Bullet list
|
||||
- Nested bullet
|
||||
- Sub-nested bullet etc
|
||||
- Bullet list item 2
|
||||
~~~
|
||||
|
||||
### Ordered List
|
||||
|
||||
1. A numbered list
|
||||
1. A nested numbered list
|
||||
2. Which is numbered
|
||||
2. Which is numbered
|
||||
|
||||
~~~
|
||||
Markup : 1. A numbered list
|
||||
1. A nested numbered list
|
||||
2. Which is numbered
|
||||
2. Which is numbered
|
||||
~~~
|
||||
|
||||
|
||||
- [ ] An uncompleted task
|
||||
- [x] A completed task
|
||||
|
||||
~~~
|
||||
Markup : - [ ] An uncompleted task
|
||||
- [x] A completed task
|
||||
~~~
|
||||
|
||||
- [ ] An uncompleted task
|
||||
- [ ] A subtask
|
||||
|
||||
~~~
|
||||
Markup : - [ ] An uncompleted task
|
||||
- [ ] A subtask
|
||||
~~~
|
||||
|
||||
|
||||
> Blockquote
|
||||
>> Nested blockquote
|
||||
Markup : > Blockquote
|
||||
>> Nested Blockquote
|
||||
### _Horizontal line :_
|
||||
- - - -
|
||||
|
||||
Markup : - - - -
|
||||
|
||||
### _Image with alt :_
|
||||
|
||||

|
||||
|
||||
Markup : 
|
||||
|
||||
### Foldable text:
|
||||
|
||||
<details>
|
||||
<summary>Title 1</summary>
|
||||
<p>Content 1 Content 1 Content 1 Content 1 Content 1</p>
|
||||
</details>
|
||||
<details>
|
||||
<summary>Title 2</summary>
|
||||
<p>Content 2 Content 2 Content 2 Content 2 Content 2</p>
|
||||
</details>
|
||||
|
||||
Markup : <details>
|
||||
<summary>Title 1</summary>
|
||||
<p>Content 1 Content 1 Content 1 Content 1 Content 1</p>
|
||||
</details>
|
||||
|
||||
```html
|
||||
<h3>HTML</h3>
|
||||
<p> Some HTML code here </p>
|
||||
```
|
||||
|
||||
Link to a specific part of the page:
|
||||
|
||||
### [Go To TOP](#TOP)
|
||||
|
||||
Markup : [text goes here](#section_name)
|
||||
section_title<a name="section_name"></a>
|
||||
|
||||
### Hotkey:
|
||||
|
||||
<kbd>⌘F</kbd>
|
||||
|
||||
<kbd>⇧⌘F</kbd>
|
||||
|
||||
Markup : <kbd>⌘F</kbd>
|
||||
|
||||
### Hotkey list:
|
||||
|
||||
| Key | Symbol |
|
||||
| --- | --- |
|
||||
| Option | ⌥ |
|
||||
| Control | ⌃ |
|
||||
| Command | ⌘ |
|
||||
| Shift | ⇧ |
|
||||
| Caps Lock | ⇪ |
|
||||
| Tab | ⇥ |
|
||||
| Esc | ⎋ |
|
||||
| Power | ⌽ |
|
||||
| Return | ↩ |
|
||||
| Delete | ⌫ |
|
||||
| Up | ↑ |
|
||||
| Down | ↓ |
|
||||
| Left | ← |
|
||||
| Right | → |
|
||||
|
||||
### Emoji:
|
||||
|
||||
:exclamation: Use emoji icons to enhance text. :+1: Look up emoji codes at [emoji-cheat-sheet.com](http://emoji-cheat-sheet.com/)
|
||||
|
||||
Markup : Code appears between colons :EMOJICODE:
|
||||
88
docs/997-create-your-github-profile.md
Normal file
88
docs/997-create-your-github-profile.md
Normal file
@@ -0,0 +1,88 @@
|
||||
# Create your GitHub profile
|
||||
|
||||
Apart from looking awesome, a good GitHub profile shows people what you can do and gives you a chance to show it off. Also, job applications often include a section to add your GitHub profile link so this can be your chance to shine 💫
|
||||
|
||||
<img src="https://i.imgur.com/TkXywOV.png" alt="profile-pic" width="600"/>
|
||||
|
||||
[View full profile](https://github.com/elenajp)
|
||||
|
||||
### Markdown
|
||||
|
||||
To create a GitHub profile, you need to understand Markdown. Markdown is a lightweight markup language for creating formatted text using a plain-text editor. Check out this
|
||||
[Markdown Cheatsheet](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#images).
|
||||
|
||||
### Create a GitHub repository for your profile page
|
||||
|
||||
First of all you need to create a new repository. Use this link https://github.com/new to do so. You must name your repository the same as your GitHub username as shown below:
|
||||
|
||||
<img src="https://i.imgur.com/kuiey7L.png" alt="create-repo" width="600"/>
|
||||
|
||||
You will discover your secret/special repository! Make the repository public and select add a README file. Then you are done creating your repository. I recommend making your repository private whilst you work on it and then making it public once complete. Now time to add content and make it look awesome.
|
||||
|
||||
**Tip:** When working on a markdown file in your development environment, you can preview what the page will look like by pressing ```CMD+Shift+V``` or ```Ctrl+Shift+V```
|
||||
|
||||
### Adding a header
|
||||
|
||||
The first thing people on your profile notice is the header. Perhaps you could add a photo of something you love, your hobby, art that inspires you, an image of some code you worked on, etc. You could even have your profile picture match it. I recommend an actual photo of yourself, rather than a cartoon. The markdown needed is:
|
||||
|
||||
```
|
||||

|
||||
```
|
||||
|
||||
Here is a website that allows you to generate header images for your GitHub profile READMEs. https://reheader.glitch.me/
|
||||
|
||||
### Introduce yourself
|
||||
Say hello to your visitors. Write an introductory paragraph. Tell them a bit about yourself, where you are from, what inspires you. This section is where you can let your personality shine though.
|
||||
|
||||
### Mention what you are up to
|
||||
You can show visitors to your profile what you are up to and what you are working on. This is a great way for them to get to know a bit more about you.
|
||||
- 🧐 I'm interested in...
|
||||
- 🔭 I’m currently working on...
|
||||
- 🌱 I’m currently studying...
|
||||
- 👯 I’m looking to...
|
||||
- 🤔 I’m looking for help with...
|
||||
- 💬 Ask me about...
|
||||
- ⚡ Fun fact:...
|
||||
|
||||
### Include statistics
|
||||
You can display your GitHub stats on your profile. These include displaying total commits made, total pull requests, total issues etc. Check out these cool themes to display your statistics:
|
||||
|
||||
<img src="https://i.imgur.com/jUjiTSM.png" alt="create-repo" width="400"/>
|
||||
|
||||
[Click here](https://github.com/anuraghazra/github-readme-stats#themes) to use one of these cool themes
|
||||
|
||||
### Add social media buttons
|
||||
Adding social media buttons is a great way to direct visitors or even employers to your social media platforms. For example to add Twitter:
|
||||
|
||||
[](https://twitter.com/USER-NAME)
|
||||
````
|
||||
[](https://twitter.com/USER-NAME)
|
||||
````
|
||||
|
||||
### Pin repositories to your GitHub profile
|
||||
|
||||
As the number of repositories you've created or contributed to grows, you might want to showcase a few of these repositories straight on your profile. This feature is extra useful when you want to present your portfolio to a potential employer and want them to see the work you are proudest of first!
|
||||
|
||||
This is how you do it:
|
||||
|
||||
In the top right corner, click on your profile photo and select "Your profile" from the menu:
|
||||
|
||||

|
||||
|
||||
In the section saying "Popular repositories" or "Pinned", click on "Customize your pins":
|
||||
|
||||

|
||||
|
||||
After the previous step, the "Edit pinned items" modal will open. Here, you can choose a combination of up to six repositories and/or gists to display:
|
||||
|
||||

|
||||
|
||||
Once you've decided which repositories you want to pin, click "Save pins".
|
||||
|
||||
### Get inspired
|
||||
Check out these useful links to inspire you, to help you with your GitHub profile:
|
||||
* https://github.com/abhisheknaiidu/awesome-github-profile-readme
|
||||
* https://github.com/elangosundar/awesome-README-templates
|
||||
|
||||
### Be creative
|
||||
This is a fun project to work on. Be creative! There is a lot more you can add to your profile. From adding different statistics, technologies & tools you use, emoji GIFs, etc. You can ask friends or other developers their opinions of your GitHub profile. Remember don't overdo it. No one wants super fast animations or flashing images that will hurt their eyes. Think of nice color themes, what works well together, and add a nice profile pic. Good luck!
|
||||
218
docs/998-git-commands-cheat-sheet.md
Normal file
218
docs/998-git-commands-cheat-sheet.md
Normal file
@@ -0,0 +1,218 @@
|
||||
# Git Cheat Sheet
|
||||
|
||||
Here is a list of the Git commands mentioned throughout the eBook
|
||||
|
||||
* Git Configuration
|
||||
|
||||
Before you initialize a new git repository or start making commits, you should set up your git identity.
|
||||
|
||||
To change the name that is associated with your commits, you can use the `git config` command:
|
||||
|
||||
```bash
|
||||
git config --global user.name "Your Name"
|
||||
```
|
||||
|
||||
The same would go for changing your email address associated with your commits as well:
|
||||
|
||||
```bash
|
||||
git config --global user.email "yourmail@example.com"
|
||||
```
|
||||
|
||||
That way, once you have the above configured when you make a commit and then check the git log, you will be able to see that the commit is associated with the details that you've configured above.
|
||||
|
||||
```bash
|
||||
git log
|
||||
```
|
||||
|
||||
In my case the output looks like this:
|
||||
|
||||
```
|
||||
commit 45f96b8c2ef143011f11b5f6cc7a3ae20db5349d (HEAD -> main, origin/master, origin/HEAD)
|
||||
Author: Bobby Iliev <bobby@bobbyiliev.com>
|
||||
Date: Fri Jun 19 17:03:53 2020 +0300
|
||||
|
||||
Nginx server name for www version (#26)
|
||||
|
||||
```
|
||||
|
||||
### Initializing a project
|
||||
|
||||
To initialize a new local git project, open your git or bash terminal, `cd` to the directory that you would like your project to be stored at, and then run:
|
||||
|
||||
```bash
|
||||
git init .
|
||||
```
|
||||
|
||||
If you already have an existing project in GitHub, for example, you can clone it by using the git clone command:
|
||||
|
||||
```bash
|
||||
git clone your_project_url
|
||||
```
|
||||
|
||||
### Current status
|
||||
|
||||
To check the current status of your local git repository, you need to use the following command:
|
||||
|
||||
```bash
|
||||
git status
|
||||
```
|
||||
|
||||
This is probably one of the most used commands as you would need to check the status of your local repository quite often to be able to tell what files have been changed, staged, or deleted.
|
||||
|
||||
### Add a file to the staging area
|
||||
|
||||
Let's say that you have a static HTML project, and you have already initialized your git repository.
|
||||
|
||||
After that, at a later stage, you decide to add a new HTML file called `about-me.html`, then you've added some HTML code in there already. To add your new file so that it is also tracked in git, you first need to use the `git add` command:
|
||||
|
||||
```bash
|
||||
git add file_name
|
||||
```
|
||||
|
||||
This will stage your new file, which essentially means that the next time you make a commit, the change will be part of the commit.
|
||||
|
||||
To check that, you can again run the `git status` command:
|
||||
|
||||
```bash
|
||||
git status
|
||||
```
|
||||
|
||||
You will see the following output:
|
||||
|
||||
```
|
||||
On branch main
|
||||
Your branch is up to date with 'origin/main'.
|
||||
|
||||
Changes to be committed:
|
||||
(use "git reset HEAD <file>..." to unstage)
|
||||
|
||||
new file: about-me.html
|
||||
```
|
||||
|
||||
### Removing files
|
||||
|
||||
To remove a file from your git project, use the following command:
|
||||
|
||||
```bash
|
||||
git rm some_file.txt
|
||||
```
|
||||
|
||||
Then after that, if you run `git status` again, you will see that the `some_file.txt` file has been deleted:
|
||||
|
||||
```
|
||||
On branch main
|
||||
Your branch is up to date with 'origin/main'.
|
||||
|
||||
Changes to be committed:
|
||||
(use "git reset HEAD <file>..." to unstage)
|
||||
|
||||
deleted: some_file.txt
|
||||
```
|
||||
|
||||
### Discard changes for a file
|
||||
|
||||
In case that you've made a mistake and you want to discard the changes for a specific file and reset the content of that file as it was in the latest commit, you need to use the command below:
|
||||
|
||||
```bash
|
||||
git checkout -- file_name
|
||||
```
|
||||
|
||||
This is a convenient command as you can quickly revert a file to its original content.
|
||||
|
||||
### Commit to local
|
||||
|
||||
Once you've made your changes and you've staged them with the `git add` command, you need to commit your changes.
|
||||
|
||||
To do so, you have to use the `git commit` command:
|
||||
|
||||
```bash
|
||||
git commit
|
||||
```
|
||||
|
||||
This will open a text editor where you could type your commit message.
|
||||
|
||||
Instead, you could use the `-m` flag to specify the commit message directly in your command:
|
||||
|
||||
```bash
|
||||
git commit -m "Nice commit message here"
|
||||
```
|
||||
|
||||
### List branches
|
||||
|
||||
To list all of the available local branches, just run the following command:
|
||||
|
||||
```bash
|
||||
git branch -a
|
||||
```
|
||||
|
||||
You would get a list of both local and remote branches, the output would look like this:
|
||||
|
||||
```
|
||||
bugfix/nginx-www-server-name
|
||||
develop
|
||||
* main
|
||||
remotes/origin/HEAD -> origin/master
|
||||
remotes/origin/bugfix/nginx-www-server-name
|
||||
remotes/origin/develop
|
||||
remotes/origin/main
|
||||
```
|
||||
|
||||
The `remotes` keyword indicates that those branches are remote branches.
|
||||
|
||||
### Fetch changes from remote and merge the current branch with upstream
|
||||
|
||||
If you are working together with a team of developers working on the same project, more often than not, you would need to fetch the changes that your colleagues have made to have them locally on your PC.
|
||||
|
||||
To do that, all you need to do is to use the `git pull` command:
|
||||
|
||||
```bash
|
||||
git pull origin branch_name
|
||||
```
|
||||
|
||||
Note that this will also merge the new changes to the current branch that you are checked into.
|
||||
|
||||
### Create a new branch
|
||||
|
||||
To create a new branch, all you need to do is use the `git branch` command:
|
||||
|
||||
```bash
|
||||
git branch branch_name
|
||||
```
|
||||
|
||||
Instead of the above, I prefer using the following command as it creates a new branch and also switches you to the newly created branch:
|
||||
|
||||
```bash
|
||||
git checkout -b branch_name
|
||||
```
|
||||
|
||||
If the `branch_name` already exists, you would get a warning that the branch name exists and you would not be checked out to it,
|
||||
|
||||
### Push local changes to remote
|
||||
|
||||
Then finally, once you've made all of your changes, you've staged them with the `git add .` command, and then you committed the changes with the `git commit` command, you have to push those changes to the remote git repository.
|
||||
|
||||
To do so, just use the `git push` command:
|
||||
|
||||
```bash
|
||||
git push origin branch_name
|
||||
```
|
||||
|
||||
### Delete a branch
|
||||
|
||||
```bash
|
||||
git branch -d branch_name
|
||||
```
|
||||
|
||||
### Switch to a new branch
|
||||
|
||||
```bash
|
||||
git checkout branch_name
|
||||
```
|
||||
|
||||
As mentioned above, if you add the `-b` flag, it would create the branch if it does not exist.
|
||||
|
||||
### Conclusion
|
||||
|
||||
Knowing the above commands will let you manage your project like a pro!
|
||||
|
||||
If you are interested in improving your command line skills in general, I strongly recommend this [Linux Command-line basics course here](https://devdojo.com/course/linux-command-line-basics)!
|
||||
@@ -1,59 +0,0 @@
|
||||
# The `cal` Command
|
||||
The `cal` command displays a formatted calendar in the terminal. If no options are specified, cal displays the current month, with the current day highlighted.
|
||||
|
||||
### Syntax:
|
||||
```
|
||||
cal [general options] [-jy] [[month] year]
|
||||
```
|
||||
|
||||
### Options:
|
||||
|**Option**|**Description**|
|
||||
|:--|:--|
|
||||
|`-h`|Don't highlight today's date.|
|
||||
|`-m month`|Specify a month to display. The month specifier is a full month name (e.g., February), a month abbreviation of at least three letters (e.g., Feb), or a number (e.g., 2). If you specify a number, followed by the letter "f" or "p", the month of the following or previous year, respectively, display. For instance, `-m 2f` displays February of next year.|
|
||||
|`-y year`|Specify a year to display. For example, `-y 1970` displays the entire calendar of the year 1970.|
|
||||
|`-3`|Display last month, this month, and next month.|
|
||||
|`-1`|Display only this month. This is the default.|
|
||||
|`-A num`|Display num months occurring after any months already specified. For example, `-3 -A 3` displays last month, this month, and four months after this one; and `-y 1970 -A 2` displays every month in 1970, and the first two months of 1971.|
|
||||
|`-B num`|Display num months occurring before any months already specified. For example, `-3 -B 2` displays the previous three months, this month, and next month.|
|
||||
|`-d YYYY-MM`|Operate as if the current month is number MM of year YYYY.|
|
||||
|
||||
### Examples:
|
||||
1. Display the calendar for this month, with today highlighted.
|
||||
```
|
||||
cal
|
||||
```
|
||||
|
||||
2. Same as the previous command, but do not highlight today.
|
||||
```
|
||||
cal -h
|
||||
```
|
||||
|
||||
3. Display last month, this month, and next month.
|
||||
```
|
||||
cal -3
|
||||
```
|
||||
4. Display this entire year's calendar.
|
||||
```
|
||||
cal -y
|
||||
```
|
||||
|
||||
5. Display the entire year 2000 calendar.
|
||||
```
|
||||
cal -y 2000
|
||||
```
|
||||
|
||||
6. Same as the previous command.
|
||||
```
|
||||
cal 2000
|
||||
```
|
||||
|
||||
7. Display the calendar for December of this year.
|
||||
```
|
||||
cal -m [December, Dec, or 12]
|
||||
```
|
||||
|
||||
10. Display the calendar for December 2000.
|
||||
```
|
||||
cal 12 2000
|
||||
```
|
||||
@@ -1,94 +0,0 @@
|
||||
# The `bc` command
|
||||
|
||||
The `bc` command provides the functionality of being able to perform mathematical calculations through the command line.
|
||||
|
||||
### Examples:
|
||||
|
||||
1 . Arithmetic:
|
||||
|
||||
```
|
||||
Input : $ echo "11+5" | bc
|
||||
Output : 16
|
||||
```
|
||||
2 . Increment:
|
||||
- var –++ : Post increment operator, the result of the variable is used first and then the variable is incremented.
|
||||
- – ++var : Pre increment operator, the variable is increased first and then the result of the variable is stored.
|
||||
|
||||
```
|
||||
Input: $ echo "var=3;++var" | bc
|
||||
Output: 4
|
||||
```
|
||||
3 . Decrement:
|
||||
- var – – : Post decrement operator, the result of the variable is used first and then the variable is decremented.
|
||||
- – – var : Pre decrement operator, the variable is decreased first and then the result of the variable is stored.
|
||||
|
||||
```
|
||||
Input: $ echo "var=3;--var" | bc
|
||||
Output: 2
|
||||
```
|
||||
4 . Assignment:
|
||||
- var = value : Assign the value to the variable
|
||||
- var += value : similar to var = var + value
|
||||
- var -= value : similar to var = var – value
|
||||
- var *= value : similar to var = var * value
|
||||
- var /= value : similar to var = var / value
|
||||
- var ^= value : similar to var = var ^ value
|
||||
- var %= value : similar to var = var % value
|
||||
|
||||
```
|
||||
Input: $ echo "var=4;var" | bc
|
||||
Output: 4
|
||||
```
|
||||
5 . Comparison or Relational:
|
||||
- If the comparison is true, then the result is 1. Otherwise,(false), returns 0
|
||||
- expr1<expr2 : Result is 1, if expr1 is strictly less than expr2.
|
||||
- expr1<=expr2 : Result is 1, if expr1 is less than or equal to expr2.
|
||||
- expr1>expr2 : Result is 1, if expr1 is strictly greater than expr2.
|
||||
- expr1>=expr2 : Result is 1, if expr1 is greater than or equal to expr2.
|
||||
- expr1==expr2 : Result is 1, if expr1 is equal to expr2.
|
||||
- expr1!=expr2 : Result is 1, if expr1 is not equal to expr2.
|
||||
|
||||
```
|
||||
Input: $ echo "6<4" | bc
|
||||
Output: 0
|
||||
```
|
||||
```
|
||||
Input: $ echo "2==2" | bc
|
||||
Output: 1
|
||||
```
|
||||
6 . Logical or Boolean:
|
||||
|
||||
- expr1 && expr2 : Result is 1, if both expressions are non-zero.
|
||||
- expr1 || expr2 : Result is 1, if either expression is non-zero.
|
||||
- ! expr : Result is 1, if expr is 0.
|
||||
|
||||
```
|
||||
Input: $ echo "! 1" | bc
|
||||
Output: 0
|
||||
|
||||
Input: $ echo "10 && 5" | bc
|
||||
Output: 1
|
||||
```
|
||||
|
||||
### Syntax:
|
||||
|
||||
```
|
||||
bc [ -hlwsqv ] [long-options] [ file ... ]
|
||||
```
|
||||
|
||||
### Additional Flags and their Functionalities:
|
||||
|
||||
*Note: This does not include an exhaustive list of options.*
|
||||
|
||||
|**Short Flag** |**Long Flag** |**Description** |
|
||||
|:---|:---|:---|
|
||||
|`-i`|`--interactive`|Force interactive mode|
|
||||
|`-l`|`--mathlib`|Use the predefined math routines|
|
||||
|`-q`|`--quiet`|Opens the interactive mode for bc without printing the header|
|
||||
|`-s`|`--standard`|Treat non-standard bc constructs as errors|
|
||||
|`-w`|`--warn`|Provides a warning if non-standard bc constructs are used|
|
||||
|
||||
### Notes:
|
||||
|
||||
1. The capabilities of `bc` can be further appreciated if used within a script. Aside from basic arithmetic operations, `bc` supports increments/decrements, complex calculations, logical comparisons, etc.
|
||||
2. Two of the flags in `bc` refer to non-standard constructs. If you evaluate `100>50 | bc` for example, you will get a strange warning. According to the POSIX page for bc, relational operators are only valid if used within an `if`, `while`, or `for` statement.
|
||||
@@ -1,31 +0,0 @@
|
||||
# The `help` command
|
||||
The `help` command displays information about builtin commands.
|
||||
Display information about builtin commands.
|
||||
|
||||
If a `PATTERN` is specified, this command gives detailed help on all commands matching the `PATTERN`, otherwise the list of available help topics is printed.
|
||||
|
||||
## Syntax
|
||||
```bash
|
||||
$ help [-dms] [PATTERN ...]
|
||||
```
|
||||
|
||||
## Options
|
||||
|**Option**|**Description**|
|
||||
|:--|:--|
|
||||
|`-d`|Output short description for each topic.|
|
||||
|`-m`|Display usage in pseudo-manpage format.|
|
||||
|`-s`|Output only a short usage synopsis for each topic matching the provided `PATTERN`.|
|
||||
|
||||
## Examples of uses:
|
||||
1. We get the complete information about the `cd` command
|
||||
```bash
|
||||
$ help cd
|
||||
```
|
||||
2. We get a short description about the `pwd` command
|
||||
```bash
|
||||
$ help -d pwd
|
||||
```
|
||||
3. We get the syntax of the `cd` command
|
||||
```bash
|
||||
$ help -s cd
|
||||
```
|
||||
@@ -1,29 +0,0 @@
|
||||
# The `factor` command
|
||||
The `factor` command prints the prime factors of each specified integer `NUMBER`. If none are specified on the command line, it will read them from the standard input.
|
||||
|
||||
## Syntax
|
||||
```bash
|
||||
$ factor [NUMBER]...
|
||||
```
|
||||
OR:
|
||||
```bash
|
||||
$ factor OPTION
|
||||
```
|
||||
|
||||
## Options
|
||||
|**Option**|**Description**|
|
||||
|:--|:--|
|
||||
|`--help`|Display this a help message and exit.|
|
||||
|`--version`|Output version information and exit.|
|
||||
|
||||
## Examples
|
||||
|
||||
1. Print prime factors of a prime number.
|
||||
```bash
|
||||
$ factor 50
|
||||
```
|
||||
|
||||
2. Print prime factors of a non-prime number.
|
||||
```bash
|
||||
$ factor 75
|
||||
```
|
||||
@@ -1,32 +0,0 @@
|
||||
# The `whatis` command
|
||||
|
||||
The `whatis` command is used to display one-line manual page descriptions for commands.
|
||||
It can be used to get a basic understanding of what a (unknown) command is used for.
|
||||
|
||||
### Examples of uses:
|
||||
|
||||
1. To display what `ls` is used for:
|
||||
|
||||
```
|
||||
whatis ls
|
||||
```
|
||||
|
||||
2. To display the use of all commands which start with `make`, execute the following:
|
||||
|
||||
```
|
||||
whatis -w make*
|
||||
```
|
||||
|
||||
### Syntax:
|
||||
|
||||
```
|
||||
whatis [-OPTION] [KEYWORD]
|
||||
```
|
||||
|
||||
### Additional Flags and their Functionalities:
|
||||
|
||||
|**Short Flag** |**Long Flag** |**Description** |
|
||||
|:---|:---|:---|
|
||||
|`-d`|`--debug`|Show debugging messages|
|
||||
|`-r`|`--regex`|Interpret each keyword as a regex|
|
||||
|`-w`|`--wildcard`|The keyword(s) contain wildcards|
|
||||
@@ -1,33 +0,0 @@
|
||||
# The `who` command
|
||||
|
||||
The `who` command lets you print out a list of logged-in users, the current run level of the system and the time of last system boot.
|
||||
|
||||
### Examples
|
||||
|
||||
1. Print out all details of currently logged-in users
|
||||
|
||||
```
|
||||
who -a
|
||||
```
|
||||
|
||||
2. Print out the list of all dead processes
|
||||
|
||||
```
|
||||
who -d -H
|
||||
```
|
||||
|
||||
### Syntax:
|
||||
|
||||
```
|
||||
who [options] [filename]
|
||||
```
|
||||
|
||||
### Additional Flags and their Functionalities
|
||||
|
||||
|**Short Flag** |**Description** |
|
||||
|---|---|
|
||||
| `-r` |prints all the current runlevel |
|
||||
| `-d` |print all the dead processes |
|
||||
|`-q`|print all the login names and total number of logged on users |
|
||||
|`-h`|print the heading of the columns displayed |
|
||||
|`-b`|print the time of last system boot |
|
||||
@@ -1,33 +0,0 @@
|
||||
018-the-free-command.md
|
||||
|
||||
# The `free` command
|
||||
|
||||
The `free` command in Linux/Unix is used to show memory (RAM/SWAP) information.
|
||||
|
||||
# Usage
|
||||
|
||||
## Show memory usage
|
||||
|
||||
**Action:**
|
||||
--- Output the memory usage - available and used, as well as swap
|
||||
|
||||
**Details:**
|
||||
--- Outputted values are not human-readable (are in bytes)
|
||||
|
||||
**Command:**
|
||||
```
|
||||
free
|
||||
```
|
||||
|
||||
## Show memory usage in human-readable form
|
||||
|
||||
**Action:**
|
||||
--- Output the memory usage - available and used, as well as swap
|
||||
|
||||
**Details:**
|
||||
--- Outputted values ARE human-readable (are in GB / MB)
|
||||
|
||||
**Command:**
|
||||
```
|
||||
free -h
|
||||
```
|
||||
@@ -1,19 +0,0 @@
|
||||
# The `sl` command
|
||||
|
||||
The `sl` command in Linux is a humorous program that runs a steam locomotive(sl) across your terminal.
|
||||
|
||||

|
||||
|
||||
## Installation
|
||||
|
||||
Install the package before running.
|
||||
|
||||
```
|
||||
sudo apt install sl
|
||||
```
|
||||
|
||||
## Syntax
|
||||
|
||||
```
|
||||
sl
|
||||
```
|
||||
@@ -1,76 +0,0 @@
|
||||
|
||||
# The `finger` command
|
||||
|
||||
The `finger` displays information about the system users.
|
||||
|
||||
### Examples:
|
||||
|
||||
1. View detail about a particular user.
|
||||
|
||||
```
|
||||
finger abc
|
||||
```
|
||||
*Output*
|
||||
```
|
||||
Login: abc Name: (null)
|
||||
Directory: /home/abc Shell: /bin/bash
|
||||
On since Mon Nov 1 18:45 (IST) on :0 (messages off)
|
||||
On since Mon Nov 1 18:46 (IST) on pts/0 from :0.0
|
||||
New mail received Fri May 7 10:33 2013 (IST)
|
||||
Unread since Sat Jun 7 12:59 2003 (IST)
|
||||
No Plan.
|
||||
```
|
||||
|
||||
2. View login details and Idle status about an user
|
||||
|
||||
```
|
||||
finger -s root
|
||||
```
|
||||
*Output*
|
||||
```
|
||||
Login Name Tty Idle Login Time Office Office Phone
|
||||
root root *1 19d Wed 17:45
|
||||
root root *2 3d Fri 16:53
|
||||
root root *3 Mon 20:20
|
||||
root root *ta 2 Tue 15:43
|
||||
root root *tb 2 Tue 15:44
|
||||
```
|
||||
### Syntax:
|
||||
|
||||
```
|
||||
finger [-l] [-m] [-p] [-s] [username]
|
||||
```
|
||||
|
||||
|
||||
### Additional Flags and their Functionalities:
|
||||
|
||||
|**Flag** |**Description** |
|
||||
|:---|:---|
|
||||
|`-l`|Force long output format.|
|
||||
|`-m`|Match arguments only on user name (not first or last name).|
|
||||
|`-p`|Suppress printing of the .plan file in a long format printout.|
|
||||
|`-s`|Force short output format.|
|
||||
|
||||
### Additional Information
|
||||
**Default Format**
|
||||
|
||||
The default format includes the following items:
|
||||
|
||||
Login name
|
||||
Full username
|
||||
Terminal name
|
||||
Write status (an * (asterisk) before the terminal name indicates that write permission is denied)
|
||||
For each user on the host, the default information list also includes, if known, the following items:
|
||||
|
||||
Idle time (Idle time is minutes if it is a single integer, hours and minutes if a : (colon) is present, or days and hours if a “d” is present.)
|
||||
Login time
|
||||
Site-specific information
|
||||
|
||||
**Longer Format**
|
||||
|
||||
A longer format is used by the finger command whenever a list of user’s names is given. (Account names as well as first and last names of users are accepted.) This format is multiline, and includes all the information described above along with the following:
|
||||
|
||||
User’s $HOME directory
|
||||
User’s login shell
|
||||
Contents of the .plan file in the user’s $HOME directory
|
||||
Contents of the .project file in the user’s $HOME directory
|
||||
@@ -1,56 +0,0 @@
|
||||
# The `w` command
|
||||
|
||||
The `w` command displays information about the users that are currently active on the machine and their [processes](https://www.computerhope.com/jargon/p/process.htm).
|
||||
|
||||
### Examples:
|
||||
|
||||
1. Running the `w` command without [arguments](https://www.computerhope.com/jargon/a/argument.htm) shows a list of logged on users and their processes.
|
||||
|
||||
```
|
||||
w
|
||||
```
|
||||
|
||||
|
||||
2. Show information for the user named *hope*.
|
||||
|
||||
```
|
||||
w hope
|
||||
```
|
||||
|
||||
### Syntax:
|
||||
|
||||
```
|
||||
finger [-l] [-m] [-p] [-s] [username]
|
||||
```
|
||||
|
||||
|
||||
### Additional Flags and their Functionalities:
|
||||
|
||||
|**Short Flag** |**Long Flag** |**Description** |
|
||||
|:---|:---|:---|
|
||||
|`-h`|`--no-header`|Don't print the header.|
|
||||
|`-u`|`--no-current`|Ignores the username while figuring out the current process and cpu times. *(To see an example of this, switch to the root user with `su` and then run both `w` and `w -u`.)*|
|
||||
|`-s`|`--short`|Display abbreviated output *(don't print the login time, JCPU or PCPU times).*|
|
||||
|`-f`|`--from`|Toggle printing the from *(remote hostname)* field. The default as released is for the from field to not be printed, although your system administrator or distribution maintainer may have compiled a version where the from field is shown by default.|
|
||||
|`--help`|<center>-</center>|Display a help message, and exit.|
|
||||
|`-V`|`--version`|Display version information, and exit.|
|
||||
|`-o`|`--old-style`|Old style output *(prints blank space for idle times less than one minute)*.|
|
||||
|*`user`*|<center>-</center>|Show information about the specified the user only.|
|
||||
|
||||
|
||||
### Additional Information
|
||||
|
||||
The [header](https://www.computerhope.com/jargon/h/header.htm) of the output shows (in this order): the current time, how long the system has been running, how many users are currently logged on, and the system [load](https://www.computerhope.com/jargon/l/load.htm) averages for the past 1, 5, and 15 minutes.
|
||||
|
||||
The following entries are displayed for each user:
|
||||
- login name the [tty](https://www.computerhope.com/jargon/t/tty.htm)
|
||||
- name the [remote](https://www.computerhope.com/jargon/r/remote.htm)
|
||||
- [host](https://www.computerhope.com/jargon/h/hostcomp.htm) they are
|
||||
- logged in from the amount of time they are logged in their
|
||||
- [idle](https://www.computerhope.com/jargon/i/idle.htm) time JCPU
|
||||
- PCPU
|
||||
- [command line](https://www.computerhope.com/jargon/c/commandi.htm) of their current process
|
||||
|
||||
The JCPU time is the time used by all processes attached to the tty. It does not include past background jobs, but does include currently running background jobs.
|
||||
|
||||
The PCPU time is the time used by the current process, named in the "what" field.
|
||||
@@ -1,28 +0,0 @@
|
||||
# The `login` Command
|
||||
|
||||
The `login` command initiates a user session.
|
||||
|
||||
## Syntax
|
||||
|
||||
```bash
|
||||
$ login [-p] [-h host] [-H] [-f username|username]
|
||||
```
|
||||
|
||||
## Flags and their functionalities
|
||||
|
||||
|**Short Flag** |**Description** |
|
||||
|---|---|
|
||||
| `-f` |Used to skip a login authentication. This option is usually used by the getty(8) autologin feature. |
|
||||
| `-h` | Used by other servers (such as telnetd(8) to pass the name of the remote host to login so that it can be placed in utmp and wtmp. Only the superuser is allowed use this option. |
|
||||
|`-p`|Used by getty(8) to tell login to preserve the environment. |
|
||||
|`-H`|Used by other servers (for example, telnetd(8)) to tell login that printing the hostname should be suppressed in the login: prompt. |
|
||||
|`--help`|Display help text and exit.|
|
||||
|`-v`|Display version information and exit.|
|
||||
|
||||
## Examples
|
||||
|
||||
To log in to the system as user abhishek, enter the following at the login prompt:
|
||||
```bash
|
||||
$ login: abhishek
|
||||
```
|
||||
If a password is defined, the password prompt appears. Enter your password at this prompt.
|
||||
@@ -1,52 +0,0 @@
|
||||
# `lscpu` command
|
||||
|
||||
`lscpu` in Linux/Unix is used to display CPU Architecture info. `lscpu` gathers CPU architecture information from `sysfs` and `/proc/cpuinfo` files.
|
||||
|
||||
For example :
|
||||
```
|
||||
manish@godsmack:~$ lscpu
|
||||
Architecture: x86_64
|
||||
CPU op-mode(s): 32-bit, 64-bit
|
||||
Byte Order: Little Endian
|
||||
CPU(s): 4
|
||||
On-line CPU(s) list: 0-3
|
||||
Thread(s) per core: 2
|
||||
Core(s) per socket: 2
|
||||
Socket(s): 1
|
||||
NUMA node(s): 1
|
||||
Vendor ID: GenuineIntel
|
||||
CPU family: 6
|
||||
Model: 142
|
||||
Model name: Intel(R) Core(TM) i5-7200U CPU @ 2.50GHz
|
||||
Stepping: 9
|
||||
CPU MHz: 700.024
|
||||
CPU max MHz: 3100.0000
|
||||
CPU min MHz: 400.0000
|
||||
BogoMIPS: 5399.81
|
||||
Virtualization: VT-x
|
||||
L1d cache: 32K
|
||||
L1i cache: 32K
|
||||
L2 cache: 256K
|
||||
L3 cache: 3072K
|
||||
NUMA node0 CPU(s): 0-3
|
||||
```
|
||||
|
||||
|
||||
## Options
|
||||
|
||||
`-a, --all`
|
||||
Include lines for online and offline CPUs in the output (default for -e). This option may only specified together with option -e or -p.
|
||||
For example: `lsof -a`
|
||||
|
||||
`-b, --online`
|
||||
Limit the output to online CPUs (default for -p). This option may only be specified together with option -e or -p.
|
||||
For example: `lscpu -b`
|
||||
|
||||
`-c, --offline`
|
||||
Limit the output to offline CPUs. This option may only be specified together with option -e or -p.
|
||||
|
||||
`-e, --extended [=list]`
|
||||
Display the CPU information in human readable format.
|
||||
For example: `lsof -e`
|
||||
|
||||
For more info: use `man lscpu` or `lscpu --help`
|
||||
@@ -1,37 +0,0 @@
|
||||
# The `printenv` command
|
||||
|
||||
The `printenv` prints the values of the specified [environment _VARIABLE(s)_](https://www.computerhope.com/jargon/e/envivari.htm). If no [_VARIABLE_](https://www.computerhope.com/jargon/v/variable.htm) is specified, print name and value pairs for them all.
|
||||
|
||||
### Examples:
|
||||
|
||||
1. Display the values of all environment variables.
|
||||
|
||||
```
|
||||
printenv
|
||||
```
|
||||
|
||||
2. Display the location of the current user's [home directory](https://www.computerhope.com/jargon/h/homedir.htm).
|
||||
```
|
||||
printenv HOME
|
||||
```
|
||||
|
||||
3. To use the `--null` command line option as the terminating character between output entries.
|
||||
```
|
||||
printenv --null SHELL HOME
|
||||
```
|
||||
*NOTE: By default, the* `printenv` *command uses newline as the terminating character between output entries.*
|
||||
|
||||
|
||||
### Syntax:
|
||||
|
||||
```
|
||||
printenv [OPTION]... PATTERN...
|
||||
```
|
||||
|
||||
|
||||
### Additional Flags and their Functionalities:
|
||||
|
||||
|**Short Flag** |**Long Flag** |**Description** |
|
||||
|:---|:---|:---|
|
||||
|`-0`|`--null`|End each output line with **0** byte rather than [newline](https://www.computerhope.com/jargon/n/newline.htm).|
|
||||
|`--help`|<center>-</center>|Display a help message, and exit.|
|
||||
@@ -1,39 +0,0 @@
|
||||
# The `ip` command
|
||||
|
||||
The `ip` command is present in the net-tools which is used for performing several network administration tasks. IP stands for Internet Protocol. This command is used to show or manipulate routing, devices, and tunnels. It can perform tasks like configuring and modifying the default and static routing, setting up tunnel over IP, listing IP addresses and property information, modifying the status of the interface, assigning, deleting and setting up IP addresses and routes.
|
||||
|
||||
### Examples:
|
||||
|
||||
1. To assign an IP Address to a specific interface (eth1) :
|
||||
|
||||
```
|
||||
ip addr add 192.168.50.5 dev eth1
|
||||
```
|
||||
|
||||
2. To show detailed information about network interfaces like IP Address, MAC Address information etc. :
|
||||
|
||||
```
|
||||
ip addr show
|
||||
```
|
||||
|
||||
### Syntax:
|
||||
|
||||
```
|
||||
ip [ OPTIONS ] OBJECT { COMMAND | help }
|
||||
```
|
||||
|
||||
|
||||
### Additional Flags and their Functionalities:
|
||||
|
||||
|**Flag** |**Description** |
|
||||
|:---|:---|
|
||||
|`-a`| Display and modify IP Addresses |
|
||||
|`-l`|Display and modify network interfaces |
|
||||
|`-r`|Display and alter the routing table|
|
||||
|`-n`|Display and manipulate neighbor objects (ARP table) |
|
||||
|`-ru`|Rule in routing policy database.|
|
||||
|`-s`|Output more information. If the option appears twice or more, the amount of information increases |
|
||||
|`-f`|Specifies the protocol family to use|
|
||||
|`-r`|Use the system's name resolver to print DNS names instead of host addresses|
|
||||
|`-c`|To configure color output |
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
# The `last` command
|
||||
|
||||
This command shows you a list of all the users that have logged in and out since the creation of the `var/log/wtmp` file. There are also some parameters you can add which will show you for example when a certain user has logged in and how long he was logged in for.
|
||||
|
||||
If you want to see the last 5 logs, just add `-5` to the command like this:
|
||||
|
||||
```
|
||||
last -5
|
||||
```
|
||||
|
||||
And if you want to see the last 10, add `-10`.
|
||||
|
||||
Another cool thing you can do is if you add `-F` you can see the login and logout time including the dates.
|
||||
|
||||
```
|
||||
last -F
|
||||
```
|
||||
|
||||
There are quite a lot of stuff you can view with this command. If you need to find out more about this command you can run:
|
||||
|
||||
```
|
||||
last --help
|
||||
```
|
||||
@@ -1,93 +0,0 @@
|
||||
# The `locate` command
|
||||
|
||||
The `locate` command searches the file system for files and directories whose name matches a given pattern through a database file that is generated by the `updatedb` command.
|
||||
|
||||
### Examples:
|
||||
|
||||
1. Running the `locate` command to search for a file named `.bashrc`.
|
||||
|
||||
```
|
||||
locate .bashrc
|
||||
```
|
||||
*Output*
|
||||
```
|
||||
/etc/bash.bashrc
|
||||
/etc/skel/.bashrc
|
||||
/home/linuxize/.bashrc
|
||||
/usr/share/base-files/dot.bashrc
|
||||
/usr/share/doc/adduser/examples/adduser.local.conf.examples/bash.bashrc
|
||||
/usr/share/doc/adduser/examples/adduser.local.conf.examples/skel/dot.bashrc
|
||||
```
|
||||
The `/root/.bashrc` file will not be shown because we ran the command as a normal user that doesn’t have access permissions to the `/root` directory.
|
||||
|
||||
If the result list is long, for better readability, you can pipe the output to the [`less`](https://linuxize.com/post/less-command-in-linux/) command:
|
||||
|
||||
```
|
||||
locate .bashrc | less
|
||||
```
|
||||
|
||||
2. To search for all `.md` files on the system
|
||||
```
|
||||
locate *.md
|
||||
```
|
||||
3. To search all `.py` files and display only 10 results
|
||||
```
|
||||
locate -n 10 *.py
|
||||
```
|
||||
4. To performs case-insensitive search.
|
||||
```
|
||||
locate -i readme.md
|
||||
```
|
||||
*Output*
|
||||
```
|
||||
/home/linuxize/p1/readme.md
|
||||
/home/linuxize/p2/README.md
|
||||
/home/linuxize/p3/ReadMe.md
|
||||
```
|
||||
5. To return the number of all files containing `.bashrc` in their name.
|
||||
```
|
||||
locate -c .bashrc
|
||||
```
|
||||
*Output*
|
||||
```
|
||||
6
|
||||
```
|
||||
6. The following would return only the existing `.json` files on the file system.
|
||||
```
|
||||
locate -e *.json
|
||||
```
|
||||
7. To run a more complex search the `-r` (`--regexp`) option is used.
|
||||
To search for all `.mp4` and `.avi` files on your system and ignore case.
|
||||
```
|
||||
locate --regex -i "(\.mp4|\.avi)"
|
||||
```
|
||||
|
||||
### Syntax:
|
||||
|
||||
```
|
||||
1. locate [OPTION]... PATTERN...
|
||||
```
|
||||
|
||||
|
||||
### Additional Flags and their Functionalities:
|
||||
|
||||
|**Short Flag** |**Long Flag** |**Description** |
|
||||
|:---|:---|:---|
|
||||
|`-A`|`--all`|It is used to display only entries that match all PATTERNs instead of requiring only one of them to match.|
|
||||
|`-b`|`--basename`|It is used to match only the base name against the specified patterns.|
|
||||
|`-c`|`--count`|It is used for writing the number matching entries instead of writing file names on standard output.|
|
||||
|`-d`|`--database DBPATH`|It is used to replace the default database with DBPATH.|
|
||||
|`-e`|`--existing`|It is used to display only entries that refer to existing files during the command is executed.|
|
||||
|`-L`|`--follow`|If the `--existing` option is specified, It is used for checking whether files exist and follow trailing symbolic links. It will omit the broken symbolic links to the output. This is the default behavior. The opposite behavior can be specified using the `--nofollow` option.|
|
||||
|`-h`|`--help`|It is used to display the help documentation that contains a summary of the available options.|
|
||||
|`-i`|`--ignore-case`|It is used to ignore case sensitivity of the specified patterns.|
|
||||
|`-p`|`--ignore-spaces`|It is used to ignore punctuation and spaces when matching patterns.|
|
||||
|`-t`|`--transliterate`|It is used to ignore accents using iconv transliteration when matching patterns.|
|
||||
|`-l`|`--limit, -n LIMIT`|If this option is specified, the command exit successfully after finding LIMIT entries.|
|
||||
|`-m`|`--mmap`|It is used to ignore the compatibility with BSD, and GNU locate.|
|
||||
|`-0`|`--null`|It is used to separate the entries on output using the ASCII NUL character instead of writing each entry on a separate line.|
|
||||
|`-S`|`--statistics`|It is used to write statistics about each read database to standard output instead of searching for files.|
|
||||
|`-r`|`--regexp REGEXP`|It is used for searching a basic regexp REGEXP.|
|
||||
|`--regex`|<center>-</center>|It is used to describe all PATTERNs as extended regular expressions.|
|
||||
|`-V`|`--version`|It is used to display the version and license information.|
|
||||
|`-w`|` --wholename`|It is used for matching only the whole path name in specified patterns.|
|
||||
@@ -1,47 +0,0 @@
|
||||
# The `iostat` command
|
||||
|
||||
The `iostat` command in Linux is used for monitoring system input/output statistics for devices and partitions. It monitors system input/output by observing the time the devices are active in relation to their average transfer rates. The iostat produce reports may be used to change the system configuration to raised balance the input/output between the physical disks. iostat is being included in sysstat package. If you don’t have it, you need to install first.
|
||||
|
||||
### Syntax:
|
||||
|
||||
```[linux]
|
||||
iostat [ -c ] [ -d ] [ -h ] [ -N ] [ -k | -m ] [ -t ] [ -V ] [ -x ]
|
||||
[ -z ] [ [ [ -T ] -g group_name ] { device [...] | ALL } ]
|
||||
[ -p [ device [,...] | ALL ] ] [ interval [ count ] ]
|
||||
```
|
||||
|
||||
### Examples:
|
||||
|
||||
1. Display a single history-since-boot report for all CPU and Devices:
|
||||
```[linux]
|
||||
iostat -d 2
|
||||
```
|
||||
|
||||
2. Display a continuous device report at two-second intervals:
|
||||
```[linux]
|
||||
iostat -d 2 6
|
||||
```
|
||||
|
||||
3.Display, for all devices, six reports at two-second intervals:
|
||||
```[linux]
|
||||
iostat -x sda sdb 2 6
|
||||
```
|
||||
|
||||
4.Display, for devices sda and sdb, six extended reports at two-second intervals:
|
||||
```[linux]
|
||||
iostat -p sda 2 6
|
||||
```
|
||||
|
||||
### Additional Flags and their Functionalities:
|
||||
|
||||
| **Short Flag** | **Description** |
|
||||
| :------------------------------ | :--------------------------------------------------------- |
|
||||
| `-x` | Show more details statistics information. |
|
||||
| `-c` | Show only the cpu statistic. |
|
||||
| `-d` | Display only the device report |
|
||||
| `-xd | Show extended I/O statistic for device only. |
|
||||
| `-k` | Capture the statistics in kilobytes or megabytes. |
|
||||
| `-k23` | Display cpu and device statistics with delay. |
|
||||
| `-j ID mmcbkl0 sda6 -x -m 2 2` | Display persistent device name statistics. |
|
||||
| `-p ` | Display statistics for block devices. |
|
||||
| `-N ` | Display lvm2 statistic information. |
|
||||
@@ -1,77 +0,0 @@
|
||||
# The `sort` command
|
||||
|
||||
the `sort` command is used to sort a file, arranging the records in a particular order. By default, the sort command sorts a file assuming the contents are ASCII. Using options in the sort command can also be used to sort numerically.
|
||||
|
||||
### Examples:
|
||||
|
||||
Suppose you create a data file with name file.txt:
|
||||
```
|
||||
Command :
|
||||
$ cat > file.txt
|
||||
abhishek
|
||||
chitransh
|
||||
satish
|
||||
rajan
|
||||
naveen
|
||||
divyam
|
||||
harsh
|
||||
```
|
||||
|
||||
Sorting a file: Now use the sort command
|
||||
|
||||
Syntax :
|
||||
|
||||
```
|
||||
sort filename.txt
|
||||
```
|
||||
|
||||
```
|
||||
Command:
|
||||
$ sort file.txt
|
||||
|
||||
Output :
|
||||
abhishek
|
||||
chitransh
|
||||
divyam
|
||||
harsh
|
||||
naveen
|
||||
rajan
|
||||
satish
|
||||
```
|
||||
|
||||
Note: This command does not actually change the input file, i.e. file.txt.
|
||||
|
||||
|
||||
### The sort function on a file with mixed case content
|
||||
|
||||
i.e. uppercase and lower case: When we have a mix file with both uppercase and lowercase letters then first the upper case letters would be sorted following with the lower case letters.
|
||||
|
||||
|
||||
Example:
|
||||
|
||||
Create a file mix.txt
|
||||
|
||||
|
||||
```
|
||||
Command :
|
||||
$ cat > mix.txt
|
||||
abc
|
||||
apple
|
||||
BALL
|
||||
Abc
|
||||
bat
|
||||
```
|
||||
Now use the sort command
|
||||
|
||||
```
|
||||
Command :
|
||||
$ sort mix.txt
|
||||
Output :
|
||||
Abc
|
||||
BALL
|
||||
abc
|
||||
apple
|
||||
bat
|
||||
```
|
||||
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
# The `paste` command
|
||||
|
||||
The `paste` command writes lines of two or more files, sequentially and separated by TABs, to the standard output
|
||||
|
||||
### Syntax:
|
||||
|
||||
```[linux]
|
||||
paste [OPTIONS]... [FILE]...
|
||||
```
|
||||
|
||||
### Examples:
|
||||
|
||||
1. To paste two files
|
||||
|
||||
```[linux]
|
||||
paste file1 file2
|
||||
```
|
||||
|
||||
2. To paste two files using new line as delimiter
|
||||
|
||||
```[linux]
|
||||
paste -d '\n' file1 file2
|
||||
```
|
||||
|
||||
### Additional Flags and their Functionalities:
|
||||
|
||||
| **Short Flag** | **Long Flag** | **Description** |
|
||||
| :----------------- | :-------------------------- | :-------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `-d` | `--delimiter` | use charater of TAB |
|
||||
| `-s` | `--serial` | paste one file at a time instead of in parallel |
|
||||
| `-z` | `--zero-terminated` | set line delimiter to NUL, not newline |
|
||||
| | `--help` | print command help |
|
||||
| | `--version` | print version information |
|
||||
@@ -1,24 +0,0 @@
|
||||
# The `iptables` Command
|
||||
|
||||
The `iptables` command is used to set up and maintain tables for the Netfilter firewall for IPv4, included in the Linux kernel. The firewall matches packets with rules defined in these tables and then takes the specified action on a possible match.
|
||||
|
||||
### Syntax:
|
||||
```
|
||||
iptables --table TABLE -A/-C/-D... CHAIN rule --jump Target
|
||||
```
|
||||
|
||||
### Example and Explanation:
|
||||
*This command will append to the chain provided in parameters:*
|
||||
```
|
||||
iptables [-t table] --append [chain] [parameters]
|
||||
```
|
||||
|
||||
*This command drops all the traffic coming on any port:*
|
||||
```
|
||||
iptables -t filter --append INPUT -j DROP
|
||||
```
|
||||
### Flags and their Functionalities:
|
||||
|Flag|Description|
|
||||
|:---|:---|
|
||||
|`-C`|Check if a rule is present in the chain or not. It returns 0 if the rule exists and returns 1 if it does not.|
|
||||
|`-A`|Append to the chain provided in parameters.|
|
||||
@@ -1,50 +0,0 @@
|
||||
# The `lsof` command
|
||||
|
||||
The `lsof` command shows **file infomation** of all the files opened by a running process. It's name is also derived from the fact that, list open files > `lsof`
|
||||
|
||||
An open file may be a regular file, a directory, a block special file, a character special file, an executing text reference, a library , a stream or a network file (Internet socket, NFS file or UNIX domain socket). A specific file or all the files in a file system may be selected by path.
|
||||
### Syntax:
|
||||
|
||||
```
|
||||
lsof [-OPTION] [USER_NAME]
|
||||
```
|
||||
|
||||
### Examples:
|
||||
|
||||
1. To show all the files opened by all active processes:
|
||||
|
||||
```
|
||||
lsof
|
||||
```
|
||||
|
||||
2. To show the files opened by a particular user:
|
||||
|
||||
```
|
||||
lsof -u [USER_NAME]
|
||||
```
|
||||
|
||||
|
||||
3. To list the processes with opened files under a specified directory:
|
||||
|
||||
```
|
||||
lsof +d [PATH_TO_DIR]
|
||||
```
|
||||
|
||||
### Options and their Functionalities:
|
||||
|
||||
|**Option** |**Additional Options** |**Description** |
|
||||
|:---|:---|:---|
|
||||
|`-i`|`tcp`/ `udp`/ `:port`|List all network connections running, Additionally, on udp/tcp or on specified port.|
|
||||
|`-i4`|<center>-</center>|List all processes with ipv4 connections.|
|
||||
|`-i6`|<center>-</center>|List all processes with ipv6 connections.|
|
||||
|`-c`|`[PROCESS_NAME]`|List all the files of a particular process with given name.|
|
||||
|`-p`|`[PROCESS_ID]`|List all the files opened by a specified process id.|
|
||||
|`-p`|`^[PROCESS_ID]`|List all the files that are not opened by a specified process id.|
|
||||
|`+d`|`[PATH]`|List the processes with opened files under a specified directory|
|
||||
|`+R`|<center>-</center>|List the files opened by parent process Id.|
|
||||
|
||||
### Help Command
|
||||
Run below command to view the complete guide to `lsof` command.
|
||||
```
|
||||
man lsof
|
||||
```
|
||||
@@ -1,57 +0,0 @@
|
||||
# The `bzip2` command
|
||||
|
||||
The `bzip2` command lets you compress and decompress the files i.e. it helps in binding the files into a single file which takes less storage space as the original file use to take.
|
||||
|
||||
### Syntax:
|
||||
|
||||
```
|
||||
bzip2 [OPTIONS] filenames ...
|
||||
```
|
||||
|
||||
#### Note : Each file is replaced by a compressed version of itself, with the name original name of the file followed by extension bz2.
|
||||
|
||||
### Options and their Functionalities:
|
||||
|
||||
|**Option** |**Alias** |**Description** |
|
||||
|:---|:---|:---|
|
||||
|`-d`|`--decompress`|to decompress compressed file|
|
||||
|`-f`|`--force`|to force overwrite an existing output file|
|
||||
|`-h`|`--help`|to display the help message and exit|
|
||||
|`-k`|`--keep`|to enable file compression, doesn't deletes the original input file|
|
||||
|`-L`|`--license`|to display the license terms and conditions|
|
||||
|`-q`|`--quiet`|to suppress non-essential warning messages|
|
||||
|`-t`|`--test`|to check integrity of the specified .bz2 file, but don't want to decompress them|
|
||||
|`-v`|`--erbose`|to display details for each compression operation|
|
||||
|`-V`|`--version`|to display the software version|
|
||||
|`-z`|`--compress`|to enable file compression, but deletes the original input file|
|
||||
|
||||
|
||||
> #### By default, when bzip2 compresses a file, it deletes the original (or input) file. However, if you don't want that to happen, use the -k command line option.
|
||||
|
||||
### Examples:
|
||||
|
||||
1. To force compression:
|
||||
```
|
||||
bzip2 -z input.txt
|
||||
```
|
||||
**Note: This option deletes the original file also**
|
||||
|
||||
2. To force compression and also retain original input file:
|
||||
```
|
||||
bzip2 -k input.txt
|
||||
```
|
||||
|
||||
3. To force decompression:
|
||||
```
|
||||
bzip2 -d input.txt.bz2
|
||||
```
|
||||
|
||||
4. To test integrity of compressed file:
|
||||
```
|
||||
bzip2 -t input.txt.bz2
|
||||
```
|
||||
|
||||
5. To show the compression ratio for each file processed:
|
||||
```
|
||||
bzip2 -v input.txt
|
||||
```
|
||||
@@ -1,30 +0,0 @@
|
||||
# The `service` command
|
||||
|
||||
Service runs a System V init script in as predictable environment as possible, removing most environment variables and with current working directory set to /.
|
||||
|
||||
The SCRIPT parameter specifies a System V init script, located in /etc/init.d/SCRIPT. The supported values of COMMAND depend on the invoked script, service passes COMMAND and OPTIONS it to the init script unmodified. All scripts should support at least the start and stop commands. As a special case, if COMMAND is --full-restart, the script is run twice, first with the stop command, then with the start command.
|
||||
|
||||
The COMMAND can be at least start, stop, status, and restart.
|
||||
|
||||
service --status-all runs all init scripts, in alphabetical order, with the `status` command
|
||||
|
||||
Examples :
|
||||
|
||||
1. To check the status of all the running services:
|
||||
|
||||
```
|
||||
service --status-all
|
||||
```
|
||||
|
||||
2. To run a script
|
||||
|
||||
```
|
||||
service SCRIPT-Name start
|
||||
```
|
||||
|
||||
3. A more generalized command:
|
||||
|
||||
```
|
||||
service [SCRIPT] [COMMAND] [OPTIONS]
|
||||
|
||||
```
|
||||
@@ -1,25 +0,0 @@
|
||||
# The `vmstat` command
|
||||
|
||||
The `vmstat` command lets you monitor the performance of your system. It shows you information about your memory, disk, processes, CPU scheduling, paging, and block IO. This command is also referred to as **virtual memory statistic report**.
|
||||
|
||||
The very first report that is produced shows you the average details since the last reboot and after that, other reports are made which report over time.
|
||||
|
||||
### `vmstat`
|
||||
|
||||

|
||||
|
||||
As you can see it is a pretty useful little command. The most important things that we see above are the `free`, which shows us the free space that is not being used, `si` shows us how much memory is swapped in every second in kB, and `so` shows how much memory is swapped out each second in kB as well.
|
||||
|
||||
### `vmstat -a`
|
||||
|
||||
If we run `vmstat -a`, it will show us the active and inactive memory of the system running.
|
||||
|
||||

|
||||
|
||||
### `vmstat -d`
|
||||
|
||||
The `vmstat -d` command shows us all the disk statistics.
|
||||
|
||||

|
||||
|
||||
As you can see this is a pretty useful little command that shows you different statistics about your virtual memory
|
||||
@@ -1,57 +0,0 @@
|
||||
# The `mpstat` command
|
||||
|
||||
The `mpstat` command is used to report processor related statistics. It accurately displays the statistics of the CPU usage of the system and information about CPU utilization and performance.
|
||||
|
||||
### Syntax:
|
||||
|
||||
```
|
||||
mpstat [options] [<interval> [<count>]]
|
||||
```
|
||||
|
||||
#### Note : It initializes the first processor with CPU 0, the second one with CPU 1, and so on.
|
||||
|
||||
### Options and their Functionalities:
|
||||
|
||||
|**Option** |**Description** |
|
||||
|-------------|----------------------------------------------------------------------|
|
||||
|`-A` |to display all the detailed statistics |
|
||||
|`-h` |to display mpstat help |
|
||||
|`-I` |to display detailed interrupts statistics |
|
||||
|`-n` |to report summary CPU statistics based on NUMA node placement |
|
||||
|`-N` |to indicate the NUMA nodes for which statistics are to be reported |
|
||||
|`-P` |to indicate the processors for which statistics are to be reported |
|
||||
|`-o` |to display the statistics in JSON (Javascript Object Notation) format |
|
||||
|`-T` |to display topology elements in the CPU report |
|
||||
|`-u` |to report CPU utilization |
|
||||
|`-v` |to display utilization statistics at the virtual processor level |
|
||||
|`-V` |to display mpstat version |
|
||||
|`-ALL` |to display detailed statistics about all CPUs |
|
||||
|
||||
|
||||
### Examples:
|
||||
|
||||
1. To display processor and CPU statistics:
|
||||
```
|
||||
mpstat
|
||||
```
|
||||
|
||||
2. To display processor number of all CPUs:
|
||||
```
|
||||
mpstat -P ALL
|
||||
```
|
||||
|
||||
3. To get all the information which the tool may collect:
|
||||
```
|
||||
mpstat -A
|
||||
```
|
||||
|
||||
4. To display CPU utilization by a specific processor:
|
||||
```
|
||||
mpstat -P 0
|
||||
```
|
||||
|
||||
5. To display CPU usage with a time interval:
|
||||
```
|
||||
mpstat 1 5
|
||||
```
|
||||
**Note: This command will print 5 reports with 1 second time interval**
|
||||
@@ -1,36 +0,0 @@
|
||||
# The `ncdu` Command
|
||||
|
||||
`ncdu` (NCurses Disk Usage) is a curses-based version of the well-known `du` command. It provides a fast way to see what directories are using your disk space.
|
||||
|
||||
|
||||
## Example
|
||||
1. Quiet Mode
|
||||
```
|
||||
ncdu -q
|
||||
```
|
||||
|
||||
2. Omit mounted directories
|
||||
```
|
||||
ncdu -q -x
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Syntax
|
||||
```
|
||||
ncdu [-hqvx] [--exclude PATTERN] [-X FILE] dir
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
## Additional Flags and their Functionalities:
|
||||
|
||||
|Short Flag | Long Flag | Description|
|
||||
|---|---|---|
|
||||
| `-h`| - |Print a small help message|
|
||||
| `-q`| - |Quiet mode. While calculating disk space, ncdu will update the screen 10 times a second by default, this will be decreased to once every 2 seconds in quiet mode. Use this feature to save bandwidth over remote connections.|
|
||||
| `-v`| - |Print version.|
|
||||
| `-x`| - |Only count files and directories on the same filesystem as the specified dir.|
|
||||
| - | `--exclude PATTERN`|Exclude files that match PATTERN. This argument can be added multiple times to add more patterns.|
|
||||
| `-X FILE`| `--exclude-from FILE`| Exclude files that match any pattern in FILE. Patterns should be separated by a newline.|
|
||||
@@ -1,69 +0,0 @@
|
||||
# The `uniq` command
|
||||
|
||||
The `uniq` command in Linux is a command line utility that reports or filters out the repeated lines in a file.
|
||||
In simple words, `uniq` is the tool that helps you to detect the adjacent duplicate lines and also deletes the duplicate lines. It filters out the adjacent matching lines from the input file(that is required as an argument) and writes the filtered data to the output file .
|
||||
|
||||
### Examples:
|
||||
|
||||
In order to omit the repeated lines from a file, the syntax would be the following:
|
||||
|
||||
```
|
||||
uniq kt.txt
|
||||
```
|
||||
|
||||
In order to tell the number of times a line was repeated, the syntax would be the following:
|
||||
|
||||
```
|
||||
uniq -c kt.txt
|
||||
```
|
||||
|
||||
In order to print repeated lines, the syntax would be the following:
|
||||
|
||||
```
|
||||
uniq -d kt.txt
|
||||
```
|
||||
|
||||
In order to print unique lines, the syntax would be the following:
|
||||
|
||||
```
|
||||
uniq -u kt.txt
|
||||
```
|
||||
|
||||
In order to allows the N fields to be skipped while comparing uniqueness of the lines, the syntax would be the following:
|
||||
|
||||
```
|
||||
uniq -f 2 kt.txt
|
||||
```
|
||||
|
||||
In order to allows the N characters to be skipped while comparing uniqueness of the lines, the syntax would be the following:
|
||||
|
||||
```
|
||||
uniq -s 5 kt.txt
|
||||
```
|
||||
|
||||
In order to to make the comparison case-insensitive, the syntax would be the following:
|
||||
|
||||
```
|
||||
uniq -i kt.txt
|
||||
```
|
||||
|
||||
### Syntax:
|
||||
|
||||
```
|
||||
uniq [OPTION] [INPUT[OUTPUT]]
|
||||
```
|
||||
|
||||
### Possible options:
|
||||
|
||||
|**Flag** |**Description** |**Params** |
|
||||
|:---|:---|:---|
|
||||
|`-c`|It tells how many times a line was repeated by displaying a number as a prefix with the line.|-|
|
||||
|`-d`|It only prints the repeated lines and not the lines which aren’t repeated.|-|
|
||||
|`-i`|By default, comparisons done are case sensitive but with this option case insensitive comparisons can be made.|-|
|
||||
|`-f`|It allows you to skip N fields(a field is a group of characters, delimited by whitespace) of a line before determining uniqueness of a line.|N|
|
||||
|`-s`|It doesn’t compares the first N characters of each line while determining uniqueness. This is like the -f option, but it skips individual characters rather than fields.|N|
|
||||
|`-u`|It allows you to print only unique lines.|-|
|
||||
|`-z`|It will make a line end with 0 byte(NULL), instead of a newline.|-|
|
||||
|`-w`|It only compares N characters in a line.|N|
|
||||
|`--help`|It displays a help message and exit.|-|
|
||||
|`--version`|It displays version information and exit.|-|
|
||||
@@ -1,103 +0,0 @@
|
||||
# The `RPM` command
|
||||
|
||||
`rpm` - RPM Package Manager
|
||||
|
||||
`rpm` is a powerful __Package Manager__, which can be used to build, install, query, verify, update, and erase individual software packages. A __package__ consists of an archive of files and meta-data used to install and erase the archive files. The meta-data includes helper scripts, file attributes, and descriptive information about the package. Packages come in two varieties: binary packages, used to encapsulate software to be installed, and source packages, containing the source code and recipe necessary to produce binary packages.
|
||||
|
||||
One of the following basic modes must be selected: __Query, Verify, Signature Check, Install/Upgrade/Freshen, Uninstall, Initialize Database, Rebuild Database, Resign, Add Signature, Set Owners/Groups, Show Querytags, and Show Configuration.__
|
||||
|
||||
**General Options**
|
||||
|
||||
These options can be used in all the different modes.
|
||||
|
||||
|Short Flag| Long Flag| Description|
|
||||
|---|---|---|
|
||||
| -? | --help| Print a longer usage message then normal.|
|
||||
| - |--version |Print a single line containing the version number of rpm being used.|
|
||||
| - | --quiet | Print as little as possible - normally only error messages will be displayed.|
|
||||
| -v | - | Print verbose information - normally routine progress messages will be displayed.|
|
||||
| -vv | - | Print lots of ugly debugging information.|
|
||||
| - | --rcfile FILELIST | Each of the files in the colon separated FILELIST is read sequentially by rpm for configuration information. Only the first file in the list must exist, and tildes will be expanded to the value of $HOME. The default FILELIST is /usr/lib/rpm/rpmrc:/usr/lib/rpm/redhat/rpmrc:/etc/rpmrc:~/.rpmrc. |
|
||||
| - | --pipe CMD | Pipes the output of rpm to the command CMD. |
|
||||
| - | --dbpath DIRECTORY | Use the database in DIRECTORY rather than the default path /var/lib/rpm |
|
||||
| - | --root DIRECTORY | Use the file system tree rooted at DIRECTORY for all operations. Note that this means the database within DIRECTORY will be used for dependency checks and any scriptlet(s) (e.g. %post if installing, or %prep if building, a package) will be run after a chroot(2) to DIRECTORY. |
|
||||
| -D | --define='MACRO EXPR' | Defines MACRO with value EXPR.|
|
||||
| -E | --eval='EXPR' | Prints macro expansion of EXPR. |
|
||||
|
||||
|
||||
# Synopsis
|
||||
|
||||
## Querying and Verifying Packages:
|
||||
|
||||
```
|
||||
rpm {-q|--query} [select-options] [query-options]
|
||||
|
||||
rpm {-V|--verify} [select-options] [verify-options]
|
||||
|
||||
rpm --import PUBKEY ...
|
||||
|
||||
rpm {-K|--checksig} [--nosignature] [--nodigest] PACKAGE_FILE ...
|
||||
```
|
||||
|
||||
## Installing, Upgrading, and Removing Packages:
|
||||
|
||||
```
|
||||
rpm {-i|--install} [install-options] PACKAGE_FILE ...
|
||||
|
||||
rpm {-U|--upgrade} [install-options] PACKAGE_FILE ...
|
||||
|
||||
rpm {-F|--freshen} [install-options] PACKAGE_FILE ...
|
||||
|
||||
rpm {-e|--erase} [--allmatches] [--nodeps] [--noscripts] [--notriggers] [--test] PACKAGE_NAME ...
|
||||
```
|
||||
|
||||
## Miscellaneous:
|
||||
|
||||
```
|
||||
rpm {--initdb|--rebuilddb}
|
||||
|
||||
rpm {--addsign|--resign} PACKAGE_FILE...
|
||||
|
||||
rpm {--querytags|--showrc}
|
||||
|
||||
rpm {--setperms|--setugids} PACKAGE_NAME .
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### query-options
|
||||
|
||||
```
|
||||
[--changelog] [-c,--configfiles] [-d,--docfiles] [--dump]
|
||||
[--filesbypkg] [-i,--info] [--last] [-l,--list]
|
||||
[--provides] [--qf,--queryformat QUERYFMT]
|
||||
[-R,--requires] [--scripts] [-s,--state]
|
||||
[--triggers,--triggerscripts]
|
||||
```
|
||||
|
||||
### verify-options
|
||||
|
||||
```
|
||||
[--nodeps] [--nofiles] [--noscripts]
|
||||
[--nodigest] [--nosignature]
|
||||
[--nolinkto] [--nofiledigest] [--nosize] [--nouser]
|
||||
[--nogroup] [--nomtime] [--nomode] [--nordev]
|
||||
[--nocaps]
|
||||
```
|
||||
### install-options
|
||||
```
|
||||
[--aid] [--allfiles] [--badreloc] [--excludepath OLDPATH]
|
||||
[--excludedocs] [--force] [-h,--hash]
|
||||
[--ignoresize] [--ignorearch] [--ignoreos]
|
||||
[--includedocs] [--justdb] [--nodeps]
|
||||
[--nodigest] [--nosignature] [--nosuggest]
|
||||
[--noorder] [--noscripts] [--notriggers]
|
||||
[--oldpackage] [--percent] [--prefix NEWPATH]
|
||||
[--relocate OLDPATH=NEWPATH]
|
||||
[--replacefiles] [--replacepkgs]
|
||||
[--test]
|
||||
```
|
||||
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
# The `scp` command
|
||||
|
||||
SCP (secure copy) is a command-line utility that allows you to securely copy files and directories between two locations.
|
||||
|
||||
Both the files and passwords are encrypted so that anyone snooping on the traffic doesn't get anything sensitive.
|
||||
|
||||
### Different ways to copy a file or directory:
|
||||
|
||||
- From local system to a remote system.
|
||||
- From a remote system to a local system.
|
||||
- Between two remote systems from the local system.
|
||||
|
||||
### Examples:
|
||||
|
||||
1. To copy the files from a local system to a remote system:
|
||||
|
||||
```
|
||||
scp /home/documents/local-file root@{remote-ip-address}:/home/
|
||||
```
|
||||
|
||||
2. To copy the files from a remote system to the local system:
|
||||
```
|
||||
scp root@{remote-ip-address}:/home/remote-file /home/documents/
|
||||
```
|
||||
|
||||
3. To copy the files between two remote systems from the local system.
|
||||
```
|
||||
scp root@{remote1-ip-address}:/home/remote-file root@{remote2-ip-address}/home/
|
||||
```
|
||||
4. To copy file though a jump host server.
|
||||
```
|
||||
scp /home/documents/local-file -oProxyJump=<jump-host-ip> root@{remote-ip-address}/home/
|
||||
```
|
||||
On newer version of scp on some machines you can use the above command with a `-J` flag.
|
||||
```
|
||||
scp /home/documents/local-file -J <jump-host-ip> root@{remote-ip-address}/home/
|
||||
```
|
||||
|
||||
### Syntax:
|
||||
```
|
||||
scp [OPTION] [user@]SRC_HOST:]file1 [user@]DEST_HOST:]file2
|
||||
```
|
||||
- `OPTION` - scp options such as cipher, ssh configuration, ssh port, limit, recursive copy …etc.
|
||||
- `[user@]SRC_HOST:]file1` - Source file
|
||||
- `[user@]DEST_HOST:]file2` - Destination file
|
||||
|
||||
Local files should be specified using an absolute or relative path, while remote file names should include a user and host specification.
|
||||
|
||||
scp provides several that control every aspect of its behaviour. The most widely used options are:
|
||||
|
||||
|**Short Flag** |**Long Flag** |**Description** |
|
||||
|:---|:---|:---|
|
||||
|`-P`|<center>-</center>|Specifies the remote host ssh port.|
|
||||
|`-p`|<center>-</center>|Preserves files modification and access times.|
|
||||
|`-q`|<center>-</center>|Use this option if you want to suppress the progress meter and non-error messages.|
|
||||
|`-C`|<center>-</center>|This option forces scp to compresses the data as it is sent to the destination machine.|
|
||||
|`-r`|<center>-</center>|This option tells scp to copy directories recursively.|
|
||||
|
||||
### Before you begin
|
||||
|
||||
The `scp` command relies on `ssh` for data transfer, so it requires an `ssh key` or `password` to authenticate on the remote systems.
|
||||
|
||||
The `colon (:)` is how scp distinguish between local and remote locations.
|
||||
|
||||
To be able to copy files, you must have at least read permissions on the source file and write permission on the target system.
|
||||
|
||||
Be careful when copying files that share the same name and location on both systems, `scp` will overwrite files without warning.
|
||||
|
||||
When transferring large files, it is recommended to run the scp command inside a `screen` or `tmux` session.
|
||||
@@ -1,76 +0,0 @@
|
||||
# The `split` command
|
||||
|
||||
The `split` command in Linux is used to split a file into smaller files.
|
||||
|
||||
### Examples
|
||||
|
||||
1. Split a file into a smaller file using file name
|
||||
|
||||
```
|
||||
split filename.txt
|
||||
```
|
||||
|
||||
2. Split a file named filename into segments of 200 lines beginning with prefix file
|
||||
|
||||
```
|
||||
split -l 200 filename file
|
||||
```
|
||||
|
||||
This will create files of the name fileaa, fileab, fileac, filead, etc. of 200 lines.
|
||||
|
||||
3. Split a file named filename into segments of 40 bytes with prefix file
|
||||
|
||||
```
|
||||
split -b 40 filename file
|
||||
```
|
||||
|
||||
This will create files of the name fileaa, fileab, fileac, filead, etc. of 40 bytes.
|
||||
|
||||
4. Split a file using --verbose to see the files being created.
|
||||
|
||||
```
|
||||
split filename.txt --verbose
|
||||
```
|
||||
|
||||
### Syntax:
|
||||
|
||||
```
|
||||
split [options] filename [prefix]
|
||||
```
|
||||
|
||||
### Additional Flags and their Functionalities
|
||||
|
||||
|**Short Flag** |**Long Flag** |**Description** |
|
||||
|:---|:---|:---|
|
||||
|`-a`|`--suffix-length=N`|Generate suffixes of length N (default 2)|
|
||||
||`--additional-suffix=SUFFIX`|Append an additional SUFFIX to file names|
|
||||
|`-b`|`--bytes=SIZE`|Put SIZE bytes per output file|
|
||||
|`-C`|`--line-bytes=SIZE`|Put at most SIZE bytes of records per output file|
|
||||
|`-d`| |Use numeric suffixes starting at 0, not alphabetic|
|
||||
||`--numeric-suffixes[=FROM]`|Same as -d, but allow setting the start value|
|
||||
|`-x`||Use hex suffixes starting at 0, not alphabetic|
|
||||
||`--hex-suffixes[=FROM]`|Same as -x, but allow setting the start value|
|
||||
|`-e`|`--elide-empty-files`|Do not generate empty output files with '-n'|
|
||||
||`--filter=COMMAND`|Write to shell COMMAND;<br>file name is $FILE|
|
||||
|`-l`|`--lines=NUMBER`|Put NUMBER lines/records per output file|
|
||||
|`-n`|`--number=CHUNKS`|Generate CHUNKS output files;<br>see explanation below|
|
||||
|`-t`|`--separator=SEP`|Use SEP instead of newline as the record separator;<br>'\0' (zero) specifies the NUL character|
|
||||
|`-u`|`--unbuffered`|Immediately copy input to output with '-n r/...'|
|
||||
||`--verbose`|Print a diagnostic just before each<br>output file is opened|
|
||||
||`--help`|Display this help and exit|
|
||||
||`--version`|Output version information and exit|
|
||||
|
||||
The SIZE argument is an integer and optional unit (example: 10K is 10*1024).
|
||||
Units are K,M,G,T,P,E,Z,Y (powers of 1024) or KB,MB,... (powers of 1000).
|
||||
|
||||
CHUNKS may be:
|
||||
|**CHUNKS** |**Description** |
|
||||
|:---|:---|
|
||||
|`N`|Split into N files based on size of input|
|
||||
|`K/N`|Output Kth of N to stdout|
|
||||
|`l/N`|Split into N files without splitting lines/records|
|
||||
|`l/K/N`|Output Kth of N to stdout without splitting lines/records|
|
||||
|`r/N`|Like 'l' but use round robin distribution|
|
||||
|`r/K/N`|Likewise but only output Kth of N to stdout|
|
||||
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
# The `stat` command
|
||||
|
||||
The `stat` command lets you display file or file system status. It gives you useful information about the file (or directory) on which you use it.
|
||||
|
||||
### Examples:
|
||||
|
||||
1. Basic command usage
|
||||
|
||||
```
|
||||
stat file.txt
|
||||
```
|
||||
|
||||
2. Use the `-c` (or `--format`) argument to only display information you want to see (here, the total size, in bytes)
|
||||
|
||||
```
|
||||
stat file.txt -c %s
|
||||
```
|
||||
|
||||
### Syntax:
|
||||
|
||||
```
|
||||
stat [OPTION] [FILE]
|
||||
```
|
||||
|
||||
### Additional Flags and their Functionalities:
|
||||
|
||||
| Short Flag | Long Flag | Description |
|
||||
| ---------- | ----------------- | ----------------------------------------------------------------------------- |
|
||||
| `-L` | `--dereference` | Follow links |
|
||||
| `-f` | `--file-system` | Display file system status instead of file status |
|
||||
| `-c` | `--format=FORMAT` | Specify the format (see below) |
|
||||
| `-t` | `--terse` | Print the information in terse form |
|
||||
| - | `--cached=MODE` | Specify how to use cached attributes. Can be: `always`, `never`, or `default` |
|
||||
| - | `--printf=FORMAT` | Like `--format`, but interpret backslash escapes (`\n`, `\t`, ...) |
|
||||
| - | `--help` | Display the help and exit |
|
||||
| - | `--version` | Output version information and exit |
|
||||
|
||||
|
||||
### Example of Valid Format Sequences for Files:
|
||||
|
||||
| Format | Description |
|
||||
| ------ | ---------------------------------------------------- |
|
||||
| `%a` | Permission bits in octal |
|
||||
| `%A` | Permission bits and file type in human readable form |
|
||||
| `%d` | Device number in decimal |
|
||||
| `%D` | Device number in hex |
|
||||
| `%F` | File type |
|
||||
| `%g` | Group ID of owner |
|
||||
| `%G` | Group name of owner |
|
||||
| `%h` | Number of hard links |
|
||||
| `%i` | Inode number |
|
||||
| `%m` | Mount point |
|
||||
| `%n` | File name |
|
||||
| `%N` | Quoted file name with dereference if symbolic link |
|
||||
| `%s` | Total size, in bytes |
|
||||
| `%u` | User ID of owner |
|
||||
| `%U` | User name of owner |
|
||||
| `%w` | Time of file birth, human-readable; - if unknown |
|
||||
| `%x` | Time of last access, human-readable |
|
||||
| `%y` | Time of last data modification, human-readable |
|
||||
| `%z` | Time of last status change, human-readable |
|
||||
@@ -1,93 +0,0 @@
|
||||
# The `ionice` command
|
||||
|
||||
The `ionice` command is used to set or get process I/O scheduling class and priority.
|
||||
|
||||
If no arguments are given , `ionice` will query the current I/O scheduling class and priority for that process.
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
ionice [options] -p <pid>
|
||||
```
|
||||
|
||||
```
|
||||
ionice [options] -P <pgid>
|
||||
```
|
||||
|
||||
```
|
||||
ionice [options] -u <uid>
|
||||
```
|
||||
|
||||
```
|
||||
ionice [options] <command>
|
||||
```
|
||||
|
||||
## A process can be of three scheduling classes:
|
||||
- ### Idle
|
||||
|
||||
A program with idle I/O priority will only get disk time when `no other program has asked for disk I/O for a defined grace period`.
|
||||
|
||||
The impact of idle processes on normal system actively should be `zero`.
|
||||
|
||||
This scheduling class `doesn’t take priority` argument.
|
||||
|
||||
Presently this scheduling class is permitted for an `ordinary user (since kernel 2.6.25)`.
|
||||
- ### Best Effort
|
||||
|
||||
This is `effective` scheduling class for any process that has `not asked for a specific I/O priority`.
|
||||
|
||||
This class `takes priority argument from 0-7`, with `lower` number being `higher priority`.
|
||||
|
||||
Programs running at the same best effort priority are served in `round- robbin fashion`.
|
||||
|
||||
Note that before kernel 2.6.26 a process that has not asked for an I/O priority formally uses “None” as scheduling class , but the io schedular will treat such processes as if it were in the best effort class.
|
||||
|
||||
The priority within best effort class will be dynamically derived form the CPU nice level of the process : io_priority = ( cpu_nice + 20 ) / 5/
|
||||
for kernels after 2.6.26 with CFQ I/O schedular a process that has not asked for sn io priority inherits CPU scheduling class.
|
||||
|
||||
`The I/O priority is derived from the CPU nice level of the process` ( smr sd before kernel 2.6.26 ).
|
||||
|
||||
- ### Real Time
|
||||
|
||||
The real time schedular class is `given first access to disk, regardless of what else is going on in the system`.
|
||||
|
||||
Thus the real time class needs to be used with some care, as it cans tarve other processes .
|
||||
|
||||
As with the best effort class, `8 priority levels are defined denoting how big a time slice a given process will receive on each scheduling window`.
|
||||
|
||||
This scheduling class is `not permitted for an ordinary user(non-root)`.
|
||||
|
||||
## Options
|
||||
| Options | Description |
|
||||
|---|---|
|
||||
| -c, --class <class> | name or number of scheduling class, 0: none, 1: realtime, 2: best-effort, 3: idle|
|
||||
| -n, --classdata <num> | priority (0..7) in the specified scheduling class,only for the realtime and best-effort classes|
|
||||
| -p, --pid <pid>... | act on these already running processes|
|
||||
| -P, --pgid <pgrp>... | act on already running processes in these groups|
|
||||
| -t, --ignore | ignore failures|
|
||||
| -u, --uid <uid>... | act on already running processes owned by these users|
|
||||
| -h, --help | display this help|
|
||||
| -V, --version | display version|
|
||||
|
||||
For more details see ionice(1).
|
||||
|
||||
|
||||
## Examples
|
||||
| Command | O/P |Explanation|
|
||||
|---|---|---|
|
||||
|`$ ionice` |*none: prio 4*|Running alone `ionice` will give the class and priority of current process |
|
||||
|`$ ionice -p 101`|*none : prio 4*|Give the details(*class : priority*) of the process specified by given process id|
|
||||
|`$ ionice -p 2` |*none: prio 4*| Check the class and priority of process with pid 2 it is none and 4 resp.|
|
||||
|`$ ionice -c2 -n0 -p2`|2 ( best-effort ) priority 0 process 2 | Now lets set process(pid) 2 as a best-effort program with highest priority|
|
||||
|$ `ionice` -p 2|best-effort : prio 0| Now if I check details of Process 2 you can see the updated one|
|
||||
|$ `ionice` /bin/ls||get priority and class info of bin/ls |
|
||||
|$ `ionice` -n4 -p2||set priority 4 of process with pid 2 |
|
||||
|$ `ionice` -p 2| best-effort: prio 4| Now observe the difference between the command ran above and this one we have changed priority from 0 to 4|
|
||||
|$ `ionice` -c0 -n4 -p2|ionice: ignoring given class data for none class|(Note that before kernel 2.6.26 a process that has not asked for an I/O priority formally uses “None” as scheduling class , |
|
||||
|||but the io schedular will treat such processes as if it were in the best effort class. )|
|
||||
|||-t option : ignore failure|
|
||||
|$ `ionice` -c0 -n4 -p2 -t| | For ignoring the warning shown above we can use -t option so it will ignore failure |
|
||||
|
||||
## Conclusion
|
||||
|
||||
Thus we have successfully learnt about `ionice` command.
|
||||
@@ -1,85 +0,0 @@
|
||||
# The `rsync` command
|
||||
|
||||
The `rsync` command is probably one of the most used commands out there. It is used to securely copy files from one server to another over SSH.
|
||||
|
||||
Compared to the `scp` command, which does a similar thing, `rsync` makes the transfer a lot faster, and in case of an interruption, you could restore/resume the transfer process.
|
||||
|
||||
In this tutorial, I will show you how to use the `rsync` command and copy files from one server to another and also share a few useful tips!
|
||||
|
||||
Before you get started, you would need to have 2 Linux servers. I will be using DigitalOcean for the demo and deploy 2 Ubuntu servers.
|
||||
|
||||
You can use my referral link to get a free $100 credit that you could use to deploy your virtual machines and test the guide yourself on a few DigitalOcean servers:
|
||||
|
||||
**[DigitalOcean $100 Free Credit](https://m.do.co/c/2a9bba940f39)**
|
||||
|
||||
## Transfer Files from local server to remote
|
||||
|
||||
This is one of the most common causes. Essentially this is how you would copy the files from the server that you are currently on (the source server) to remote/destination server.
|
||||
|
||||
What you need to do is SSH to the server that is holding your files, cd to the directory that you would like to transfer over:
|
||||
|
||||
```
|
||||
cd /var/www/html
|
||||
```
|
||||
|
||||
And then run:
|
||||
|
||||
```
|
||||
rsync -avz user@your-remote-server.com:/home/user/dir/
|
||||
```
|
||||
|
||||
The above command would copy all the files and directories from the current folder on your server to your remote server.
|
||||
|
||||
Rundown of the command:
|
||||
|
||||
* `-a`: is used to specify that you want recursion and want to preserve the file permissions and etc.
|
||||
* `-v`: is verbose mode, it increases the amount of information you are given during the transfer.
|
||||
* `-z`: this option, rsync compresses the file data as it is sent to the destination machine, which reduces the amount of data being transmitted -- something that is useful over a slow connection.
|
||||
|
||||
I recommend having a look at the following website which explains the commands and the arguments very nicely:
|
||||
|
||||
[https://explainshell.com/explain?cmd=rsync+-avz](https://explainshell.com/explain?cmd=rsync+-avz)
|
||||
|
||||
In case that the SSH service on the remote server is not running on the standard `22` port, you could use `rsync` with a special SSH port:
|
||||
|
||||
```
|
||||
rsync -avz -e 'ssh -p 1234' user@your-remote-server.com:/home/user/dir/
|
||||
```
|
||||
|
||||
## Transfer Files remote server to local
|
||||
|
||||
In some cases you might want to transfer files from your remote server to your local server, in this case, you would need to use the following syntax:
|
||||
|
||||
```
|
||||
rsync -avz your-user@your-remote-server.com:/home/user/dir/ /home/user/local-dir/
|
||||
```
|
||||
|
||||
Again, in case that you have a non-standard SSH port, you can use the following command:
|
||||
|
||||
```
|
||||
rsync -avz -e 'ssh -p 2510' your-user@your-remote-server.com:/home/user/dir/ /home/user/local-dir/
|
||||
```
|
||||
|
||||
## Transfer only missing files
|
||||
|
||||
If you would like to transfer only the missing files you could use the `--ignore-existing` flag.
|
||||
|
||||
This is very useful for final sync in order to ensure that there are no missing files after a website or a server migration.
|
||||
|
||||
Basically the commands would be the same apart from the appended --ignore-existing flag:
|
||||
|
||||
```
|
||||
rsync -avz --ignore-existing user@your-remote-server.com:/home/user/dir/
|
||||
```
|
||||
|
||||
## Conclusion
|
||||
|
||||
Using `rsync` is a great way to quickly transfer some files from one machine over to another in a secure way over SSH.
|
||||
|
||||
For more cool Linux networking tools, I would recommend checking out this tutorial here:
|
||||
|
||||
[Top 15 Linux Networking tools that you should know!](https://devdojo.com/serverenthusiast/top-15-linux-networking-tools-that-you-should-know)
|
||||
|
||||
Hope that this helps!
|
||||
|
||||
Initially posted here: [How to Transfer Files from One Linux Server to Another Using rsync](https://devdojo.com/bobbyiliev/how-to-transfer-files-from-one-linux-server-to-another-using-rsync)
|
||||
@@ -1,133 +0,0 @@
|
||||
# The `dig` command
|
||||
|
||||
dig - DNS lookup utility
|
||||
|
||||
The `dig` is a flexible tool for interrogating DNS name servers. It performs DNS lookups and displays the answers that are returned from the name server(s) that
|
||||
were queried.
|
||||
|
||||
### Examples:
|
||||
|
||||
1. Dig is a network administration command-line tool for querying the Domain Name System.
|
||||
|
||||
```
|
||||
dig google.com
|
||||
```
|
||||
|
||||
2. The system will list all google.com DNS records that it finds, along with the IP addresses.
|
||||
|
||||
```
|
||||
dig google.com ANY
|
||||
```
|
||||
|
||||
### Syntax:
|
||||
|
||||
```
|
||||
dig [server] [name] [type] [q-type] [q-class] {q-opt}
|
||||
{global-d-opt} host [@local-server] {local-d-opt}
|
||||
[ host [@local-server] {local-d-opt} [...]]
|
||||
```
|
||||
|
||||
|
||||
### Additional Flags and their Functionalities:
|
||||
|
||||
```bash
|
||||
|
||||
domain is in the Domain Name System
|
||||
q-class is one of (in,hs,ch,...) [default: in]
|
||||
q-type is one of (a,any,mx,ns,soa,hinfo,axfr,txt,...) [default:a]
|
||||
(Use ixfr=version for type ixfr)
|
||||
q-opt is one of:
|
||||
-4 (use IPv4 query transport only)
|
||||
-6 (use IPv6 query transport only)
|
||||
-b address[#port] (bind to source address/port)
|
||||
-c class (specify query class)
|
||||
-f filename (batch mode)
|
||||
-k keyfile (specify tsig key file)
|
||||
-m (enable memory usage debugging)
|
||||
-p port (specify port number)
|
||||
-q name (specify query name)
|
||||
-r (do not read ~/.digrc)
|
||||
-t type (specify query type)
|
||||
-u (display times in usec instead of msec)
|
||||
-x dot-notation (shortcut for reverse lookups)
|
||||
-y [hmac:]name:key (specify named base64 tsig key)
|
||||
d-opt is of the form +keyword[=value], where keyword is:
|
||||
+[no]aaflag (Set AA flag in query (+[no]aaflag))
|
||||
+[no]aaonly (Set AA flag in query (+[no]aaflag))
|
||||
+[no]additional (Control display of additional section)
|
||||
+[no]adflag (Set AD flag in query (default on))
|
||||
+[no]all (Set or clear all display flags)
|
||||
+[no]answer (Control display of answer section)
|
||||
+[no]authority (Control display of authority section)
|
||||
+[no]badcookie (Retry BADCOOKIE responses)
|
||||
+[no]besteffort (Try to parse even illegal messages)
|
||||
+bufsize[=###] (Set EDNS0 Max UDP packet size)
|
||||
+[no]cdflag (Set checking disabled flag in query)
|
||||
+[no]class (Control display of class in records)
|
||||
+[no]cmd (Control display of command line -
|
||||
global option)
|
||||
+[no]comments (Control display of packet header
|
||||
and section name comments)
|
||||
+[no]cookie (Add a COOKIE option to the request)
|
||||
+[no]crypto (Control display of cryptographic
|
||||
fields in records)
|
||||
+[no]defname (Use search list (+[no]search))
|
||||
+[no]dnssec (Request DNSSEC records)
|
||||
+domain=### (Set default domainname)
|
||||
+[no]dscp[=###] (Set the DSCP value to ### [0..63])
|
||||
+[no]edns[=###] (Set EDNS version) [0]
|
||||
+ednsflags=### (Set EDNS flag bits)
|
||||
+[no]ednsnegotiation (Set EDNS version negotiation)
|
||||
+ednsopt=###[:value] (Send specified EDNS option)
|
||||
+noednsopt (Clear list of +ednsopt options)
|
||||
+[no]expandaaaa (Expand AAAA records)
|
||||
+[no]expire (Request time to expire)
|
||||
+[no]fail (Don't try next server on SERVFAIL)
|
||||
+[no]header-only (Send query without a question section)
|
||||
+[no]identify (ID responders in short answers)
|
||||
+[no]idnin (Parse IDN names [default=on on tty])
|
||||
+[no]idnout (Convert IDN response [default=on on tty])
|
||||
+[no]ignore (Don't revert to TCP for TC responses.)
|
||||
+[no]keepalive (Request EDNS TCP keepalive)
|
||||
+[no]keepopen (Keep the TCP socket open between queries)
|
||||
+[no]mapped (Allow mapped IPv4 over IPv6)
|
||||
+[no]multiline (Print records in an expanded format)
|
||||
+ndots=### (Set search NDOTS value)
|
||||
+[no]nsid (Request Name Server ID)
|
||||
+[no]nssearch (Search all authoritative nameservers)
|
||||
+[no]onesoa (AXFR prints only one soa record)
|
||||
+[no]opcode=### (Set the opcode of the request)
|
||||
+padding=### (Set padding block size [0])
|
||||
+[no]qr (Print question before sending)
|
||||
+[no]question (Control display of question section)
|
||||
+[no]raflag (Set RA flag in query (+[no]raflag))
|
||||
+[no]rdflag (Recursive mode (+[no]recurse))
|
||||
+[no]recurse (Recursive mode (+[no]rdflag))
|
||||
+retry=### (Set number of UDP retries) [2]
|
||||
+[no]rrcomments (Control display of per-record comments)
|
||||
+[no]search (Set whether to use searchlist)
|
||||
+[no]short (Display nothing except short
|
||||
form of answers - global option)
|
||||
+[no]showsearch (Search with intermediate results)
|
||||
+[no]split=## (Split hex/base64 fields into chunks)
|
||||
+[no]stats (Control display of statistics)
|
||||
+subnet=addr (Set edns-client-subnet option)
|
||||
+[no]tcflag (Set TC flag in query (+[no]tcflag))
|
||||
+[no]tcp (TCP mode (+[no]vc))
|
||||
+timeout=### (Set query timeout) [5]
|
||||
+[no]trace (Trace delegation down from root [+dnssec])
|
||||
+tries=### (Set number of UDP attempts) [3]
|
||||
+[no]ttlid (Control display of ttls in records)
|
||||
+[no]ttlunits (Display TTLs in human-readable units)
|
||||
+[no]unexpected (Print replies from unexpected sources
|
||||
default=off)
|
||||
+[no]unknownformat (Print RDATA in RFC 3597 "unknown" format)
|
||||
+[no]vc (TCP mode (+[no]tcp))
|
||||
+[no]yaml (Present the results as YAML)
|
||||
+[no]zflag (Set Z flag in query)
|
||||
global d-opts and servers (before host name) affect all queries.
|
||||
local d-opts and servers (after host name) affect only that lookup.
|
||||
-h (print help and exit)
|
||||
-v (print version and exit)
|
||||
|
||||
```
|
||||
@@ -1,66 +0,0 @@
|
||||
# The `whois` command
|
||||
|
||||
The `whois` command in Linux to find out information about a domain, such as the owner of the domain, the owner’s contact information, and the nameservers that the domain is using.
|
||||
|
||||
### Examples:
|
||||
|
||||
1. Performs a whois query for the domain name:
|
||||
|
||||
```
|
||||
whois {Domain_name}
|
||||
```
|
||||
|
||||
2. -H option omits the lengthy legal disclaimers that many domain registries deliver along with the domain information.
|
||||
|
||||
```
|
||||
whois -H {Domain_name}
|
||||
```
|
||||
|
||||
### Syntax:
|
||||
|
||||
```
|
||||
whois [ -h HOST ] [ -p PORT ] [ -aCFHlLMmrRSVx ] [ -g SOURCE:FIRST-LAST ]
|
||||
[ -i ATTR ] [ -S SOURCE ] [ -T TYPE ] object
|
||||
```
|
||||
```
|
||||
whois -t TYPE
|
||||
```
|
||||
```
|
||||
whois -v TYPE
|
||||
```
|
||||
```
|
||||
whois -q keyword
|
||||
```
|
||||
|
||||
|
||||
### Additional Flags and their Functionalities:
|
||||
|
||||
|**Flag** |**Description** |
|
||||
|:---|:---|
|
||||
|`-h HOST`, `--host HOST`|Connect to HOST.|
|
||||
|`-H`|Do not display the legal disclaimers some registries like to show you.|
|
||||
|`-p`, `--port PORT`|Connect to PORT.|
|
||||
|`--verbose`|Be verbose.|
|
||||
|`--help`|Display online help.|
|
||||
|`--version`|Display client version information. Other options are flags understood by whois.ripe.net and some other RIPE-like servers.|
|
||||
|`-a`|Also search all the mirrored databases.|
|
||||
|`-b`|Return brief IP address ranges with abuse contact.|
|
||||
|`-B`|Disable object filtering *(show the e-mail addresses)*|
|
||||
|`-c`|Return the smallest IP address range with a reference to an irt object.|
|
||||
|`-d`|Return the reverse DNS delegation object too.|
|
||||
|`-g SOURCE:FIRST-LAST`|Search updates from SOURCE database between FIRST and LAST update serial number. It's useful to obtain Near Real Time Mirroring stream.|
|
||||
|`-G`|Disable grouping of associated objects.|
|
||||
|`-i ATTR[,ATTR]...`|Search objects having associated attributes. ATTR is attribute name. Attribute value is positional OBJECT argument.|
|
||||
|`-K`|Return primary key attributes only. Exception is members attribute of set object which is always returned. Another exceptions are all attributes of objects organisation, person, and role that are never returned.|
|
||||
|`-l`|Return the one level less specific object.|
|
||||
|`-L`|Return all levels of less specific objects.|
|
||||
|`-m`|Return all one level more specific objects.|
|
||||
|`-M`|Return all levels of more specific objects.|
|
||||
|`-q KEYWORD`|Return list of keywords supported by server. KEYWORD can be version for server version, sources for list of source databases, or types for object types.|
|
||||
|`-r`|Disable recursive look-up for contact information.|
|
||||
|`-R`|Disable following referrals and force showing the object from the local copy in the server.|
|
||||
|`-s SOURCE[,SOURCE]...`|Request the server to search for objects mirrored from SOURCES. Sources are delimited by comma and the order is significant. Use `-q` sources option to obtain list of valid sources.|
|
||||
|`-t TYPE`|Return the template for a object of TYPE.|
|
||||
|`-T TYPE[,TYPE]...`|Restrict the search to objects of TYPE. Multiple types are separated by a comma.|
|
||||
|`-v TYPE`|Return the verbose template for a object of TYPE.|
|
||||
|`-x`|Search for only exact match on network address prefix.|
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user