1. We give the scripts executable permission via:
chmod u+rx
2. We name a bash script as scriptname.bash or scriptname.sh
3. To clean up logs, we can realize this function in three ways:
a. cat /dev/null > /var/log/messages
b. > /var/log/messages
c. echo " " > /var/log/messages
4. An enhanced and generalized version of bash script that is to clean up logs
=======================================================================================================
#!/bin/bash
# Clean up logs
LOG_DIR=/var/log # That is the log folder
ROOT_UID=0 # Only user with $UID 0 has root privilege
LINES=50 # Default number of lines saved
E_XCD=86 # Can't change directory?
E_NOTROOT=87 # Non-root exit error
# Run as root
if [ "$UID" -ne "$ROOT_UID" ] # If current UID doesn't equal to 0 (Means the current user is not root)
then
echo “Must be root to run the script.” # Only root can run this script
exit $E_NOTROOT # Exit with specified signal
fi
if [ -n "$1" ] # If the first parameter $1 is not empty, then execute "then" command.
then
lines=$1 # The first parameter means the last lines you want to keep
else
lines=$LINES # Default lines you want to keep, if not specified on command-line
fi
cd $LOG_DIR || {
echo "Can't change to necessary directory." 2> /dev/null # If destination path doesn't exist, exit with specified signal
exit $E_XCD;
}
tail -n $lines messages > mesg.tmp # Save last section of messages log file
mv mesg.tmp messages # To keep as new log file
cat /dev/null > wtmp # Clean up logging information
exit 0 # A zero return means that the script is executed successfully
=======================================================================================================
5. If you want to execute a bash script, please test it by ./scriptname with user execution privilege.
6. Preliminary exercise:
A. Write a script that upon invocation shows the time and date, lists all logged-in users, and gives the system uptime. The script saves this information to a log file.
Answer:
#!/bin/bash
echo "Today is `/bin/date`.”
echo "`/usr/bin/who | awk '{ print $1 }' | sort | uniq | xargs | tr " " ","` are logging.” # Get root,alex result. As xargs can re-arrange the result delimited by blank, we can use "tr" command to replace the blank with comma. And if we don't use "sort" command, "uniq" command doesn't make sense."uniq" command only works after the results get sorted.
if [ `uptime | awk '{ print $4 }' | cut -c1-3` == "min" ] # If min parameter exists, the result is minute. Otherwise, it is day.
then
echo "The system has run `/usr/bin/uptime | awk '{ print $3 }'` minutes."
else
echo "The system has run `/usr/bin/uptime | awk '{ print $3 }'` days."
fi
7. In vi / vim editor, try "esc" button and ":nohl" to cancel highlight.
8. In /etc/vimrc, add "syntax on" to highlight syntax.
9. # is used for comments. Lines beginning with a # (with the exception of #!) are comments and will not be executed. One # will not end until you use a new line. That means if you want to use a new command, please don't use the same line as the line of comments.
But the standard quoting and escape characters (“ ' \) escape the #.
#!/bin/bash
echo 'The # here doesn’t begin a comment.'
echo The \# here doesn’t begin a comment.
echo “The # here doesn’t begin a comment."
10. “;”semicolon, permits putting two or more commands on the same line.
echo "File $filename exists." ; cp $filename $filename.bak # The first command runs and then the second runs accordingly.
“;”is also used for case option. (double semicolon)
#!/bin/bash
case “$var” in
abc) echo “\$var = abc” ;;
xyz) echo “\var = xyz” ;;
esac
11. #!/bin/bash
if [ -x “$filename” ] ; then # If $filename can be executed, the result is true. That means "then" command will be executed accordingly.
12. "dot" command is equivalent to source which is a bash builtin.
A. When working with filenames, a leading dot is the prefix of a "hidden" file, a file that an ls will not normally show. (ls -al can show.)
B. When considering directory names, a single dot represents the current working directory, and two dots denote the parent directory. The dot often appears as the destination directory of a file movement command (sometimes means current directory.)
For instance:
cp /home/alex/junk/* . # Copy specified files to current directory ($PWD)
C. "dot" character matches a single character. This function is used in regular expression.
13. Comma operator links together a series of arithmetic operations. All are evaluated, but only the last one is returned.
For example,
#!/bin/bash
let "t2 = ((a=9, 15/3))"
echo $t2
# Set "a=9" and "t2 = 15 / 3”
For another instance,
#!/bin/bash
for file in /{,usr/}bin/*calc
# Find all files ending in "calc" in /bin and /usr/bin directories.
14. escape [backslash] \ , a quoting mechanism for single characters.
\X escapes the character X. The \ may be used to quote "and ', so they are expressed literally.
15. / , filename path separator like /home/alex/projects. This is also the division arithmetic operator.
16. ` backquotes , the command in the backquotes will be executed firstly.
For instance,
echo `expr 4 + 5`
17. : , this symbol is named as null command [colon], equivalent of a "NOP"(no op, do-nothing operation). It is considered as "true". Itself is a bash builtin and its exit status is true (0)
#!/bin/bash
:
echo $? # This is to get the exit status of last command. If the last command runs successfully, the result is 0. Otherwise, the result will be from 1 to 255.
Another example:
#!/bin/bash
while :
do
echo $PWD
done
# Same as
# while true
# do
# echo $PWD
# done
18. [root@test scripts]# ls
1 2 3 4 5 6 checkups
[root@test scripts]# rm -rf [1-6]
[root@test scripts]# ls
checkups
19. #!/bin/bash
VAR=2
if [ $VAR = 1 ]
then : # Do nothing and branch ahead.
else
echo "Test failed."
fi
20. #!/bin/bash
: > /tmp/test # Empty /tmp/test file. However, this doesn’t fork a new process as “:” is a builtin.
21. Sometimes “:” serves as a field separator, like in /etc/passwd and in the $PATH variable.
[root@test scripts]# echo $PATH
/usr/lib64/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/var/cfengine/bin:/root/bin
22. “!” [reverse or negate]
“!=“ means not equal
23. “*” [asterisk] serves a “wild card” for filename expansion in globbing. By itself, it matches every filename in a given directory.
[root@test scripts]# echo *
checkups test
Also, it represents any number (zero) characters in a regular expression.
24. A double asterisk serves as arithmetic operator to represent exponent operator or extended file-match blobbing.
25. “?” serves as test operator
#!/bin/bash
(( var0 = var1<98?9:21 ))
If var1 is less than 98, then var0 equals to 9.
If var1 is great or equals 98, then var0 equals to 21.
26. “?” serves as wild card, as a single-character for filename expansion in globbing as well as extended regular expression.
27. “$” serves as variable substitution
var1=5
var2=23abc
echo $var1 # 5
echo $var2 # 23abc
28. “$” serves end-of-line in regular expression, meaning the end of a line in test.
28. “${}” serves as parameter substitution.
29. “$'…'” This construct expands single or multiple escaped octal or hex values in to ASCII or Unicode characters.
30. “$*,$@,$#,$0,$?”
$@ = $*
They show all of the parameters. The parameters are in their original positions.
[root@test scripts]# cat test
#!/bin/bash
for var in $*
do
echo $var
done
[root@test scripts]# ./test 1 2 3
1
2
3
[root@test scripts]# cat test
#!/bin/bash
for var in $@
do
echo $var
done
[root@test scripts]# ./test 1 2 3
1
2
3
For “$*”, the results are like “$1 $2 $3”
[root@test scripts]# cat test
#!/bin/bash
for var in "$*"
do
echo $var
done
[root@test scripts]# ./test 1 2 3
1 2 3
For “$@“, the results are like “$1" "$2" "$3" "$4”
[root@test scripts]# cat test
#!/bin/bash
for var in "$@"
do
echo $var
done
[root@test scripts]# ./test 1 2 "3 4"
1
2
3 4
$0 means bash file name.
$? the exit status of last command.
$# print the numbers of the arguments
31. $$ holds the process ID of the script in which it appears.
32. () command group, it starts a subshell. The parent process, the script, can’t read variables created in the child process, the subshell.
{} A comma may act upon a comma-separated list of file specs within braces. No spaces allowed within the braces unless the spaces are quoted or escaped.
echo {file1,file2}\ :{\ A,” B”,’ C’}
file1 : A file1 : B file1 : C file2 : A file2 : B file2 : C
33. echo {a..c} # a b c
echo {1..3} # 1 2 3
34. {} means block of code.
function echovar
{
echo $var1
echo $var2
}
echovar
35. For example 1
[root@test scripts]# vim test
#!/bin/bash
SUCCESS=0
E_NOARGS=65
if [ -z "$1" ] # If "$1" is empty
then
echo "Usage: `basename $0` rpm-file” # Get the full script name, no need path.
exit $E_NOARGS
fi
{
echo
echo "Archive Description:"
rpm -qpi $1 # Query description.
echo
echo "Archive Listing:"
rpm -qpl $1 # Query Listing.
echo
rpm -i --test $1 # Query whether rpm file can be installed.
if [ "$?" -eq $SUCCESS ]
then
echo "$1 can be installed."
else
echo "$1 can't be installed."
fi
echo # End code block.
} > "$1.test" # Redirects output of everything in block to file.
echo "Results of rpm test in file $1.test"
exit 0
36. {}\; mostly used in find constructs but not a shell builtin.
find /var/log -name messages -exec tail -100 '{}' \;
37.[] test.
[[]] test. Used more flexible.
38.[] array element.
Array[1]]slot_1
echo ${Array[1]}
39. $[…] integer expansion.
a=3
b=7
echo $[$a+$b] # 10
echo $[$a*$b] # 21
40. (()) integer expansion.
equals to $[…]
41.
script > filename # Redirects the output of script to the file filename. overwrite if it already exists.
command &> filename # Redirects both the stdout and stderr of command to filename.
command &> /dev/null # Redirects stdout and stderr to black hole.
command >&2 # Redirects stdout of command to stderr.
script >> filename # Appends the output of script to filename. If filename doesn’t exist, it is created.
42. [i]<>filename # Opens filename for reading and writing and assigns file descriptor i to it. If filename doesn’t exist, it is created.
exec 3<> filename # Give file descriptor to filename. If filename doesn’t exist, it is created.
read -n 4 <&3 # Open file descriptor and read the first four characters.
echo -n . >&3 # Replace the fifth character with .
exec 3>&- # Close file desciptior
43. \<, \> word boundary
[root@test scripts]# cat test
the
I am the hero
atheb
[root@test scripts]# grep "\" test
the
I am the hero
44. “|” pipe passes the output (stdout) of a previous command to the input (stdin) of the next one, or to the shell. Pipe runs a child process, and therefore can’t alter script variables.
45. “||”
cd /tmp/test || echo “Test failed” # If cd /tmp/test failed, then echo Test failed.
46. “&” run job in background.
[root@test scripts]# sleep 10 &
[1] 27820
47. “&&” AND logical operator. If the first command runs ok, then the next command will be executed.
cd /tmp/test && echo “Test ok.”
48. cat - >> test
If you use the above command, you can input some characters and then input ctrl+d to end the command. File test will contain the inputs.
tar -cf - * | gzip -c > abc.gz # tar and gzip are working simultaneously. tar all of the files and gzip them into a new file named abc.gz
Something needs to be mentioned. The above command is using tar and gzip simultaneously but not using tar firstly and then gzip. It is better for the first one for it can reduce space as using tar firstly will occupy more disk space.
49. Example:
#!/bin/bash
BACKUPFILE=backup-$(date +%m-%d-%Y)
archive=${1:-$BACKUPFILE}
find . -mtime 1 -type f -exec tar rvf "$archive.tar" '{}' \;
${file:-my.file.txt} :If $file is not set or empty, then use my.file.txt.(If $file is set or not empty, it will not be executed.)
50. ls . | xargs -i -t cp ./{} $1
List all of the files and copy all of them to $1 (Used in bash script)
-t print firstly and then execute
-i let xargs deal with the files listed by ls
./{} means the files listed by ls
$1 means the first parameter
51. - has two meanings.
A. Previous working directory like cd -
B. Minus An arithmetic operation
52. = Equals Assignment operator
53. + Plus Arithmetic operator or regular expression operator
Also, + means to enable certain options and - to disable them.
54. % Modulo arithmetic operation
let “z = 5 % 3”
echo $z # 2
55. ~ home directory like cd ~alex
56. ^ beginning-of-line in a regular expression, a “^” addresses the beginning of a line of text.
57. Control Characters
ctrl - a Moves cursor to beginning of line of text (on the command line)
ctrl - c break
ctrl - d logout from a shell
58. EOF (end-of-file). Also terminates input from stdin.
ctrl - e Move cursor to end of line of text (on the command line)
ctrl - l clean screen
ctrl - r search in history buffer
ctrl - u erase a line of output
ctrl - z pauses a foreground job
59. Whitespace are including spaces / tabs / blank lines or any combination thereof. In some contexts, such as variable assignment, whitespace is not permitted and resulted in a syntax error.
60. $IFS used as separating fields of input to certain commands. It defaults to whitespace.
61. $var equals to ${var}. When the previous format doesn’t work, try the later one.
62. hello=“A B C D”
echo $hello # A B C D
echo “$hello” # A B C D
echo ‘$hello’ # $hello
Quoting a variable preserves whitespace.
63. unset var # unset a variable
64.
echo “$uninitialized”
let “uninitialized +=5”
echo “$uninitialized” # 5
An uninitialized variable has no value however it evaluates as 0 in an arithmetic operation.
65. If = is used as assignment operator, no space is before and after. Like a=879
66.
a=2335
b=${a/23/BB}
echo $b # BB35
67. b=BB35
let “b += 1”
echo $b # 1
Bash sets the “integer value” of a string to 0.
68. $0 is the name of the script itself, $1 is the first argument, $2 is the second and so on. After $9, the arguments must be enclosed in brackets like ${10} , ${11}.
69. if [ -n “$1” ] # The length of $1 is nonzero
if [ -z “$1” ] # The length of $1 is zero
70. ${!#} print the last argument
71. shift [n]
The positional parameters from n+1 ... are renamed to $1 ....
Parameters represented by the numbers $# down to $#-n+1 are
unset. n must be a non-negative number less than or equal to
$#. If n is 0, no parameters are changed. If n is not given,
it is assumed to be 1. If n is greater than $#, the positional
parameters are not changed. The return status is greater than
zero if n is greater than $# or less than zero; otherwise 0.
#!/bin/bash
# shift-past.sh
shift 3
echo “$1”
sh shift-past.sh 1 2 3 4 5
4
72. ls -l [Vv]* -> works
ls -l '[Vv]*’ -> doesn’t work
73. Escaped characters (used with echo and sed)
\n new line
\r return
\t tab
\v vertical tab
\b backspace
\0xx octal ASCII equivalent of 0nn, nn is a string of digits
74. echo “This will print \
as one line.” # This will print as one line.
75. echo -e “\v\v\v\v” # print 4 vertical tabs
echo -e to print escaped characters
76.