Skip to content

Commit ec353e6

Browse files
committed
Upades of the scripting chapter, added another script example.
Signed-off-by: V-Z <vojta@trapa.cz>
1 parent e52b240 commit ec353e6

File tree

2 files changed

+81
-27
lines changed

2 files changed

+81
-27
lines changed

presentation/linux_bash_metacentrum_course.tex

Lines changed: 57 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3116,6 +3116,7 @@ \subsection{Basic skeleton}
31163116
\item Launch with \texttt{./noninteractive.sh}
31173117
\item The most simple script:
31183118
\end{itemize}
3119+
\vfill
31193120
\begin{bashcode}
31203121
#!/bin/bash
31213122
# Simple non-interactive script - no communication with user
@@ -3126,26 +3127,11 @@ \subsection{Basic skeleton}
31263127
\end{bashcode}
31273128
\end{frame}
31283129
3129-
\subsection{BASH variables}
3130-
3131-
\begin{frame}{Special variables available in the script (selection)}
3132-
\begin{itemize}
3133-
\item \alert{\texttt{\$1}},~\ldots~(number from \texttt{1} up to number of parameters) --- individual positional parameters (see further for example)
3134-
\item \alert{\texttt{\$0}} --- path of the starting script
3135-
\item \alert{\texttt{\$\#}} --- number of command-line arguments
3136-
\item \alert{\texttt{\$*}} --- all of the positional parameters, seen as a~single word, must be quoted (i.e. \texttt{"\$*"})
3137-
\item \alert{\texttt{\$@}} --- same as \texttt{\$*}, but each parameter is a~quoted string --- the parameters are passed on intact, without interpretation or expansion, each parameter in the argument list is seen as a~separate word, should be quoted (i.e. something like \texttt{"\$@"})
3138-
\item \alert{\texttt{\$\$}} --- process ID (PID) of the script itself
3139-
\item \alert{\texttt{\$?}} --- Exit status of previous command, function, or the script itself
3140-
\item \href{https://www.tldp.org/LDP/abs/html/internalvariables.html}{See more variables\ldots}
3141-
\end{itemize}
3142-
\end{frame}
3143-
31443130
\subsection{Functions}
31453131
31463132
\begin{frame}[fragile]{Functions in BASH}{Pieces of code, which can be used repeatedly}
31473133
\begin{bashcode}
3148-
# Declare new function
3134+
# Declare new function within script
31493135
function MyNewFunction1 {
31503136
echo "Hello, $USER from $(groups) on $HOSTNAME!"
31513137
}
@@ -3165,11 +3151,27 @@ \subsection{Functions}
31653151
\end{bashcode}
31663152
\end{frame}
31673153
3154+
\subsection{BASH variables}
3155+
3156+
\begin{frame}{Special variables available in the script (selection)}
3157+
\begin{itemize}
3158+
\item These variables can be used within script e.g. to parse arguments provided by the user
3159+
\item \alert{\texttt{\$1}},~\ldots~(number from \texttt{1} up to number of parameters) --- individual positional parameters (see further for example)
3160+
\item \alert{\texttt{\$0}} --- path of the starting script
3161+
\item \alert{\texttt{\$\#}} --- number of command-line arguments
3162+
\item \alert{\texttt{\$*}} --- all of the positional parameters, seen as a~single word, must be quoted (i.e. \texttt{"\$*"})
3163+
\item \alert{\texttt{\$@}} --- same as \texttt{\$*}, but each parameter is a~quoted string --- the parameters are passed on intact, without interpretation or expansion, each parameter in the argument list is seen as a~separate word, should be quoted (i.e. something like \texttt{"\$@"})
3164+
\item \alert{\texttt{\$\$}} --- process ID (PID) of the script itself
3165+
\item \alert{\texttt{\$?}} --- Exit status of previous command, function, or the script itself
3166+
\item \href{https://www.tldp.org/LDP/abs/html/internalvariables.html}{See more variables\ldots}
3167+
\end{itemize}
3168+
\end{frame}
3169+
31683170
\subsection{Reading variables}
31693171
31703172
\begin{frame}{It is important to check user input\ldots}
31713173
\begin{center}
3172-
\includegraphics[width=7.5cm]{exploits_of_a_mom.png}
3174+
\includegraphics[width=8cm]{exploits_of_a_mom.png}
31733175
\end{center}
31743176
\begin{flushright}
31753177
\url{https://xkcd.com/327/}
@@ -3178,7 +3180,7 @@ \subsection{Reading variables}
31783180
\item By accident or purpose (attack), user can enter unexpected value
31793181
\begin{itemize}
31803182
\item In the \enquote{best} case, the script \enquote{just} crashes
3181-
\item Script can behave unexpectedly, returning very weird results
3183+
\item Script can behave unexpectedly, returning very weird results, damage data
31823184
\item Internal functions/commands can return error messages, which are hard to understand
31833185
\item Attacker can e.g. modify web content (\href{https://en.wikipedia.org/wiki/Cross-site_scripting}{XSS},~\ldots), obtain private data, root privileges,~\ldots
31843186
\end{itemize}
@@ -3246,6 +3248,7 @@ \subsection{Reading variables}
32463248
\begin{itemize}
32473249
\item Detailed explanations of all features used here are in various following slides\ldots{ }See scripts \texttt{interactive2\{whiles,functions\}.sh}
32483250
\end{itemize}
3251+
\vfill
32493252
\begin{bashcode}
32503253
... # Following code replace lines 3 and 4 from previous script
32513254
NUMBER='^[0-9]+$'
@@ -3379,6 +3382,7 @@ \subsection{Reading variables}
33793382
\item See \texttt{interactive5.sh} for complete example
33803383
\item \texttt{getopts} reads short (one-letter) parameters, they can have input value (marked by \texttt{:})
33813384
\end{itemize}
3385+
\vfill
33823386
\begin{bashcode}
33833387
#!/bin/bash
33843388
# All provided values are evaluated in while cycles...
@@ -3471,6 +3475,31 @@ \subsection{Reading variables}
34713475
\end{bashcode}
34723476
\end{frame}
34733477
3478+
\begin{frame}[fragile]{Simple providing of input file}
3479+
\begin{bashcode}
3480+
#!/bin/bash
3481+
# We expect exactly one parameter
3482+
if [ "$#" -ne "1" ]; then
3483+
echo "Error! Exactly one parameter is required!"
3484+
exit 1
3485+
fi
3486+
# Verify that file exists and is readable
3487+
if [ ! -r "$1" ]; then
3488+
echo "Error! The file provided does not exist or is not readable!"
3489+
exit 1
3490+
fi
3491+
# Do the operation with input file..
3492+
echo "Size of the file is $(du -sh "$1" | cut -f 1)."
3493+
echo "The file has $(wc -l "$1" | cut -d ' ' -f 1) lines."
3494+
echo "Making backup of the file $1..."
3495+
cp "$1" "$1".bak || { echo "Error! Making backup of $1 failed!"; exit 1; }
3496+
echo "Done!"
3497+
exit
3498+
# Use the script with some text file...
3499+
./interactive6.sh long_text.txt
3500+
\end{bashcode}
3501+
\end{frame}
3502+
34743503
\subsection{Branching the code}
34753504
34763505
\begin{frame}[fragile]{If branching (examples are elsewhere)}
@@ -3505,14 +3534,14 @@ \subsection{Branching the code}
35053534
\begin{itemize}
35063535
\item Escaping variables and values by double quotes (\texttt{"}\ldots\texttt{"}) is recommended (to be sure), but not strictly required all the time
35073536
\end{itemize}
3508-
\item \texttt{if [ ! -f regularfile ];} \ldots --- reverted condition (\texttt{!})
3537+
\item \texttt{if [ !} -\texttt{f regularfile ];} \ldots --- reverted condition (\texttt{!})
35093538
\item Single-bracket conditions --- file, string, or arithmetic conditions
35103539
\item Double-bracket syntax --- enhanced
35113540
\begin{itemize}
35123541
\item Allow usage of regular expressions and globing patterns
35133542
\item Word splitting is prevented --- \texttt{\$STRINGVAR} can contain spaces
3514-
\item Expanding file names --- \texttt{if [[ -a *.sh ]]} (variant with only one bracket doesn't work when there are multiple sh files)
3515-
\item Allows more detailed test, e.g. \texttt{if [[ \$num -eq 3 \&\& "\$STRINGVAR" == XXX ]] \ldots}
3543+
\item Expanding file names --- \texttt{if [[} -\texttt{a *.sh ]]} (variant with only one bracket doesn't work when there are multiple sh files)
3544+
\item Allows more detailed test, e.g. \texttt{if [[ \$num} -\texttt{eq 3 \&\& "\$STRINGVAR" == XXX ]] \ldots}
35163545
\end{itemize}
35173546
\end{itemize}
35183547
\item -\texttt{eq} --- Equal to
@@ -3531,8 +3560,8 @@ \subsection{Branching the code}
35313560
\item \texttt{\$STR1 == \$STR2} --- True if both strings are equal
35323561
\item \texttt{\$STR} --- True if string \texttt{\$STR} is assigned a~value and is not null
35333562
\item \texttt{\$STR1 != \$STR2} --- True if both strings are unequal
3534-
\item -\texttt{a} --- Performs the \texttt{AND} function (\texttt{[ \ldots -a \ldots~]} or \texttt{[ \ldots~] \&\& [ \ldots~]})
3535-
\item -\texttt{o} --- Performs the \texttt{OR} function (\texttt{[ \ldots -o \ldots~]} or \texttt{[ \ldots~] || [ \ldots~]})
3563+
\item -\texttt{a} --- Performs the \texttt{AND} function (\texttt{[ \ldots} -\texttt{a \ldots~]} or \texttt{[ \ldots~] \&\& [ \ldots~]})
3564+
\item -\texttt{o} --- Performs the \texttt{OR} function (\texttt{[ \ldots} -\texttt{o \ldots~]} or \texttt{[ \ldots~] || [ \ldots~]})
35363565
\item Do not confuse globing patterns and regular expressions when using \texttt{[[ \ldots~]]}
35373566
\begin{itemize}
35383567
\item Shell globing: \texttt{if [[ "\$STRINGVAR" \textbf{==} ?[sS]tring* ]]; then} --- \texttt{?} represents single character \texttt{[]} any character inside and \texttt{*} zero or more characters
@@ -3548,6 +3577,7 @@ \subsection{Branching the code}
35483577
\item RAxML binaries must be in \texttt{\$PATH}
35493578
\item See \texttt{raxml\_if.sh} for whole script
35503579
\end{itemize}
3580+
\vfill
35513581
\begin{bashcode}
35523582
if grep -iq avx2 /proc/cpuinfo; then # Does the CPU support AVX2?
35533583
RAXML='raxmlHPC-AVX2' # Select appropriate binary
@@ -3567,6 +3597,7 @@ \subsection{Branching the code}
35673597
\item Same task as on previous slide, but instead of if-then branching it is using \texttt{case}
35683598
\item See \texttt{raxml\_case.sh} for whole script
35693599
\end{itemize}
3600+
\vfill
35703601
\begin{bashcode}
35713602
# Determine which CPU is available and which binary use then
35723603
CPUFLAGS=$(grep -i flags /proc/cpuinfo | uniq)
@@ -3597,7 +3628,7 @@ \subsection{Loops}
35973628
for JPGF in *.jpg; do convert $JPGF -resize 100x100 thumbs-$JPGF; done
35983629
# More commands in a block
35993630
for JPGF in $(ls -1 *.jpg); do
3600-
echo "Processing JPGF $JPGF"
3631+
echo "Processing JPG $JPGF"
36013632
convert $JPGF -resize 100x100 thumbs-$JPGF
36023633
echo "File thumbs-$file created"
36033634
done
@@ -3614,8 +3645,7 @@ \subsection{Loops}
36143645
\begin{bashcode}
36153646
# while cycle is evaluating condition and if it is equal to 0 (TRUE)
36163647
# the cycle body is launched, repeatedly while the condition is met
3617-
while condition
3618-
do
3648+
while condition; do
36193649
commands
36203650
done
36213651
# Like while cycle, but until condition is not equal to zero
@@ -3627,7 +3657,7 @@ \subsection{Loops}
36273657
if [condition]; then # If something happens
36283658
break; fi # End up the cycles and continue by following commands
36293659
while read TEXTLINE; do # Run cycles on text file
3630-
commands...
3660+
commands... # TEXTLINE contains in each cycle one line of the file
36313661
done < text_file_to_process.txt
36323662
while :; do echo "Press CTRL+C to exit..."; done # Infinite loop
36333663
for (( ; ; )) ; do echo "Press CTRL+C to exit..."; done # Infinite loop

scripts_data/interactive6.sh

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#!/bin/bash
2+
3+
# We expect exactly one parameter
4+
if [ "$#" -ne "1" ]; then
5+
echo "Error! Exactly one parameter is required!"
6+
exit 1
7+
fi
8+
9+
# Verify that file exists and is readable
10+
if [ ! -r "$1" ]; then
11+
echo "Error! The file provided does not exist or is not readable!"
12+
exit 1
13+
fi
14+
15+
# Do the operation with input file..
16+
echo "Size of the file is $(du -sh "$1" | cut -f 1)."
17+
echo "The file has $(wc -l "$1" | cut -d ' ' -f 1) lines."
18+
19+
echo "Making backup of the file $1..."
20+
cp "$1" "$1".bak || { echo "Error! Making backup of $1 failed!"; exit 1; }
21+
22+
echo "Done!"
23+
24+
exit

0 commit comments

Comments
 (0)