CHAPTER 2
Working with Bash
This chapter will explain the basics for you to navigate inside your Linux system, the main directories, mostly used commands, important files, managing users and groups, and how the Linux permission system works!
Structure
In this chapter, we will discuss the following topics:
- What is Bash?
- Introduction
- Basic commands
- Managing files and directories
- Structure of directories
- Important files
- Customizing your environment
- Managing users and groups
- Creating and modifying users
- Creating and modifying groups
- Working with permissions
- Changing read and write permissions
- Changing the owner of files and executing scripts
Objectives
After studying this unit, you should be able to:
- Understand directories infrastructure
- Customize your environment using important files
- Manage users and groups
- Understand the permissions and executing scripts
What is Bash?
Bash is an abbreviation of Bourne Again Shell. It is an improved version of the Legacy Shell that we used to see in older Linux/Unix Systems. In this version, we have many features, like creating functions, controlling jobs in the foreground and background, creating aliases, customizing your environment, putting color in your terminal, new shortcuts, auto-complete, and many other features that we are going to see in this chapter. Just to give you more context about it, Shell is the interface on Linux which is used to administer the system. In other words, it is where we run all the commands.
It is also a programming language. Often among Linux users, we see the term Shell Scripting. What does it mean? It means we can get all the commands used during our work, put all of them together in the same file, give permission to execute it, and automate your daily job. It is a Shell Script. It is basically the Swiss Knife of the Linux administrators. Today, it is frequently challenged by Python, because Python is an object-oriented language and has a lot of features which are very easy to use if we compare it with the Shell Script. Nevertheless, it will always be the favorite tool of all the Linux administrators to automate easy tasks, and at the end of this chapter, I will teach how to create a script using all the commands learned before.
Introduction
In the last chapter, we configured and installed our Linux system and we were able to access it using the SSH tool. The point where we stopped is as follows:
ssh alisson@192.168.178.62
Welcome to Ubuntu 18.04.3 LTS (GNU/Linux 4.15.0-76-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
System information disabled due to load higher than 1.0
* Multipass 1.0 is out! Get Ubuntu VMs on demand on your Linux, Windows or
Mac. Supports cloud-init for fast, local, cloud devops simulation.
https://multipass.run/
60 packages can be updated.
6 updates are security updates.
Last login: Mon Feb 10 18:59:46 2020
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.
alisson@devops:~$
It means we are inside the Linux Shell. Now, we are going to call it Bash because it is the command-line interpreter used. Every operating system has its own command-line interpreter, because it is required to administer the system. In the older versions of Windows, we had MS-DOS. Now, we have the PowerShell. In the older versions of Linux, we had the Shell. Now, we have the Bash and some users are migrating from Bash to Z shell. I will show in the following pages how we can change our CLI (Command Line Interpreter).
Within your server, the most useful command is called ls
:
alisson@devops:~$ ls
id_rsa.pub
This command is used to show the files and the directories of Linux. It can be used with different parameters. For example, if I want to show the files and directories in a detailed mode, I can pass the parameter –l
:
alisson@devops:~$ ls -l
total 4
-rw-rw-r-- 1 alisson alisson 398 Jan 31 20:18 id_rsa.pub
alisson@devops:~$
The last output shows us more information following that sequence:
Permissions – Number of the Hard Links – User – Group – Size – Last Modification Date – Filename
This kind of information is called the metadata. But why does it have this name? Because, we have a file which contains the data that we use, and this data is about the file that is used the most by the OS. For example, we need not always know the size of a file, but the operating system always needs that kind of information, because it needs to calculate the free and used space on the disk.
If you want to see more about the metadata of a file, use the following command stat
:
alisson@devops:~$ stat id_rsa.pub
File: id_rsa.pub
Size: 398 Blocks: 8 IO Block: 4096 regular file
Device: 802h/2050d Inode: 532800 Links: 1
Access: (0664/-rw-rw-r--) Uid: (1000/ alisson) Gid: (1000/ alisson)
Access: 2020-01-31 20:20:23.741638861 +0000
Modify: 2020-01-31 20:18:39.467733742 +0000
Change: 2020-01-31 20:18:39.467733742 +0000
Birth: -
This command will show you all the metadata about the file and in a detailed form.
One very interesting parameter of the ls
is the -a
, which will show you all the files including the hidden ones. In Linux, all the hidden files starts with a .
(dot) in the beginning. For example:
alisson@devops:~$ ls -la
total 40
drwxr-xr-x 5 alisson alisson 4096 Jan 31 20:20 .
drwxr-xr-x 3 root root 4096 Jan 31 19:40 ..
-rw------- 1 alisson alisson 113 Jan 31 20:20 .bash_history
-rw-r--r-- 1 alisson alisson 220 Apr 4 2018 .bash_logout
-rw-r--r-- 1 alisson alisson 3771 Apr 4 2018 .bashrc
drwx------ 2 alisson alisson 4096 Jan 31 19:41 .cache
drwx------ 3 alisson alisson 4096 Jan 31 19:41 .gnupg
-rw-rw-r-- 1 alisson alisson 398 Jan 31 20:18 id_rsa.pub
-rw-r--r-- 1 alisson alisson 807 Apr 4 2018 .profile
drwxrwxr-x 2 alisson alisson 4096 Jan 31 20:20 .ssh
We can see a lot of files now, like the .bashrc
or .bash_history
or the hidden directory .ssh
, which we used in the first chapter to save our public key to access the server without any password.
If you want to see the content of a file, you can use the command cat
:
alisson@devops:~$ cat .bash_logout
# ~/.bash_logout: executed by bash(1) when login shell exits.
# when leaving the console clear the screen to increase privacy
if ["$SHLVL" = 1]; then
[-x /usr/bin/clear_console] && /usr/bin/clear_console -q
fi
Using the command cat
, we were able to see the content of the .bash_logout
file. This file has some importance, because if we want to execute a command before logging out of the server, we should put in this file.
To display a message on the screen, use the command echo
:
alisson@devops:~$ echo Message on Terminal
Message on Terminal
This command is often used to create a file as well:
alisson@devops:~$ echo Creating a file > message.txt
alisson@devops:~$ ls
id_rsa.pub message.txt
alisson@devops:~$ cat message.txt
Creating a file
We can use redirectors at Shell Script to send command outputs to write the files. There exist many redirectors, but the most used are ">
" and ">>
".
If you use ">
" after a command, the standard output of the command is redirected to a file that you need to specify. But, if you select an existing file, the redirector will overwrite it.
If you use ">>
" after a command, the standard output of the command is redirected to a file that you need to specify too. But, if you select an existing file, the redirector will append it and not overwrite it.
To manage files, most commands use the same syntax. If you want to copy, move, or rename a file, you can use COMMAND <SOURCE FILE><DESTINATION FILE>
.
Renaming a file:
alisson@devops:~$ mv message.txt file.txt
alisson@devops:~$ ls
file.txt id_rsa.pub
Copying a file:
alisson@devops:~$ cp file.txt file2.txt
alisson@devops:~$ ls
file2.txt file.txt id_rsa.pub
In the first chapter, we edited a file and called authorized_keys
. If we want to check this file again, we can access the directory using the command cd
:
alisson@devops:~$ cd .ssh/
alisson@devops:~/.ssh$ ls
authorized_keys
And, we can check the file content again:
alisson@devops:~/.ssh$ cat authorized_keys
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQChi8HX26xv9Rk9gz47Qhb+Tu7MRqGIyP xnheIeEgFad/dlqG4w4pY7y5dtx5LNGE9C01varco5dZagqsHplI7M+5ECSvjAuS6b5r kYZwZiZruDXxckcQHFpr2yIz 3DOzKRTUc5Hg5JHF5aymiqyVfTsxL/aI/LDY8Ikh+ INn3S9+b5bZtU+74tA6yuqt h5SCtNSWwMUlv7QL6ONHtQiviAjBe+ksDBBV6thWz2ZIJA/jApSIBJWK9AWmZwq 2hFy9sOZArUDB2Kt6kl3rIZnHpqJ/GMUCxFhtggYamJ5J2H62 77qLFqLZ/8tum9uc5l/lSWYKTDm2+E/prQfmFrxPf9 1511 mxti@avell
If you need to know the directory you are working on, use the following command:
alisson@devops:~/.ssh$ pwd
/home/alisson/.ssh
And if you want to go to the previous directory again, use the command cd
using two dots (..
):
alisson@devops:~/.ssh$ cd ..
alisson@devops:~$ pwd
/home/alisson
Managing files and directories
After getting to know some basic commands, it is really important for you to know how to navigate among the directories, know the files within them, and what we can do using these files. So, now we will see what the root directory is, where the configuration files are, what these files do for our Linux system, and how we can customize the environment using it.
Structure of directories
To see the basic structure of the directories on Linux, use the following command:
alisson@devops:~$ ls /
bin cdrom etc initrd.img lib lost+found mnt proc run snap swap.img tmp var vmlinuz.old
boot dev home initrd.img.old lib64 media opt root sbin srv sys usr vmlinuz
Here, we have some directories. I will explain just the most important of them:
/
: It is the root directory and everything that runs in your Linux system is below this directory./etc
: This directory stores all the configuration files on Linux./var
: This directory stores the log files and data of some services. For example, if you have a MySQL server installed in your system, you can find all the data stored inside/var/lib/mysql/data
./lib
: Here you will find the libraries of your system. We do not have to often access this directory, but it is an important one to know. For example, the kernel modules are stored in/lib/modules
./bin
: This directory stores the binaries. In other words, the programs are required for your Linux Words. For example, the commandls
, it is found in this directory./usr
: Here you can find some binaries, like the/bin
. But the binaries installed here are not required for your system works. For example,/usr/bin/at
, this binary allows you to schedule a task to run in your system, but you can live without that./boot
: In this directory, you can find your kernel installed. My current version is:/boot/vmlinuz-4.15.0-76-generic
./proc
: This is the current process running. One fact about this directory is it only exists when your Linux is turned on. If you have a dual boot and you try to mount your Linux partition, you will be able to see all the directories, except the/proc
, because it is your RAM content./opt
: Usually, it becomes empty after your installation. But, when you compile a program, it is a good practice to put the binaries and the configuration files in this directory./sbin
: This is exactly like the/bin
, but the binaries here require administration permissions. For example, if you want to format a partition, you will call the command/sbin/fdisk
. You cannot run this command as a common user./home
: In this directory, you will find the home directory of all the common users. The only exception is the user root; its home directory can be found in/root
./mnt
: Here, you can use to mount network shares; your pendrive, SD card, and another kind of external volumes.
These are the most important directories you can find in your Linux system and they will be a part of your daily work.
Important Files
Now that you already know the important directories, let's get inside of them and see the files that are important for our system to work.
One important file is the /etc/passwd.
This file is responsible to store all the Linux users, and we can give a look at its content using the cat
command:
alisson@devops:~$ cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
This was an example of the first 5 lines. Its structure follows the following sequence:
User – password – user id – group id – comment – home folder - shell
The data is separated by a colon (:
). It is important to know that the Linux shell has many useful commands to work with these kinds of files.
For example, we could use the command cut to see just the information we want:
alisson@devops:~$ cut -f 1,6,7 -d : /etc/passwd
root:/root:/bin/bash
daemon:/usr/sbin:/usr/sbin/nologin
bin:/bin:/usr/sbin/nologin
sys:/dev:/usr/sbin/nologin
Thus, in the example, I printed just the columns 1, 6, 7 which correspond to the user, the home folder, and the shell.
I am not posting the entire output of the command because I want to save some space. But, you probably are running this on your own virtual machine. So, if you want to show just the first 3 lines of any file, you can use the command head. By default, this command shows the first 10 lines of a file, but we have the -n parameter, where we can define as many lines we want to see.
For example:
alisson@devops:~$ head -n 3 /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
On Linux, it is also possible to concatenate the commands. If you want to see just the first 3 lines and only the columns 1, 6, 7 like we did with the cut command, we can use the pipe (|
). This statement has the function of getting the output of the last command and sending it to the next command in the pipeline.
Example:
alisson@devops:~$ head -n3 /etc/passwd | cut -f 1,6,7 -d :
root:/root:/bin/bash
daemon:/usr/sbin:/usr/sbin/nologin
bin:/bin:/usr/sbin/nologin
Therefore, every time that you want to concatenate the commands, you must use the pipe (|
). One interesting point is the second columns of the /etc/passwd
file. I wrote that it is the password, but we can only see an x
, this character represents the encrypted password. The hash can be found in the file /etc/shadow
:
alisson@devops:~$ sudo head -n3 /etc/shadow
[sudo] password for alisson:
root:*:18113:0:99999:7:::
daemon:*:18113:0:99999:7:::
bin:*:18113:0:99999:7:::
To see the content of this file, you need to run the command sudo
before the command head. The sudo
command means the substitute users do. In a simple way, we are running the command head as we were another user. If you do not specify the user, by default, the user is root. The password is the same as we set in the installation. If you set the same password as me, it’s devops
.
To see your user's password, we can use the command grep
. This command will find the line which corresponds with our criteria of the search.
Example:
alisson@devops:~$ sudo grep alisson /etc/shadow
alisson:$6$aeR.OxEqoVMnyUuq$eYxtbG6V.156mtlsK9QBZcVOjQZBm7NlcKFn5x1y xF4mffuLYd6Wmz2R9V2iKZvuC7fgp96H7.jlQW/o7OenF/:18292:0:99999:7:::
Now you can clearly see the password hash in the second column. Of course, we cannot decrypt it, but if you want to take a Linux certification, you will need to record this file and the structures. However, we can also remove a user's password. You can just edit this file and delete the hash. This way, the user will not have a password and he can set a new one in the future.
Regarding the users, we also have one file on Linux to manage the groups. This file is located in /etc/group
:
alisson@devops:~$ head -n 3 /etc/group
root:x:0:
daemon:x:1:
bin:x:2:
This file follows the following sequence:
Group name | password | group id | users
So, the users added into a group will appear in the last column of each line. As I explained earlier, we can use the command grep
to find a group and see which users were added into it:
alisson@devops:~$ grep sudo /etc/group
sudo:x:27:alisson
It shows us one interesting thing; the command sudo
only allows the users who belong to the sudo
group to use the command. Another important file is the /etc/fsta
b. This file is responsible to mount our volumes during the boot. Let's give it a look:
alisson@devops:~$ cat /etc/fstab
UUID=75fbe5e6-26ff-4522-abc4-0d8a3ac69c5b / ext4 defaults 0 0
/swap.img none swap sw 0 0
When you work with Linux, it is really important for you to know the structure of the files. So, this file is organized in the following sequence:
Partition – folder – filesystem type – mounting options – backup enable – disk check sequence
Nowadays, this command lets you see the first column with a uuid,
which represents a partition. If you want to see where it binds, run the following command:
alisson@devops:~$ blkid
/dev/sda2: UUID="75fbe5e6-26ff-4522-abc4-0d8a3ac69c5b" TYPE="ext4" PARTUUID="7177f53d-2db2-49cb-93a9-21d763cac088"
If you check, it is exactly the same in the /etc/fstab
. If you want to change, you can just replace the uuid
in the file to /dev/sda2
. It will work in the same way. The machine's hostname is stored in the /etc/hostname
:
alisson@devops:~$ cat /etc/hostname
devops
If you want to change the hostname, you can just edit this file. We also have the /etc/hosts
file that you can map an IP address to a name, as we did in the DNS:
alisson@devops:~$ cat /etc/hosts
127.0.0.1 localhost
127.0.1.1 devops
# The following lines are desirable for IPv6 capable hosts
::1 ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
It is very useful when you are developing a web system and you don't want to type the IP address in the browser every time a really important file is /etc/sudores
:
alisson@devops:~$ sudo cat /etc/sudoers
[sudo] password for alisson:
#
# This file MUST be edited with the 'visudo' command as root.
#
# Please consider adding local content in /etc/sudoers.d/ instead of
# directly modifying this file.
#
# See the man page for details on how to write a sudoers file.
#
Defaults mail_badpass
Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin"
# Host alias specification
# User alias specification
# Cmnd alias specification
# User privilege specification
root ALL=(ALL:ALL) ALL
# Members of the admin group may gain root privileges
%admin ALL=(ALL) ALL
# Allow members of group sudo to execute any command
%sudo ALL=(ALL:ALL) ALL
# See sudoers(5) for more information on "#include" directives:
#includedir /etc/sudoers.d
This file is responsible to manage who can use the sudo
command. I explained earlier, the only users in the group sudo
can run the command. But, how does the command know which group it needs to use? Because of the following line:
# Allow members of group sudo to execute any command
%sudo ALL=(ALL:ALL) ALL
You can put more groups in this file or you can put the users directly, like the following line:
# User privilege specification
root ALL=(ALL:ALL) ALL
One thing that is nice to work with Linux is since all the documentation comes inside the files, like we saw in the /etc/sudoers
, the comments explain how and where you have to edit the file. We also have the command man
for that:
alisson@devops:~$ man sudo
SUDO(8)
BSD System Manager's Manual
NAME
sudo, sudoedit — execute a command as another user
SYNOPSIS
sudo -h | -K | -k | -V
sudo -v [-AknS] [-a type] [-g group] [-h host] [-p prompt] [-u user]
sudo -l [-AknS] [-a type] [-g group] [-h host] [-p prompt] [-U user] [-u user] [command]
sudo [-AbEHnPS] [-a type] [-C num] [-c class] [-g group] [-h host] [-p prompt] [-r role] [-t type] [-T timeout] [-u user] [VAR=value] [-i | -s] [command]
sudoedit [-AknS] [-a type] [-C num] [-c class] [-g group] [-h host] [-p prompt] [-T timeout] [-u user] file …
This is just the first few lines of the file. To quit the man, press q
. The file /etc/crontab
:
alisson@devops:~$ cat /etc/crontab
# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the 'crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
# m h dom mon dow user command
17 * * * * root cd / && run-parts --report /etc/cron.hourly
25 6 * * * root test -x /usr/sbin/anacron || (cd / && run-parts --report /etc/cron.daily)
47 6 * * 7 root test -x /usr/sbin/anacron || (cd / && run-parts --report /etc/cron.weekly)
52 6 1 * * root test -x /usr/sbin/anacron || (cd / && run-parts --report /etc/cron.monthly)
#
This is responsible to manage the scheduled tasks. It follows the following structure:
Minute – hour – day of the month – month – day of the week – user - command
So, if you want to schedule the tasks to run every Friday
at 07 pm
, you can add a line like the following:
00 19 * * 5 root bash /bin/backup.sh
Therefore, every Friday
at 7 pm,
the user root will run the command backup.sh.
This is how we must read a line in the crontab
file. This is the main file, but each user has their own crontabs
, and they can be found in the following path:
alisson@devops:~$ sudo ls /var/spool/cron/crontabs/ -la
[sudo] password for alisson:
total 8
drwx-wx--T 2 root crontab 4096 Nov 16 2017 .
drwxr-xr-x 5 root root 4096 Aug 5 2019 ..
We do not have any file inside this directory, because we never created any schedule. But, we can edit the users' crontab
for you to see the creation of the file. Type the following command in your terminal:
alisson@devops:~$ crontab -e
no crontab for alisson - using an empty one
Select an editor. To change later, run 'select-editor'.
1. /bin/nano <---- easiest
2. /usr/bin/vim.basic
3. /usr/bin/vim.tiny
4. /bin/ed
Choose 1-4 [1]: 2
crontab: installing new crontab
You can choose option 2, as I did. It will set the VIM as the default text editor for your crontab
. Wait for the VIM to open and close by pressing Esc, and use the following command:
:wq!
I will explain more about VIM in the next section. Now that you have saved your user crontab
, you can check the folder again:
alisson@devops:~$ sudo ls /var/spool/cron/crontabs/ -la
total 12
drwx-wx--T 2 root crontab 4096 Feb 17 20:54 .
drwxr-xr-x 5 root root 4096 Aug 5 2019 ..
-rw------- 1 alisson crontab 1089 Feb 17 20:54 alisson
You can see that a file with the same user's name was created. So, every user will have a file in this folder since they created a crontab
using the command crontab -e
. For Linux systems, it is a requirement to have an SSH connection and the configuration file for this is: /etc/ssh/sshd_config
:
alisson@devops:~$ cat /etc/ssh/sshd_config
# $OpenBSD: sshd_config,v 1.101 2017/03/14 07:19:07 djm Exp $
# This is the sshd server system-wide configuration file. See
# sshd_config(5) for more information.
# This sshd was compiled with PATH=/usr/bin:/bin:/usr/sbin:/sbin
# The strategy used for options in the default sshd_config shipped with
# OpenSSH is to specify options with their default value where
# possible, but leave them commented. Uncommented options override the
# default value.
#Port 22
#AddressFamily any
#ListenAddress 0.0.0.0
#ListenAddress ::
Formerly, we have a short part of the file, in which you are able to change the port, and define which IP addresses will listen for the connections:
alisson@devops:~$ grep Root /etc/ssh/sshd_config
#PermitRootLogin prohibit-password
# the setting of "PermitRootLogin without-password".
One important configuration in the preceding file, PermitRootLogin
, is in some cases, we are able to login in the server using the root user directly. But, it is not a good practice. However, it is not uncommon to see in an on-premises environment. In the cloud environment, it is never allowed, because everyone in the world can try to access with the root user.
Another important configuration is the following one:
alisson@devops:~$ grep PasswordAuthentication /etc/ssh/sshd_config
# PasswordAuthentication. Depending on your PAM configuration,
# PAM authentication, then enable this but set PasswordAuthentication
PasswordAuthentication yes
If you are working with any Cloud provider like Amazon, Azure, or GCP, this configuration is disabled by default, for security reasons. We have added our SSH key in the server in the first chapter. So, if you want, you can edit this file and change the option for no
.
Managing users and groups
Now, you already know some of the important files, and the files responsible to manage users and groups. We could just open these files and edit them to create new users and groups. But, Linux has useful commands which should be used to do that job and make our life easier.
Managing users
To see the users, we have the command getent
:
alisson@devops:~$ getent passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
The output is a quite similar as the command cat
, but, the difference is that we can look for a specific user, like we did using the command grep
:
alisson@devops:~$ getent passwd alisson
alisson:x:1000:1000:alisson:/home/alisson:/bin/bash
Thus, it is up to you which command you want to use. When I am working, I always use the getent
, to look for a user or group, and the grep
command, to find a line in any file of the Linux system.
To add a new user, run the following command:
alisson@devops:~$ sudo adduser elvis
[sudo] password for alisson:
Adding user 'elvis' …
Adding new group 'elvis' (1001) …
Adding new user 'elvis' (1001) with group 'elvis' …
Creating home directory '/home/elvis' …
Copying files from '/etc/skel' …
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully
Changing the user information for elvis
Enter the new value, or press ENTER for the default
Full Name []:
Room Number []:
Work Phone []:
Home Phone []:
Other []:
Is the information correct? [Y/n]
Only the username and password are mandatory. You can leave the other options blank, as I did in the example. I set the password as devops
. If you analyze the command output, you can see two things that are important for us to pay attention.
The first is the information about the home
directory. The command creates a folder called elvis
within the /home
folder. As I explained earlier, the home
folder is responsible for the user's files.
The second is the /etc/skel
, where the command adduser
gets the default files present in the home
folder of the user. We can give it a look with the following command:
alisson@devops:~$ ls /etc/skel/ -la
total 20
drwxr-xr-x 2 root root 4096 Aug 5 2019 .
drwxr-xr-x 91 root root 4096 Feb 18 19:25 ..
-rw-r--r-- 1 root root 220 Apr 4 2018 .bash_logout
-rw-r--r-- 1 root root 3771 Apr 4 2018 .bashrc
-rw-r--r-- 1 root root 807 Apr 4 2018 .profile
These files are responsible to customize the user's environment. We are going to edit them in the last part of this chapter. But, if you want to put more items inside the home
folder, you can just add inside the /etc/skel
, and they will be present for the next user created. Let's test it.
Let's create a skeleton for a hosting server. How does the web server work? Usually, we have the user and in the home
folder of each user, you have some folder called, public_html
, mail
, conf
, logs
. All these folders must be created at the same time as the user is created. So, run the following command:
alisson@devops:~$ sudo mkdir /etc/skel/{public_html, logs, mail, conf}
[sudo] password for alisson:
alisson@devops:~$ ls /etc/skel/
conf logs mail public_html
alisson@devops:~$
So, as you can see, now we have these four folders created inside the /etc/skel.
Now, let's create another user to see it working:
alisson@devops:~$ sudo adduser customer01
Adding user 'customer01' …
Adding new group 'customer01' (1002) …
Adding new user 'customer01' (1002) with group 'customer01' …
Creating home directory '/home/customer01' …
Copying files from '/etc/skel' …
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully
Changing the user information for customer01
Enter the new value, or press ENTER for the default
Full Name []:
Room Number []:
Work Phone []:
Home Phone []:
Other []:
Is the information correct? [Y/n]
alisson@devops:~$ ls /home/customer01/
conf logs mail public_html
As you can see now, we have these folders created in the home
folder of the user. I am setting the same password for all users. But, if you forgot a password and you want to change it, the command to do that is as follows:
alisson@devops:~$ sudo passwd elvis
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully
Now, type the new password and it is changed.
We are now talking about the hosting servers. So, let's use another example. Imagine your customer did not pay you. So, you need to block this user. To execute this task, you can run the following command:
alisson@devops:~$ sudo passwd -l customer01
passwd: password expiry information changed.
One interesting thing about Linux is if you want to know how it blocks the users, you can give a look at the /etc/shadow
:
alisson@devops:~$ sudo getent shadow customer01
customer01:!$6$PExBAe3N$6AxVOOJLi/A5ddWOp2I/ZhvB00mpVwq4KQ78/4.QNNcrz2tsGGFu8XXr/TU7NFA/Hg3T2X9.R5v6cCuzbYF8j.:18310:0:99999:7:::
Paying attention to the output is easy. To note one difference, let's compare with a non-blocked user:
alisson@devops:~$ sudo getent shadow alisson
alisson:$6$aeR.OxEqoVMnyUuq$eYxtbG6V.156mtlsK9QBZcVOjQZBm7NlcKFn5x1 yxF4mffuLYd6Wmz2R9V2iKZvuC7fgp96H7.jlQW/o7OenF/:18292:0:99999:7:::
In the second column, where the password is stored, for a blocked user, you can see that the system puts an exclamation point (!
) as the first character. This way, the user can type his password and it will never match with the hash because there is an exclamation point in the beginning.
To unblock the user, type the following command:
alisson@devops:~$ sudo passwd -u customer01
passwd: password expiry information changed.
alisson@devops:~$ sudo getent shadow customer01
customer01:$6$PExBAe3N$6AxVOOJLi/A5ddWOp2I/ZhvB00mpVwq4KQ78/4.QNNcrz2tsGGFu8XXr/TU7NFA/Hg3T2X9.R5v6cCuzbYF8j.:18310:0:99999:7:::
Now, Linux removed the !
in the beginning of the hash and the user is able to access the shell again. If the customer canceled the service with you, it is possible to remove his user. To execute this task, you need to run the following command:
alisson@devops:~$ sudo userdel elvis
alisson@devops:~$ sudo getent passwd elvis
It is important to remember that removing the user does not mean you will remove his home
directory if we check:
alisson@devops:~$ ls /home/
You can remove it manually now using the following command.
alisson@devops:~$ sudo rm -rf /home/elvis/
Linux has this behavior to avoid you delete files that you might need in the future. But, if you are sure you want to remove everything, run the following command:
alisson@devops:~$ sudo userdel -r customer01
userdel: customer01 mail spool (/var/mail/customer01) not found
alisson@devops:~$ ls /home/
alisson
Now, everything is deleted.
Managing groups
This task is pretty similar to the user management. We can see all the groups:
alisson@devops:~$ sudo getent group
root:x:0:
daemon:x:1:
bin:x:2:
sys:x:3:
adm:x:4:syslog,Alisson
Find a group using a specific name:
alisson@devops:~$ sudo getent group sudo
sudo:x:27:Alisson
Create a new user and add this user to the group sudo
:
alisson@devops:~$ sudo useradd gabriela
alisson@devops:~$ sudo getent passwd gabriela
gabriela:x:1001:1001::/home/gabriela:/bin/sh
alisson@devops:~$ sudo getent group sudo
sudo:x:27:Alisson
The command I ran showed that I created a user called gabriela
. This user is present in the passwd
file and the group sudo
just had the user Alisson
added. To add the new user, run the following command:
alisson@devops:~$ sudo gpasswd -a gabriela sudo
Adding user gabriela to group sudo
alisson@devops:~$ sudo getent group sudo
sudo:x:27:alisson,gabriela
Perfect! Now, we have 2 users who belong the sudo
group and we can switch the user to see if the new one has the same permissions:
alisson@devops:~$ sudo su - gabriela
No directory, logging in with HOME=/
$
One interesting point is if you paid attention, I ran 2 different commands to create a user .Firstly, I ran the adduser
and after I ran useradd
. What is the difference between the commands?
The last output when I changed the user using the command su -
, I received the message of no directory for this user. Therefore, the command useradd
does not create the home
folder for the user as the adduser
does. So, we can use the useradd
for the technical user, which does not need a password
or home
directory, and the adduser
for common users. Do I use that in my daily work? No, I use the adduser
for everything and after that, I remove the shell and the password, like the following:
alisson@devops:~$ sudo adduser app1 --shell /bin/false
Adding user 'app1' …
Adding new group 'app1' (1002) …
Adding new user 'app1' (1002) with group 'app1' …
Creating home directory '/home/app1' …
Copying files from '/etc/skel' …
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully
Changing the user information for app1
Enter the new value, or press ENTER for the default
Full Name []:
Room Number []:
Work Phone []:
Home Phone []:
Other []:
Is the information correct? [Y/n]
alisson@devops:~$ sudo passwd -l app1
passwd: password expiry information changed.
alisson@devops:~$ sudo getent shadow app1
app1:!$6$ArmlhXou$Ry11spiafwXfqcPkVQ3xJDCd4gbN9vcsw1.9wkDoO4N69. 3vnkHTZl.jPsMJLJmYjJwW4yS.CvvMEA5bGsZVE1:18312:0:99999:7:::
alisson@devops:~$ sudo getent passwd app1
app1:x:1002:1002:,,,:/home/app1:/bin/false
So, if you check the output, you can clearly see that the user has no shell and he is blocked for login. It would be so much easier if I had executed the useradd
. But, when you develop a vicious circle, it is hard to avoid.
Now, let's get back to the users in the group sudo
. Deleting the user:
alisson@devops:~$ sudo userdel -r gabriela
userdel: gabriela mail spool (/var/mail/gabriela) not found
userdel: gabriela home directory (/home/gabriela) not found
Creating the user again:
alisson@devops:~$ sudo adduser gabriela
Adding user 'gabriela' …
Adding new group 'gabriela' (1001) …
Adding new user 'gabriela' (1001) with group 'gabriela' …
Creating home directory '/home/gabriela' …
Copying files from '/etc/skel' …
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully
Changing the user information for gabriela
Enter the new value, or press ENTER for the default
Full Name []:
Room Number []:
Work Phone []:
Home Phone []:
Other []:
Is the information correct? [Y/n]
alisson@devops:~$ sudo gpasswd -a gabriela sudo
Adding user gabriela to group sudo
alisson@devops:~$
Changing the user:
alisson@devops:~$ sudo su - gabriela
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.
gabriela@devops:~$
Now, you are able to see that my shell has changed. Now, I am the user gabriela.
To create users or groups, we need to have the sudo
permission. Let's try to create a new group called applications
:
gabriela@devops:~$ sudo addgroup applications
[sudo] password for gabriela:
Adding group 'applications' (GID 1003) …
Done.
Checking if the group was created:
gabriela@devops:~$ sudo getent group applications
applications:x:1003:
Adding a new user to this group:
gabriela@devops:~$ sudo useradd juergen
gabriela@devops:~$ sudo gpasswd -a juergen applications
#Adding user juergen to group applications:
gabriela@devops:~$ getent group applications
applications:x:1003:juergen
And if you want to delete the group:
gabriela@devops:~$ sudo delgroup applications
Removing group 'applications' …
Done.
Switching back to my user:
gabriela@devops:~$ exit
alisson@devops:~$
And that is it. This was your QuickStart
for managing user and groups. Of course, we could go so much deeper in these topics, but I still have to explain how you can customize your environment.
Working with Permissions
The Linux permission system works differently from Windows. We have some numbers associated with the permission. So, for example:
1 – Execution
2 - Writing
4 – Reading
So you always have to make some math to apply for the permission. If you want to assign the execution permission you can set as 1
, write permission 2
and reading permission 4
. Write + Reading
is equal to 6
, so the permission is 6
. If you want Read + Write + Execution
is equal to 7
. Let's create a file and check its permissions:
alisson@devops:~$ touch new_file
alisson@devops:~$ ls -la new_file
-rw-rw-r-- 1 alisson alisson 0 Feb 20 19:21 new_file
The command touch is responsible to change the access time of any file. If the file does not exist, it creates one. Checking the output, you can see that we have the permissions: read+write
, read+write
, read, but what means that sequence:
user – group – other
In the same line, we can see alisson alisson
, the first one is the user owner for this file and the second one is the group. By default, all the users created on Linux have a group with the same name as the user.
If you remember the numbers which represent the permission, we can make a calculation, read+write = 4 + 2 = 6
. Then we have the following permissions:
664
Therefore, the user can read and write. Users from the same group can also read and write, users who do not belong to the group can just read. Now, we can create a directory and analyze the permissions as we did just now:
alisson@devops:~$ mkdir new_folder
alisson@devops:~$ ls -la | grep new_folder
drwxrwxr-x 2 alisson alisson 4096 Feb 20 19:29 new_folder
Analyzing the permissions, we can see, read + write + execution
for the user and group, and read + execution
for the others. If we make the following association:
read + write + execution = 4 + 2 + 1 = 7
read + execution = 4 + 1 = 5
Then, we have 775
. What can we conclude, then? The default permissions for the files are 644
, and for the directories are 775
.
Why are the permissions for the directories and the files different? If we paid attention, the only difference is Execution. The files are created without this, just for security. So, we can execute the wrong files, and the folders are created with the execution permission because with this permission, we can open the folders.
Nice, but how can we change the file permissions?
Changing read and write permissions
The command used for changing these permissions is chmod.
I will show you how we can change it using numbers and letters. The experienced Linux users usually use numbers, but it does not make any difference whether you use numbers or letters. Let’s use an example of the new_file
:
alisson@devops:~$ ls -la new_file
-rw-rw-r-- 1 alisson alisson 0 Feb 20 19:21 new_file
So, the permission is 664
, which means that any user who is not me can read the file content and I do not want to allow it. So, I will change the permission for other users to 0
:
alisson@devops:~$ chmod 660 new_file
alisson@devops:~$ ls -la new_file
-rw-rw---- 1 alisson alisson 0 Feb 20 19:21 new_file
I just changed the permissions for 660
. So, let's create the content inside this file. Change the user and see how it works:
alisson@devops:~$ echo content not allowed to other > new_file
alisson@devops:~$ cat new_file
content not allowed to other
Let's change the user to gabriela
:
alisson@devops:~$ sudo su - gabriela
[sudo] password for alisson:
gabriela@devops:~$ pwd
/home/gabriela
gabriela@devops:~$ ls -la /home
total 20
drwxr-xr-x 5 root root 4096 Feb 20 19:05 .
drwxr-xr-x 24 root root 4096 Feb 18 18:00 ..
drwxr-xr-x 6 alisson alisson 4096 Feb 20 19:29 alisson
drwxr-xr-x 6 app1 app1 4096 Feb 20 19:00 app1
drwxr-xr-x 6 gabriela gabriela 4096 Feb 20 19:12 gabriela
Now, I will enter in my home
folder and try to see the file content:
gabriela@devops:~$ cd /home/alisson/
gabriela@devops:/home/alisson$ cat new_file
cat: new_file: Permission denied
And it works! But, if we remember the managing groups' part, this user has permission to use sudo
. So, I will add itself in the group
Alisson
, and let's see what happens:
gabriela@devops:/home/alisson$ sudo gpasswd -a gabriela alisson
[sudo] password for gabriela:
Adding user gabriela to group Alisson
If we type the command groups, we can see the groups that this user belongs to:
gabriela@devops:/home/alisson$ groups
gabriela sudo
Thus, it means that the new user is not able to be used in this session. Let’s logout and login again, and see if it changes:
gabriela@devops:/home/alisson$ logout
alisson@devops:~$ sudo su - gabriela
gabriela@devops:~$ groups
gabriela sudo alisson
Now, the group is loaded. So, let's try to see the file content again:
gabriela@devops:~$ cd /home/alisson/
gabriela@devops:/home/alisson$ cat new_file
content not allowed to other
And it is possible to see the file content. So this is how the permission works. I show how we can change the permission using the number. If you want to change it using letters, it is basically the same. Let's try:
gabriela@devops:/home/alisson$ cd
gabriela@devops:~$ touch letters_file
gabriela@devops:~$ ls -la letters_file
-rw-rw-r-- 1 gabriela gabriela 0 Feb 20 19:47 letters_file
To remove all the permission to others:
gabriela@devops:~$ chmod o= letters_file
gabriela@devops:~$ ls -la letters_file
-rw-rw---- 1 gabriela gabriela 0 Feb 20 19:47 letters_file
Then, we can see that I just had to type o=
, which means other = nothing
, and the permissions were set. I could just add the execution permission:
gabriela@devops:~$ chmod o+x letters_file
gabriela@devops:~$ ls -la letters_file
-rw-rw---x 1 gabriela gabriela 0 Feb 20 19:47 letters_file
Or, I can set the permissions to read for all, and write just for the owner:
gabriela@devops:~$ chmod g=rx,o=rx letters_file
gabriela@devops:~$ ls -la letters_file
-rw-r-xr-x 1 gabriela gabriela 0 Feb 20 19:47 letters_file
And if I want to give the write permission to everyone, I will do the following:
gabriela@devops:~$ chmod +w letters_file
gabriela@devops:~$ ls -la letters_file
-rw-rwxr-x 1 gabriela gabriela 0 Feb 20 19:47 letters_file
The same command works for the directories.
Change the owner of files and executing scripts
The same way as chmod
is used for permissions, chown
is used for ownership. Let me use the same files that we have:
gabriela@devops:~$ ls -la letters_file
-rw-rwxr-x 1 gabriela gabriela 0 Feb 20 19:47 letters_file
The owner is gabriela
, and the group is gabriela
too. In the previous example, I have added the user gabriela
to the group alisson
, and then the user was able to access the file. But this time, I will do it differently:
gabriela@devops:~$ chown gabriela:alisson letters_file
gabriela@devops:~$ ls -la letters_file
-rw-rwxr-x 1 gabriela alisson 0 Feb 20 19:47 letters_file
Now, the group owner for this file is alisson
. If I want to change the user, I can run the command as follows:
gabriela@devops:~$ sudo chown juergen letters_file
[sudo] password for gabriela:
gabriela@devops:~$ ls -la letters_file
-rw-rwxr-x 1 juergen alisson 0 Feb 20 19:47 letters_file
Jurgen
is the owner of this file. We can use the command chown
to change the user and the group for a file or directory. But we have a command which can also be used to change the group:
gabriela@devops:~$ sudo chgrp gabriela letters_file
gabriela@devops:~$ ls -la letters_file
-rw-rwxr-x 1 juergen gabriela 0 Feb 20 19:47 letters_file
The group is now changed. Therefore, the command chgrp
changes only the group, and the command chown
changes the owner, or the owner and the group. Thus, to finish this chapter, we are just missing to see how to execute a script. So let's create a simple one:
gabriela@devops:~$ echo "echo this is a simple script"> simple_script.sh
gabriela@devops:~$ ls -la simple_script.sh
-rw-rw-r-- 1 gabriela gabriela 29 Feb 20 20:05 simple_script.sh
Here, we have the script created. To execute it, run it as follows:
gabriela@devops:~$ ./simple_script.sh
-su: ./simple_script.sh: Permission denied
Permission denied! This happens because, if we analyze the previous command run and check the permissions, there is no x
, which represents the execution permission. Then, set the following permission:
gabriela@devops:~$ chmod +x simple_script.sh
Run the script again:
gabriela@devops:~$ ./simple_script.sh
this is a simple script
Let's check the permissions one more time:
gabriela@devops:~$ ls -la simple_script.sh
-rwxrwxr-x 1 gabriela gabriela 29 Feb 20 20:05 simple_script.sh
The x is in all the permission groups for the users, groups, and others. So, everyone can execute it. If you still give the execution just for the file owner or for the group, you can use chmod
for it, and use the same math
to set the permissions.