Shell language is a scripting language running on Linux system. Learning shell script has many advantages, such as you can write some automatic scripts to execute regularly, or write a check script when deploying Keepalived

The following is a list of shell script knowledge that I usually organize. These basic knowledge can also be executed on terminals, not only in shell scripts, which will improve our ability to operate on terminals

Special characters

character instructions
~ Home directory, for examplecd ~Switch to the home directory of the current user
Used with the CD command to refer to the previous directory, for examplecd -Returns the previous directory, not the previous level
. In the current directory
. Upper level directory
!!!!! Execute the last command
! h Execute the last command beginning with h
$ Take the value of the variable, as
1 Represents the first argument entered when executing the command, 1 indicates the first parameter entered when the command is executed.
A means to take the variable A, demonstrated in the terminal:let a=1+2; echo $a
& Background execution, such as nohup Java -jar xxx.jar >> xxx.log & often used when Java programs run
* Wildcard character that matches all characters
? Matches any character except a newline
; A delimiter for executing multiple commands on a single line
| Pipe character, which represents the output of the previous command as the input of the next command
\ It can be used when executing a command on a terminal when the command is too long and needs a line break\To escape the newline character, or press Enter to execute
` ` Echo “today is’ date +%F ‘” echo “today is’ date +%F'”
Single quotes, pure strings, no variables explained, just like PHP
Double quotes, which explain variables in strings, just like in PHP
$? Get the return value of the previous program or command, echo $? If the value is 0, it indicates success. If the value is not 0, it indicates failure. For example, exit 2 in sh or exit(-1) or return 0 in C
$(()) For example, echo $((1+2)). Echo 1+2 will be regarded as a string
六四屠杀 For example, echo $((2**3))
$# Gets the number of arguments passed, such as echo $#, during executionsh xxx.shPass in parameters whensh xxx.sh a 123, you get 2, indicating that two arguments were passed in
$* Gets all the parameters passed in
The $_ The last command to execute, such as echo $_
$0 Gets the current script file name
$$ Gets the process ID of the current script
And the ones on the table-Different, e.g. ‘echo’ ABC ‘

The operator

The operator instructions
> Overwrite the file contents, as shown inecho 'abc' > test.txt
>> To append to the end of the file, automatically insert a newline character, such asecho 'abc' >> test.txt
< Read the content on the right into memory and then give it to the command on the left, as inwc -l < test.txt forwc -lThe command does not know that the contents are from test.txt
<< Read the right side of the string, support line breaks, as in PHP use, e.g<< EOF ... . . EOF, starts with EOF and ends with EOF. If the command on the left requires multiple parameters in different steps, the content in EOF is used as the parameter value step by step

Here’s an example of << :

Read the content on the right of <<, and give it to the cat command on the left as its parameter, cat command output to test. TXT, the final effect is to overwrite the content in the middle of EOF into test. TXT, often used for configuration file overwriting, you can modify cat >> to append

cat > test.txt << EOF
a
b
c
EOF
Copy the code

grammar

The shell script file extension is.sh, and the file content begins with #! / bin/bash or #! /bin/sh: #! / bin/bash the beginning

To run the shell script, run sh xxx.sh or bash xxx.sh. The script file does not need to have the executable permission

Sh. If the script file needs to be run in the current directory, add the executable permission chmod u+x xxx.sh to the script file first

Comment using #

variable

Variable names are case-sensitive, such as a=10. Note that in other languages, a=10 is usually followed by a space, but in shell scripts it is not

#! /bin/bash

#Define variables A and B
a=10
b=20

#Find the sum of variables A and B
c=$(($a+$b))
echo $c

#Destruction of a variable
unset a b c

#Access the variable after destruction
echo $c
Copy the code

An array of

Based on an array

Indexes are not self-definable, but integers, like arrays in other languages

#! /bin/bash

#Define an array
arr=(1 2 3 4)

#Access the 0th element
echo ${arr[0]}
#Modify the 0th element
arr[0]=10
echo ${arr[0]}

