Bash Scripting
Bash
Bash variables, redirections, history substitution, metacharacters, startup files, etc.
Shell Scripting
Shell scripting and logical constructs
Bash variables, redirections, history substitution, metacharacters, startup files, etc.
Shell scripting and logical constructs
Current shell
Sub-shell (child shell)
created within a shell to run a program.
two types of variables: local (or shell) and environment. local variable
env
or the printenv
command to view predefined environment variables.export
, unset
, and echo
to define and undefine environment variables[root@localhost ~]# env
SHELL=/bin/bash
HISTCONTROL=ignoredups
HISTSIZE=1000
HOSTNAME=localhost
PWD=/root
LOGNAME=root
XDG_SESSION_TYPE=tty
MOTD_SHOWN=pam
HOME=/root
LANG=en_US.UTF-8
LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=01;37;41:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.webp=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=01;36:*.au=01;36:*.flac=01;36:*.m4a=01;36:*.mid=01;36:*.midi=01;36:*.mka=01;36:*.mp3=01;36:*.mpc=01;36:*.ogg=01;36:*.ra=01;36:*.wav=01;36:*.oga=01;36:*.opus=01;36:*.spx=01;36:*.xspf=01;36:
SSH_CONNECTION=192.168.0.233 56990 192.168.0.169 22
XDG_SESSION_CLASS=user
SELINUX_ROLE_REQUESTED=
TERM=xterm-256color
LESSOPEN=||/usr/bin/lesspipe.sh %s
USER=root
SELINUX_USE_CURRENT_RANGE=
SHLVL=1
XDG_SESSION_ID=1
XDG_RUNTIME_DIR=/run/user/0
SSH_CLIENT=192.168.0.233 56990 22
which_declare=declare -f
PATH=/root/.local/bin:/root/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
SELINUX_LEVEL_REQUESTED=
DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/0/bus
MAIL=/var/spool/mail/root
SSH_TTY=/dev/pts/0
BASH_FUNC_which%%=() { ( alias;
eval ${which_declare} ) | /usr/bin/which --tty-only --read-alias --read-functions --show-tilde --show-dot $@
}
_=/usr/bin/env
OLDPWD=/dev/vg200
hostname
or parentheses $(hostname).set -o noclobber
set +o noclobber
[root@localhost ~]# vim test.txt
[root@localhost ~]# set -o noclobber
[root@localhost ~]# echo "Hello" > test.txt
-bash: test.txt: cannot overwrite existing file
[root@localhost ~]# set +o noclobber
[root@localhost ~]# echo "Hello" > test.txt
[root@localhost ~]# cat test.txt
Hello
history
commandset +o history
set -o history
[root@localhost ~]# set +o history
[root@localhost ~]# history | tail
126 ls
127 vim test.txt
128 set -o noclobber
129 echo "Hello" > test.txt
130 set +o noclobber
131 echo "Hello" > test.txt
132 cat test.txt
133 history | tail
134 set +0 history
135 set +o history
[root@localhost ~]# vim test2.txt
[root@localhost ~]# history | tail
126 ls
127 vim test.txt
128 set -o noclobber
129 echo "Hello" > test.txt
130 set +o noclobber
131 echo "Hello" > test.txt
132 cat test.txt
133 history | tail
134 set +0 history
135 set +o history
[root@localhost ~]# set -o history
[root@localhost ~]# vim test2.txt
[root@localhost ~]# history | tail
128 set -o noclobber
129 echo "Hello" > test.txt
130 set +o noclobber
131 echo "Hello" > test.txt
132 cat test.txt
133 history | tail
134 set +0 history
135 set +o history
136 vim test2.txt
137 history | tail
Add timestamps to history output system wide:
echo "export HISTTIMEFORMAT='%F %T '" >> /etc/profile && source /etc/profile
~+ - refers to current directory
~- - Refers to previous working directory.
~USER - Refers to specific user’s home directory.
[root@localhost ~]# alias
alias cp='cp -i'
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
alias grep='grep --color=auto'
alias l.='ls -d .* --color=auto'
alias ll='ls -l --color=auto'
alias ls='ls --color=auto'
alias mv='mv -i'
alias rm='rm -i'
alias xzegrep='xzegrep --color=auto'
alias xzfgrep='xzfgrep --color=auto'
alias xzgrep='xzgrep --color=auto'
alias zegrep='zegrep --color=auto'
alias zfgrep='zfgrep --color=auto'
alias zgrep='zgrep --color=auto'
[root@localhost ~]# alias frog='pwd'
[root@localhost ~]# frog
/root
[root@localhost ~]# unalias frog
[root@localhost ~]# frog
-bash: frog: command not found
caret (^)
period (.)
asterisk (*)
question mark (?)
pipe (|)
angle brackets (< >)
curly brackets ({})
square brackets ([])
parentheses (())
plus (+)
exclamation mark (!)
semicolon (;)
Backslash (\)
single quotation (‘’)
double quotation (“”)
grep
commandFlags -i
-n
-v
-w
-E
-e
commands and control sequences for administering the jobs.
jobs
bg
Ctrl+z
.fg
Ctrl+z
output plus sign (+) - indicates the current background job minus sign (-) - signifies the previous job. Stopped - currently suspended - can be signaled to continue their execution with bg or fg
env
printenv
echo $PATH
echo $HOME
echo $SHELL
echo $TERM
echo $PPID
echo $PS1
echo $USER
VR1=RHEL9
echo $VR1
echo $VR1
exit
export VR1
echo $VR1
unset VR1
VR2="I love RHEL 9"
export VR3="I love RHEL 9"
set
export PS1="< $LOGNAME on $HOSTNAME in \$PWD > "
vim .bash_profile
cat < /etc/redhat-release
ls > ls.out
ls 1> ls.out
set -o noclobber
ls > ls.out
set +o noclobber
ls >> ls.out
or
ls 1>> ls.out
find / -name core -print 2> /dev/null
ls /usr /cdr &> outerr.out
or
ls /usr /cdr 1> outerr.out 2>&1
\# means to redirect file descriptor 1 to file outerr.out as well as to file descriptor 2.
ls /usr/cdr &>> outerr.out
echo $HISTFILE
echo $HISTSIZE
echo $HISTFILESIZE
history
history 10
!15
!ch
!?grep?
history -d 24
!!
echo ~
echo ~+
echo ~-
echo ~user1
cd ~user1
pwd
cd ~/Documents/
ls -ld ~root/Desktop
su - user1
alias
alias
alias search='find / -name core -exec ls -l {} \;'
search
alias rm='rm -i'
rm file1
unalias search rm
ls /etc/ma*
ls -d .*
ls /var/log/*.log
ls -d /var/log/????
ls /usr/bin/[yw]*
ls -d /etc/systemd/system/[m-o]*
ls -d /etc/systemd/system/[!m-o]*
ls -l /etc | less
last | nl
ls -l /proc | grep -v root | grep -iv dec | nl | tail -4
rm \*
echo '$LOGNAME'
echo "$SHELL"
echo "\$PWD"
echo "'\'"
grep operator /etc/passwd
grep 'aliases and functions' .bashrc
grep -nv nologin /etc/passwd
grep ^root /etc/passwd
grep bash$ /etc/passwd
grep -v ^$ /etc/login.defs
grep -i path /etc/bashrc
grep -w acce.. /etc/lvm/lvm.conf
ls
command output that include either (-E) the pattern “cron” or “ly”.ls -l /etc | grep -E 'cron|ly'
sudo grep -ve ^$ -ve ^# /etc/ssh/sshd_config
man 7 regex
man grep
jobs -l
fg %1
bg %1
kill 31726
head /etc/bashrc
head /etc/profile
ls -l /etc/profile.d/
cat ~/.bashrc
cat ~/.bash_profile
vim ~/.bash_profile
export PS1='$USERNAME $PWD'
ls
command on /etc, /dvd, and /var. Have the output printed on the screen and the errors forwarded to file /tmp/ioerror.ls /etc /dvd /var 2> /tmp/ioerror
cat /tmp/ioerror
A group of Linux commands along with control structures and optional comments stored in a text file.
Can be executed directly at the Linux command prompt.
Do not need to be compiled as they are interpreted by the shell line by line.
Managing packages and users, administering partitions and file systems, monitoring file system utilization, trimming log files, archiving and compressing files, finding and removing unnecessary files, starting and stopping database services and applications, and producing reports.
Run by the shell one at a time in the order in which they are listed.
Each line is executed as if it is typed and run at the command prompt.
Control structures are utilized for creating and managing conditional and looping constructs.
Comments are also generally included to add information about the script such as the author name, creation date, previous modification dates, purpose, and usage.
If the script encounters an error during execution, the error message is printed on the screen.
Can use the nl
command to enumerate the lines for troubleshooting.
Can store your scripts in the /usr/local/bin directory, which is included in the PATH of all users by default.
#!/bin/bash
echo "Display Basic System Information"
echo "=================================="
echo
echo "The hostname, hardware, and OS information is:"
/usr/bin/hostnamectl
echo
echo "The Following users are currently logged in:"
/usr/bin/who
chmod +x /usr/local/bin/sys_info.sh
ll /usr/local/bin/sys_info.sh
-rwxr-xr-x. 1 root root 244 Jul 30 09:47 /usr/local/bin/sys_info.sh>)
Let’s run the script and see what the output will look like:
$ sys_info.sh
Display Basic System Information
==================================
The hostname, hardware, and OS information is:
Static hostname: server30
Icon name: computer-vm
Chassis: vm 🖴
Machine ID: eaa6174e108d4a27bd619754…
Boot ID: 13d8b3c167b24757b3678e4f…
Virtualization: oracle
Operating System: Red Hat Enterprise Linux…
CPE OS Name: cpe:/o:redhat:enterprise…
Kernel: Linux 5.14.0-362.24.1.el…
Architecture: x86-64
Hardware Vendor: innotek GmbH
Hardware Model: VirtualBox
Firmware Version: VirtualBox
The Following users are currently logged in:
root pts/0 2024-07-30 07:22 (172.16.7.95)
Can either append the -x
option to the “#!/bin/bash
” at the beginning of the script to look like “#!/bin/bash -x
”, or execute the script as follows:
[root@server30 ~]# bash -x sys_info.sh
+ echo 'Display Basic System Information'
Display Basic System Information
+ echo ==================================
==================================
+ echo
+ echo 'The hostname, hardware, and OS information is:'
The hostname, hardware, and OS information is:
+ /usr/bin/hostnamectl
Static hostname: server30
Icon name: computer-vm
Chassis: vm 🖴
Machine ID: eaa6174e108d4a27bd6197548ce77270
Boot ID: 13d8b3c167b24757b3678e4fd3fe19ee
Virtualization: oracle
Operating System: Red Hat Enterprise Linux 9.3 (Plow)
CPE OS Name: cpe:/o:redhat:enterprise_linux:9::baseos
Kernel: Linux 5.14.0-362.24.1.el9_3.x86_64
Architecture: x86-64
Hardware Vendor: innotek GmbH
Hardware Model: VirtualBox
Firmware Version: VirtualBox
+ echo
+ echo 'The Following users are currently logged in:'
The Following users are currently logged in:
+ /usr/bin/who
root pts/0 2024-07-30 07:22 (172.16.7.95)
Change one of the echo commands in the script to “iecho” and re-run the script in the debug mode to see the error:
[root@server30 ~]# bash -x sys_info.sh
+ echo 'Display Basic System Information'
Display Basic System Information
+ echo ==================================
==================================
+ iecho
/usr/local/bin/sys_info.sh: line 4: iecho: command not found
+ echo 'The hostname, hardware, and OS information is:'
The hostname, hardware, and OS information is:
+ /usr/bin/hostnamectl
Static hostname: server30
Icon name: computer-vm
Chassis: vm 🖴
Machine ID: eaa6174e108d4a27bd6197548ce77270
Boot ID: 13d8b3c167b24757b3678e4fd3fe19ee
Virtualization: oracle
Operating System: Red Hat Enterprise Linux 9.3 (Plow)
CPE OS Name: cpe:/o:redhat:enterprise_linux:9::baseos
Kernel: Linux 5.14.0-362.24.1.el9_3.x86_64
Architecture: x86-64
Hardware Vendor: innotek GmbH
Hardware Model: VirtualBox
Firmware Version: VirtualBox
+ echo
+ echo 'The Following users are currently logged in:'
The Following users are currently logged in:
+ /usr/bin/who
root pts/0 2024-07-30 07:22 (172.16.7.95)
[root@server30 ~]# vim /usr/local/bin/use_var.sh
#!/bin/bash
echo "Setting a Local Variable"
echo "========================"
SYSNAME=server30.example.com
echo "The hostname of this system is $SYSNAME"
[root@server30 ~]# chmod +x /usr/local/bin/use_var.sh
[root@server30 ~]# use_var.sh
Setting a Local Variable
========================
The hostname of this system is server30.example.com
If you run the echo command to see what is stored in the SYSNAME variable, you will get nothing:
[root@server30 ~]# echo $SYSNAME
The following script called pre_env.sh will display the values of SHELL and LOGNAME environment variables:
[root@server30 ~]# vim /usr/local/bin/pre_env.sh
#!/bin/bash
echo "The location of my shell command is:"
echo $SHELL
echo "I am logged in as $LOGNAME"
[root@server30 ~]# chmod +x /usr/local/bin/pre_env.sh
[root@server30 ~]# pre_env.sh
The location of my shell command is:
/bin/bash
I am logged in as root
Can use the command substitution feature of the bash shell and store the output generated by the command into a variable.
Two different ways to use command substitution: Backtics or subshell
#!/bin/bash
SYSNAME=$(hostname)
KERNVER=`uname -r`
echo "The hostname is $SYSNAME"
echo "The kernel version is $KERNVER"
[root@server30 ~]# vim /usr/local/bin/cmd_out.sh
[root@server30 ~]# chmod +x /usr/local/bin/cmd_out.sh
[root@server30 ~]# cmd_out.sh
The hostname is server30
The kernel version is 5.14.0-362.24.1.el9_3.x86_64
Create com_line_arg.sh to show the supplied arguments, total count, value of the first argument, and PID of the script:
[root@server30 ~]# vim /usr/local/bin/com_line_arg.sh
#!/bin/bash
echo "There are $# arguments specified at the command line"
echo "The arguments supplied are: $*"
echo "The first argument is: $1"
echo "The Process ID of the script is: $$"
[root@server30 ~]# chmod +x /usr/local/bin/com_line_arg.sh
[root@server30 ~]# com_line_arg.sh
There are 0 arguments specified at the command line
The arguments supplied are:
The first argument is:
The Process ID of the script is: 1935
[root@server30 ~]# com_line_arg.sh the dog jumped over the frog
There are 6 arguments specified at the command line
The arguments supplied are: the dog jumped over the frog
The first argument is: the
The Process ID of the script is: 1936
shift
command
[root@server30 ~]# vim /usr/local/bin/com_line_arg_shift.sh
#!/bin/bash
echo "There are $# arguments specified at the command line"
echo "The arguments supplied are: $*"
echo "The first argument is: $1"
echo "The Process ID of the script is: $$"
shift
echo "The new first argument after the first shift is: $1"
shift
echo "The new first argument after the second shift is: $1"
[root@server30 ~]# chmod +x /usr/local/bin/com_line_arg_shift.sh
[root@server30 ~]# com_line_arg_shift.sh
There are 0 arguments specified at the command line
The arguments supplied are:
The first argument is:
The Process ID of the script is: 1941
The new first argument after the first shift is:
The new first argument after the second shift is:
[root@server30 ~]# com_line_arg_shift.sh the dog jumped over the frog
There are 6 arguments specified at the command line
The arguments supplied are: the dog jumped over the frog
The first argument is: the
The Process ID of the script is: 1942
The new first argument after the first shift is: dog
The new first argument after the second shift is: jumped
The shell offers two logical constructs: if-then-fi case
Exit Codes (exit values)
Let’s look at the following two examples to understand their usage:
[root@server30 ~]# pwd
/root
[root@server30 ~]# echo $?
0
[root@server30 ~]# man
What manual page do you want?
For example, try 'man man'.
[root@server30 ~]# echo $?
1
Test Conditions
test
command or by enclosing them within the square brackets [].man test
Operation on Integer Value
integer1 -eq (-ne) integer2
integer1 -lt (-gt) integer2
integer1 -le (-ge) integer2
Operation on String Value
string1=(!=)string2
-l string or -z string
string or -n string
Operation on File
-b (-c) file
-d (-f) file
-e (-s) file
-L file
-r (-w) (-x) file
-u (-g) (-k) file
file1 -nt (-ot) file2
Logical Operators
!
-a
or &&
(two ampersand characters)
[ -b file1 && -r file1 ]
-o
or ||
(two pipe characters)
[ (x == 1 -o y == 2) ]
if
and ends with a fi
The general syntax of this statement is as follows:
if condition > then > action > fi
Create if_then_fi.sh to determine the number of arguments and print an error message if there are none provided:
[root@server30 ~]# vim /usr/local/bin/if_then_fi.sh
#!/bin/bash
if [ $# -ne 2 ] # Ensure there is a space after [ and before ]
then
echo "Error: Invalid number of arguments supplied"
echo "Usage: $0 source_file destination_file"
exit 2
fi
echo "Script terminated"
[root@server30 ~]# chmod +x /usr/local/bin/if_then_fi.sh
[root@server30 ~]# if_then_fi.sh
Error: Invalid number of arguments supplied
Usage: /usr/local/bin/if_then_fi.sh source_file destination_file
This script will display the following messages on the screen if it is executed without exactly two arguments specified at the command line:
[root@server30 ~]# if_then_fi.sh
Error: Invalid number of arguments supplied
Usage: /usr/local/bin/if_then_fi.sh source_file destination_file
Return code value reflects the exit code in the script .
[root@server30 ~]# echo $?
2
Return code will be 0 if you supply a pair of arguments:
[root@server30 ~]# if_then_fi.sh a b
Script terminated
[root@server30 ~]# echo $?
0
The general syntax of this statement is as follows:
if condition > then > action1 > else > action2 > fi
Create a script called if_then_else_fi.sh that will accept an integer value as an argument and tell if the value is positive or negative:
vim /usr/local/bin/if_then_else_fi.sh
#!/bin/bash
if [ $1 -gt 0 ]
then
echo "$1 is a positive integer value"
else
echo "$1 is a negative integer value"
fi
[root@server30 ~]# chmod +x /usr/local/bin/if_then_else_fi.sh
[root@server30 ~]# if_then_else_fi.sh
/usr/local/bin/if_then_else_fi.sh: line 2: [: -gt: unary operator expected
is a negative integer value
[root@server30 ~]# if_then_else_fi.sh 3
3 is a positive integer value
[root@server30 ~]# if_then_else_fi.sh -3
-3 is a negative integer value
[root@server30 ~]# if_then_else_fi.sh a
/usr/local/bin/if_then_else_fi.sh: line 2: [: a: integer expression expected
a is a negative integer value
[root@server30 ~]# echo $?
0
The general syntax of this statement is as follows:
if condition1 > then action1 > elif condition2 > then action2 > elif condition3 > then action3 > else > action(n) > fi
Create if_then_elif_fi.sh script to accept an integer value as an argument and tell if the integer is positive, negative, or zero. If a non-integer value or no argument is supplied, the script will complain. Employ the exit command after each action to help you identify where it exited.
[root@server30 ~]# vim /usr/local/bin/if_then_elif_fi.sh
#!/bin/bash
if [ $1 -gt 0 ]
then
echo "$1 is a positive integer value"
exit 1
elif [ $1 -eq 0 ]
then
echo "$1 is a zero integer value"
exit 2
elif [ $1 -lt 0 ]
then
echo "$1 is a negative integer value"
exit 3
else
echo "$1 is not an integer value. Please supply an i
nteger."
exit 4
fi
[root@server30 ~]# if_then_elif_fi.sh -0
-0 is a zero integer value
[root@server30 ~]# echo $?
2
[root@server30 ~]# if_then_elif_fi.sh -1
-1 is a negative integer value
[root@server30 ~]# echo $?
3
[root@server30 ~]# if_then_elif_fi.sh 10
10 is a positive integer value
[root@server30 ~]# echo $?
1
[root@server30 ~]# if_then_elif_fi.sh abd
/usr/local/bin/if_then_elif_fi.sh: line 2: [: abd: integer expression expected
/usr/local/bin/if_then_elif_fi.sh: line 6: [: abd: integer expression expected
/usr/local/bin/if_then_elif_fi.sh: line 10: [: abd: integer expression expected
abd is not an integer value. Please supply an i
nteger.>)
[root@server30 ~]# echo $?
4
Create ex200_ex294.sh to display the name of the Red Hat exam RHCSA or RHCE in the output based on the input argument (ex200 or ex294). If a random or no argument is provided, it will print “Usage: Acceptable values are ex200 and ex294”. Add white spaces in the conditions.
[root@server30 ~]# vim /usr/local/bin/ex200_ex294.sh
#!/bin/bash
if [ "$1" = ex200 ]
then
echo "RHCSA"
elif [ "$1" = ex294 ]
then
echo "RHCE"
else
echo "Usage: Acceptable values are ex200 and ex294"
fi
[root@server30 ~]# chmod +x /usr/local/bin/ex200_ex294.sh
[root@server30 ~]# ex200_ex294.sh ex200
RHCSA
[root@server30 ~]# ex200_ex294.sh ex294
RHCE
[root@server30 ~]# ex200_ex294.sh frog
Usage: Acceptable values are ex200 and ex294
pvcreate
command on each disk one at a time manually or employ a loop to do it for you.Three looping constructs: for-do-done
let
command
Operators used in test conditions
!
+ / – / * / /
%
< / <=
> / >=
=
== / !=
The general syntax of this construct is as follows:
for VAR in list > do > action > done
Create script for_do_done.sh script that initializes the variable COUNT to 0. The for loop will read each letter sequentially from the range placed within curly brackets (no spaces before the letter A and after the letter Z), assign it to another variable LETTER, and display the value on the screen. The expr
command is an arithmetic processor, and it is used here to increment the COUNT by 1 at each loop iteration.
[root@server10 ~]# vim /usr/local/bin/for_do_done.sh
#!/bin/bash
COUNT=0
for LETTER in {A..Z}
do
COUNT=`/usr/bin/expr $COUNT + 1`
echo "Letter $COUNT is [$LETTER]"
done
[root@server10 ~]# chmod +x /usr/local/bin/for_do_done.sh
[root@server10 ~]# for_do_done.sh
Letter 1 is [A]
Letter 2 is [B]
Letter 3 is [C]
Letter 4 is [D]
Letter 5 is [E]
Letter 6 is [F]
Letter 7 is [G]
Letter 8 is [H]
Letter 9 is [I]
Letter 10 is [J]
Letter 11 is [K]
Letter 12 is [L]
Letter 13 is [M]
Letter 14 is [N]
Letter 15 is [O]
Letter 16 is [P]
Letter 17 is [Q]
Letter 18 is [R]
Letter 19 is [S]
Letter 20 is [T]
Letter 21 is [U]
Letter 22 is [V]
Letter 23 is [W]
Letter 24 is [X]
Letter 25 is [Y]
Letter 26 is [Z]
Create script create_user.sh script to create several Linux user accounts. As each account is created, the value of the variable ? is checked. If the value is 0, a message saying the account is created successfully will be displayed, otherwise the script will terminate. In case of a successful
account creation, the passwd
command will be invoked to assign the user the same password as their username.
[root@server10 ~]# vim /usr/local/bin/create_user.sh
#!/bin/bash
for USER in user{10..12}
do
echo "Create account for user $USER"
/usr/sbin/useradd $USER
if [ $? = 0 ]
then
echo $USER | /usr/bin/passwd --stdin $USER
echo "$USER is created successfully"
else
echo "Failed to create account $USER"
exit
fi
done
[root@server10 ~]# chmod +x /usr/local/bin/create_user.sh
[root@server10 ~]# create_user.sh
Create account for user user10
Changing password for user user10.
passwd: all authentication tokens updated successfully.
user10 is created successfully
Create account for user user11
Changing password for user user11.
passwd: all authentication tokens updated successfully.
user11 is created successfully
Create account for user user12
Changing password for user user12.
passwd: all authentication tokens updated successfully.
user12 is created successfully
Script fails if ran again:
[root@server10 ~]# create_user.sh
Create account for user user10
useradd: user 'user10' already exists
Failed to create account user10
pvcreate
command. vim /usr/local/bin/lvscript.sh
vgscript
and add both physical volumes to it. #!/bin/bash
for DEVICE in "/dev/sd"{b..c}
do
echo "Creating partition 1 with the size of 400MB on $DEVICE"
parted $DEVICE mklabel msdos
parted $DEVICE mkpart primary 1 401
pvcreate $DEVICE[1]
echo "Creating partition 2 with the size of 400MB on $DEVICE"
parted $DEVICE mkpart primary 402 802
pvcreate $DEVICE[2]
vgcreate vgscript $DEVICE[1] $DEVICE[2]
done
for LV in "lvscript"{1..3}
do
echo "Creating logical volume $LV in volume group vgscript with the size of 200MB"
lvcreate vgscript -L 200MB -n $LV
done
vim /usr/local/bin/fsscript.sh
[root@server40 ~]# chmod +x /usr/local/bin/fsscript.sh
#!/bin/bash
for DEVICE in lvscript{1..3}
do
if [ "$DEVICE" = lvscript1 ]
then
echo "Creating xfs filesystem on logical volume lvscript1"
echo
mkfs.xfs /dev/vgscript/lvscript1
echo "Creating /mnt/xfs"
mkdir /mnt/xfs
echo "Mounting filesystem"
mount /dev/vgscript/lvscript1 /mnt/xfs
elif [ "$DEVICE" = lvscript2 ]
then
echo "Creating ext4 filesystem on logical volume lvscript2"
echo
mkfs.ext4 /dev/vgscript/lvscript2
echo "Creating /mnt/ext4"
mkdir /mnt/ext4
echo "Mounting filesystem"
mount /dev/vgscript/lvscript2 /mnt/ext4
elif [ "$DEVICE" = lvscript3 ]
then
echo "Creating vfat filesystem on logical volume lvscript3"
echo
mkfs.vfat /dev/vgscript/lvscript3
echo "Creating /mnt/vfat"
mkdir /mnt/vfat
echo "Mounting filesystem"
mount /dev/vgscript/lvscript3 /mnt/vfat
echo
echo
echo "Done!"
df -h
else
echo
fi
done
[root@server40 ~]# fsscript.sh
Creating xfs filesystem on logical volume lvscript1
Filesystem should be larger than 300MB.
Log size should be at least 64MB.
Support for filesystems like this one is deprecated and they will not be supported in future releases.
meta-data=/dev/vgscript/lvscript1 isize=512 agcount=4, agsize=12800 blks
= sectsz=512 attr=2, projid32bit=1
= crc=1 finobt=1, sparse=1, rmapbt=0
= reflink=1 bigtime=1 inobtcount=1 nrext64=0
data = bsize=4096 blocks=51200, imaxpct=25
= sunit=0 swidth=0 blks
naming =version 2 bsize=4096 ascii-ci=0, ftype=1
log =internal log bsize=4096 blocks=1368, version=2
= sectsz=512 sunit=0 blks, lazy- count=1
realtime =none extsz=4096 blocks=0, rtextents=0
Creating /mnt/xfs
Mounting filesystem
Creating ext4 filesystem on logical volume lvscript2
mke2fs 1.46.5 (30-Dec-2021)
Creating filesystem with 204800 1k blocks and 51200 inodes
Filesystem UUID: b16383bf-7b65-4a00-bb6d-c297733f60b3
Superblock backups stored on blocks:
8193, 24577, 40961, 57345, 73729
Allocating group tables: done
Writing inode tables: done
Creating journal (4096 blocks): done
Writing superblocks and filesystem accounting information: done
Creating /mnt/ext4
Mounting filesystem
Creating vfat filesystem on logical volume lvscript3
mkfs.fat 4.2 (2021-01-31)
Creating /mnt/vfat
Mounting filesystem
Done!
[root@server40 ~]# vim /usr/local/bin/network.sh
#!/bin/bash
cp /etc/hosts /etc/hosts.bak &&
nmcli c a type Ethernet con-name enp0s9 ifname enp0s9 ip4 10.32.32.2/24 gw4 10.32.32.1
echo "10.32.33.14 frog.example.com frog" >> /etc/hosts
[root@server40 ~]# chmod +x /usr/local/bin/network.sh
[root@server40 ~]# network.sh
Connection 'enp0s9' (5a342243-e77b-452e-88e2-8838d3ecea6d) successfully added.
[root@server40 ~]# cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
10.32.33.14 frog.example.com frog
[root@server40 ~]# ip a
enp0s9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 08:00:27:1d:f4:c1 brd ff:ff:ff:ff:ff:ff
inet 10.32.32.2/24 brd 10.32.32.255 scope global noprefixroute enp0s9
valid_lft forever preferred_lft forever
inet6 fe80::2c5d:31cc:1d79:6b43/64 scope link noprefixroute
valid_lft forever preferred_lft forever
[root@server40 ~]# nmcli d s
DEVICE TYPE STATE CONNECTION
enp0s3 ethernet connected enp0s3
enp0s8 ethernet connected enp0s8
enp0s9 ethernet connected enp0s9
lo loopback connected (externally) lo