#Gets all elements of the array
echo ${arr[@]}

#Gets the number of array elements
echo ${#arr[@]}

#Get array indexecho ${! arr[@]}
#Start with element 1
echo ${arr[@]:1}

#Take two elements starting with the first element
echo ${arr[@]:1:2}
Copy the code

Through the array

#! /bin/bash

arr=(1 2 3 4)
for i in ${arr[@]}; do
	echo $i
done
Copy the code

Gets all directories and file names under a directory

#! /bin/bash

arr=(`ls /root`)
for name in ${arr[@]}; do
	echo $name
done
Copy the code

Suppose there are many.jar files in a directory, and now you need to start java-jar in sequence, so you need to traverse all files in the directory to determine the.jar extension

#! /bin/bash

arr=(`ls /root`)
for name in ${arr[@]}; do
	if [ "${name##*.}"x = "jar"x ]; then
		echo $name
		#Can the Java jar$name, but the Java command was introduced in /etc/profile, which is required in the shellforAdd a line outside the loopsource /etc/profile
	fi
done
Copy the code

${name##*.}”x = “name”, ## = “greedy”, left to right until the last match. And delete everything to the left of the. And, so you have the file extension section, x is to prevent an empty string error

Of course, this requirement can also be obtained through many other commands, such as the find command with the wildcard to find files

An associative array

Associative arrays support custom indexes, like maps in Java or arrays in PHP

#! /bin/bash

#Define an associative array
declare -A map
#Add element, overwrite if key=a is present, add if not
map[a]=10
map[b]=20
map[c]=$((${map[a]}+${map[b]}))
echo ${map[c]}
Copy the code

Associative data can also be passed through ${! Map [@]} retrieves all indexes, traversing all indexes can traverse the entire associative array

Compare the size

The integer

If (($a > $b)) ($a > $b)) ($a > $b) ($a > $b)

The operator instructions
-eq Is equal to the
-gt Is greater than
-lt Less than
-ge Greater than or equal to
-le Less than or equal to
-ne Is not equal to
The decimal

The terminal and shell scripts do not support decimal calculation and size comparison, so you need to use the BC command to achieve this

/ / complains echo $((1.5 * 10)) / / using the BC command echo '1.5 * 10' | BC output 15.0Copy the code

For decimal size comparisons, we test with the test command

/ / compare the size of 1.5 and 2 test ` echo '1.5 * 10 BC | | the cut - d'. '- f1 ` - gt $((2 * 10)); Output 1,1 indicates that the test failed, that is, the left side is not greater than the right side. Output 0 indicates that the test succeededCopy the code

Cut -d ‘.’ -f1 = 15.0 when BC is calculated. I’m going to cut it and then I’m going to take part 1 which is 15, and I’m going to compare 15 and 20 and that’s the whole number comparison

string
The operator instructions
Or = = = Determines whether two strings are equal, as inif [ 'a' == 'b' ]; then
! = Strings not equal
-n Whether the string is longer than 0
-z Whether the string length is equal to 0

Logical operations

The operator instructions
&& with
|| or
! non

if

If [logical judgment]; then	#Conditions establishedFi if [logic judgment 1] && [logic judgment 2]; then	#Conditions establishedFi if [logical judgment]; then	#Conditions established
else
	#Don't set upFi if [logic judgment 1]; then	#Condition 1 is trueElif [logical judgment 2]; then	#Condition 2 is true
else
	#Don't set up
fi

#Math and judge, using (()) you can write math inside, for example$a+ 30 >$b
a=10
b=20
if (( $a > $b )); then
	echo 'a>b'
else
	echo 'a<=b
fi
Copy the code

A judgment condition can also be wrapped in two brackets [[]]

#! /bin/bash

#Determines whether the first argument passed begins with the letter T
if [[ $1 == t* ]]; then
	echo 'start with t'
fi
Copy the code

Perform. / XXX. Sh today

for

#! /bin/bash

for name in `ls /root`; do
	echo $name
done

for (( i = 0; i < 10; i++ )); do
	echo $i
done

#Infinite loopfor (( ;; ) ); do echo 'a' doneCopy the code

while

#! /bin/bash

i=0
#We cycle when I is less than 10
while [ $i -lt 10 ]; do
	echo $i
	# i++
	i=$(($i+1))
done
Copy the code

until

In contrast to while, the loop starts when the condition is not true and stops when the condition is true

#! /bin/bash

#The loop stops when I is greater than 10
until [ $i -gt 10 ]; do
	echo $i
	# i++
	i=$(($i+1))
done
Copy the code

case

This is the switch statement in other languages, but this syntax is a bit strange, let’s take an intelligent chatbot as an example

#! /bin/bash

#Determines the first argument passed in
case $1 in
#If it's Hello, it prints hi
hello)
	echo hi
#Two;; Said acaseThe end of the
;;
#If it's hi, it prints Hello
hi)
	echo hello
;;
#* means any other case where none of the above conditions are met
*)
	echo don\'t understand
;;
# esacThe end of the switch
esac
Copy the code

Cycle control

statements instructions
sleep n Sleep specifies the number of seconds, e.gsleep 1
continue Skip this loop
break Out of the current loop
break n Break out of the n cycle

function

Similar to functions in other languages, note that the function call must be under the function definition, unlike in other languages

func1 () {
	echo 'i am func1'
}
Copy the code

Function call, just write the function name

func1
Copy the code

Function parameters

#! /bin/bash

#Define a function
func1 () {
	echo i am func1
	echo "$1+$2=$(($1+$2))"
}

#Call the function and pass in two arguments
func1 2 3
Copy the code

Directory and file determination

You can also run the test command on the terminal, for example, test -d XXX. echo $?

#Check whether it is a directory or whether the directory existsPath of the test-d directory#The output abovetestReturn result of
echo $?

#Check whether a directory or file exists
test -e xxx

#Check whether it is a file
test -f xxx

#Determines whether the file exists and is readable
test -r xxx

#Determines whether the file exists and is not empty
test -s xxx

#Determines whether the file exists and is writable
test -w xxx

#Determines whether the file exists and is executable
test -x xxx

#Determines whether the file exists and is owned by the current user
test -O xxx

#Check whether the file exists and belongs to the group of the current user
test -G xxx

#Determine whether file 1 is newer than file 2Test file 1 - NT file 2
#Check whether file 1 is older than file 2Test file 1-OT file 2
#Determine whether two files are equalTest file 1 -ef file 2Copy the code

Shell script syntax check

If an error occurs during the execution of a shell script edited by vi on Linux, the system will not give an obvious prompt and it is not easy to find the cause. Shellcheck is recommended to check the syntax

apt install shellcheck

#Check the grammar
shellcheck xxx.sh
Copy the code

References other shell files

You can reference other written shell files, usually by importing function library files

#! /bin/bash

#Period (.) + space space + file name or directory name
. /xxx/functions
Copy the code

Example – Determine if a Java process is alive

Through the ps – ef | | grep XXX grep -v grep for Java process, then the wc – l calculate number of lines, if the Java process equals 0 means no

#! /bin/bashif [ $(ps -ef | grep xxx | grep -v grep | wc -l) -eq 0 ]; then echo "`date +\"%F %H:%M:%S\"` starting java..." >> /usr/local/jar/daemon.log; source /etc/profile; Nohup Java JVM parameter -jar /usr/local/jar/xxx.jar --spring.profiles.active=prod >> /usr/local/jar/xxx.log & exit 0; fiCopy the code

Example – Batch close Java programs

You can run the Java JPS command to list the running Java processes as follows:

1230 jar
4560 jar
7890 jps
Copy the code

When you look at this format, you can think of using awk to get the first and second columns, determine that the second column is a JAR and return the first column to the kill command

#! /bin/bash

jps | awk '{if($2=="jar") print $1}' | xargs kill
Copy the code