Linux Practical Operations - Shell Programming

The answer is tomorrow, every day tomorrow

What is Shell

Shell is a command line interpreter that provides users with an interface system-level program that sends requests to the Linux kernel to run programs. Users can use Shell to start, suspend, stop, and even write some programs.

Similar to COMMAND.COM and later cmd.exe under DOS . It receives user commands and then invokes the corresponding application.

The user writes an instruction, which cannot be directly sent to the Linux kernel for execution, but is executed by the shell for us, and the result is returned to us through the shell after execution.

There are more than one shell in Linux, the one we use is bash .

You can send a command directly to the shell, or write the command in a file/script ( .sh shell script ).

Shell programming is to write instructions in shell scripts .

Shell script

format requirement

脚本以 #!/bin/bash 开头 ---> 确定shell的类型
脚本需要有可执行权限
shell脚本文件以.sh结尾,也可以不以.sh结尾

Write your first shell script

Requirements Description: Create a Shell script to output hello world!

创建一个目录:mkdir /root/shcode
cd /root/shcode
vim hello.sh
写入:
    #!/bin/bash
    echo "hello,world!"

Implementation modalities

方式 1:
    首先要给shell脚本加x执行权限:chomod u+x hello.sh
    再输入该脚本的相对路径或绝对路径来执行该脚本
    比如:
         使用相对路径:    ./hello.sh 
         使用绝对路径:    /root/shcode/hello.sh

方式 2:
    不用赋予脚本 +x 权限,直接执行即可。(使用以下指令,即使没有执行权限也可以执行)
    使用指令: sh  shell脚本/shell脚本的绝对路径
    比如    sh hello.sh 

shell variables

The variables in the Linux Shell are divided into: system variables and user-defined variables.

system variable

System variables such as: $HOME, $PWD, $SHELL, $USER, etc.

All system variables in the shell can be displayed through the set command.

custom variable

basic grammar

(1) 定义变量:变量名=值  --->不加空格
(2) 撤销变量:unset 变量名
(3) 声明静态变量:readonly 变量 (改变量不能 unset撤销)

the case

案例 1:定义变量 A
案例 2:撤销变量 A
案例 3:声明静态的变量 B=2,不能 unset
#案例 1:定义变量 A=100  (#为注释符)
A=100
#输出变量需要加上$ ($--->引用变量)
echo $A

#上述输出结果是100,想要输出结果为A=100,这样写(A=以普通文本形式输出,$A引用变量的值)
echo A=$A 或者 echo "A=$A" 


#案例 2:撤销变量 A 
unset A
echo "A=$A"    (--->输出 A= )


#案例 3:声明静态的变量 B=2,不能 unset 
readonly B=2
echo "B=$B" 

Rules for defining shell variable names

(1) 变量名称可以由字母、数字和下划线组成,但是不能以数字开头。5A=200(×)
(2) 等号两侧不能有空格
(3) 变量名称一般习惯为大写,这是一个规范,我们遵守即可

Assign the command's return value to a variable

(1) A=`date`反引号,运行里面的命令,并把结果返回给变量 A 
(2) A=$(date) 等价于反引号

Set environment variables (global variables)

Variables can be promoted to global environment variables for common use by multiple shell programs.

basic grammar

(1) export     变量名=变量值     
(功能描述:将 shell 变量输出为环境变量/全局变量)

(2) source     配置文件            
(功能描述:在某文件中定义环境变量之后,要对该文件进行刷新才能使其生效,即让修改后的配置信息立即生效)

(3) echo     $变量名            
(功能描述:查询环境变量的值)

Define the TOMCAT_HOME environment variable in the /etc/profile file

vim /etc/profile
写入:export TOMCAT_HOME=/opt/tomcat
    
source /etc/profile
echo $TOMCAT_HOME --- 输出 /opt/tomcat

note

单行注释:#
多行注释:   
:<<!   独占一行    
内容 
!      独占一行

positional parameter variable

When we execute a shell script, if we want to get the parameter information of the command line, we can use the position parameter variable.

basic grammar

$n (功能描述:n 为数字,$0 代表命令本身(如./myshell.sh),$1-$9 代表第一到第九个参数(如:$1 就是100 $2 就是200),十以上的参数需要用大括号包含,如${10})
$* (功能描述:这个变量代表命令行中所有的参数,$*把所有的参数看成一个整体)
$@ (功能描述:这个变量也代表命令行中所有的参数,不过$@把每个参数区分对待)
$# (功能描述:这个变量代表命令行中所有参数的个数)

Case: Write a shell script myshell.sh, and obtain the parameter information of the command line in the script.

vim myshell.sh

    写入:
        #!/bin/bash
        echo "命令本身=$0 第一个参数=$1 第二个参数=$2"
        echo "所有的参数=$*"
        echo "$@"
        echo "参数个数=$#"
   保存退出
        
sh myshell.sh 100 200

predefined variable

Predefined variables are variables that have been defined in advance by the shell designer and can be used directly in shell scripts.

basic grammar

(1) $$ (功能描述:当前进程的进程号(PID))
(2) $! (功能描述:后台运行的最后一个进程的进程号(PID))
(3) $?(功能描述:最后一次执行的命令的返回状态。如果这个变量的值为 0,证明上一个命令正确执行;如果这个变量的值为非 0(具体是哪个数,由命令自己来决定),则证明上一个命令执行不正确了。)

Applications

vim preVar.sh

    写入:
    #!/bin/bash
    echo "当前执行的进程 id=$$"
    #以后台的方式运行一个脚本(在脚本后加一个$),并获取他的进程号
    /root/shcode/myshell.sh &
    echo "最后一个后台方式运行的进程 id=$!" 
    echo "执行的结果是=$?"
    保存并退出
    
sh preVar.sh

operator

basic grammar

三种写法:
$((运算式))
$[运算式]
expr m + n     (expression 表达式)

注意 expr 运算符间要有空格
如果希望将 expr 的结果赋给某个变量,使用 `` 或者 $( )
expr \*, /, %    乘,除,取余

Applications

Case 1: Calculate the value of (2+3)X4

Case 2: Request the sum of the two parameters [integer] of the command line 20 50

vim oper.sh
    写入:
    #!/bin/bash
    #案例 1:计算(2+3)X4 的值
    #使用第一种方式
    RES1=$(((2+3)*4))        --->用一个变量RES1接收
    echo "res1=$RES1"
    保存并退出
sh oper.sh

vim oper.sh
    写入:
    #!/bin/bash
    #使用第二种方式, 推荐使用
    RES2=$[(2+3)*4]
    echo "res2=$RES2"
    保存并退出
sh oper.sh    

vim oper.sh
    写入:
    #!/bin/bash    
    #使用第三种方式 expr 
    TEMP=`expr 2 + 3`       
    RES4=`expr $TEMP \* 4` 
    echo "temp=$TEMP"
    echo "res4=$RES4"
    保存并退出
sh oper.sh

vim oper.sh
    写入:
    #!/bin/bash    
    #案例 2:请求出命令行的两个参数[整数]的和 20 50 
    SUM=$[$1+$2]
    echo "sum=$SUM"
    保存并退出
sh oper.sh 20 50

conditional judgment

basic grammar

[ condition ] (注意 condition 前后要有空格)
#非空返回 true,可使用$?验证(0 为 true,>1 为 false)

Common Judgment Conditions

(1) = 字符串比较
(2)    两个整数的比较
    -lt 小于     less than
    -le 小于等于  less equal
    -eq 等于      equal
    -gt 大于      greater
    -ge 大于等于   greater equal
    -ne 不等于     not equal
(3)    按照文件权限进行判断
    -r 有读的权限
    -w 有写的权限
    -x 有执行的权限
(4)    按照文件类型进行判断
    -f 文件存在并且是一个常规的文件
    -e 文件存在
    -d 文件存在并是一个目录

Applications

案例 1:"ok"是否等于"ok"
判断语句:使用 =
案例 2:23 是否大于等于 22
判断语句:使用 -ge
案例 3:/root/shcode/aaa.txt 目录中的文件是否存在
判断语句: 使用 -f

代码如下:
vim ifdemo.sh
    #!/bin/bash
    #案例 1:"ok"是否等于"ok"
    if [ "ok" = "ok"  ]
    then
            echo "equal"
    fi                    -----> if语句 以if开头 以fi结尾
    
    #案例 2:23 是否大于等于 22
    #判断语句:使用 -ge
    if [ 23 -ge 22 ]
    then
            echo "大于"
    fi
    
    #案例 3:/root/shcode/aaa.txt 目录中的文件是否存在
    #判断语句: 使用 -f
    if [ -f  /root/shcode/aaa.txt ]
    then
            echo "文件存在"
    fi
    
    #看几个案例
    if [ ]
    then
            echo "存在"
    fi
    
    if [ hspEdu01 ]
    then
            echo "hello hspEdu01"
    fi
sh ifdemo.sh

输出结果:
    equal
    大于
    hello hspEdu01

process control

if statement

basic grammar

if [ 条件判断式 ] 
then
    代码
fi

或者 多分支

if [ 条件判断式 ] 
then
    代码
elif [条件判断式] 
then
    代码
fi

Note: [Conditional Judgment], there must be a space between the square brackets and the conditional judgment.

Applications

Write a shell program, if the input parameter is greater than or equal to 60, it will output "passed", if it is less than 60, it will output "failed"

if [ $1 -ge 60 ]
then
    echo "及格了"
else
    echo "不及格"
fi

或者
if [ $1 -ge 60 ]
then
    echo "及格了"
elif[ $1 -lt 60]
then
    echo "不及格"
fi

case statement

basic grammar

case $变量名 in
"值 1")
如果变量的值等于值 1,则执行程序 1
;;
"值 2")
如果变量的值等于值 2,则执行程序 2
;;
…省略其他分支…

*)
如果变量的值都不是以上的值,则执行此程序
;;
esac

Applications

When the command line parameter is 1, output "Monday", when it is 2, output "Tuesday", otherwise output "other"

#!/bin/bash
case $1 in
"1")
echo "周一"
;;
"2")
echo "周二"
;;
*)
echo "other..."
;;
esac
    
sh testCase.sh 1
周一

for loop

basic grammar

第一种方式:
for 变量 in  值 1  值 2  值 3… 
do
程序/代码
done

第二种方式:
for (( 初始值;循环控制条件;变量变化 ))
do
程序/代码
done

Applications

案例:打印命令行输入的参数 [这里可以看出$*  和 $@ 的区别]
    #!/bin/bash
    #案例:打印命令行输入的参数 [这里可以看出$*  和 $@ 的区别]
    #注意:$* 是把输入的参数当作一个整体,所以只会输出一句话
    for i in "$*"
    do
            echo "num is $*"
    done
    
    #使用 $@ 来获取输入的参数,注意:也是把输入的参数看作一个整体,但这是分别对待;所以有几个参数就输出几句
    echo "======================================"
    for j in "$@"
    do
            echo "num is $@"
    done

sh testFor1.sh 100 200 300
num is 100 200 300
======================================
num is 100 200 300
num is 100 200 300
num is 100 200 300

应用实例 testFor2.sh
案例:从 1 加到 100 的值输出显示
    #!/bin/bash
    #案例:从 1 加到 100 的值输出显示
    #定义一个变量SUM
    SUM=0
    for(( i=1; i<=100; i++  ))
    do
            SUM=$[$SUM+$i]
    done
    echo "总和SUM=$SUM"

sh testFor2.sh 
总和SUM=5050

如果1加到x x由自己输入
    SUM=0
    for(( i=1; i<=$1; i++  ))
    do
            SUM=$[$SUM+$i]
    done
    echo "总和SUM=$SUM"

sh textFor2.sh 1000
总和SUM=500500

while loop

basic grammar

while [ 条件判断式 ]
do
程序/代码
done

Note: while and [ have spaces, conditional judgment expressions and [ ] also have spaces

Applications

案例:从命令行输入一个数 n,统计从 1+..+ n  的值是多少?
    #!/bin/bash
    SUM=0
    i=0
    while [ $i -le $1 ] 
    do
    SUM=$[$SUM+$i]
    #i 自增
    i=$[$i+1]
    done
    echo "执行结果=$SUM"

sh testWhile.sh 100
执行结果=5050

read read console input

basic grammar

read(选项)(参数)
选项:
    -p:指定读取值时的提示符;
    -t:指定读取值时等待的时间(秒),如果没有在指定的时间内输入,就不再等待了
参数:
    变量:指定读取值的变量名

Applications

案例 1:读取控制台输入一个 NUM1 值
案例 2:读取控制台输入一个 NUM2 值,在 10 秒内输入。代码:

#!/bin/bash
#案例 1:读取控制台输入一个 NUM1 值
read -p "请输入一个数 NUM1=" NUM1 
echo "你输入的 NUM1=$NUM1"

#案例 2:读取控制台输入一个 NUM2 值,在 10 秒内输入。
read -t 10 -p "请输入一个数 NUM2=" NUM2 
echo "你输入的 NUM2=$NUM2"

sh testRead.sh
请输入一个数 NUM1=100
你输入的 NUM1=100

function

system function

basename

功能:返回完整路径最后 / 的部分,常用于获取文件名
basename [pathname] [suffix]
basename [string] [suffix]    

功能描述:basename 命令会删掉所有的前缀包括最后一个(‘/’)字符,然后将字符串显示出来。
选项:suffix 为后缀,如果 suffix 被指定了,basename 会将 pathname 或 string 中的 suffix 去掉。

案例 1:请返回 /home/aaa/test.txt 的 "test.txt" 部分
basename /home/aaa/test.txt
返回test.txt

如果输入:basename /home/aaa/test.txt .txt
返回test

dirname

功能:返回完整路径最后 / 的前面的部分,常用于返回路径部分
dirname 文件绝对路径 

功能描述:从给定的包含绝对路径的文件名中去除文件名(非目录的部分),然后返回剩下的路径(目录的部分)

案例 1:请返回 /home/aaa/test.txt 的 /home/aaa 
dirname /home/aaa/test.txt
返回/home/aaa

custom function

basic grammar

[ function ] funname[()]
{
    Action; 
    [return int;]
}

调用直接写函数名:funname    [值]

the case

Calculate the sum of the input two parameters (dynamic acquisition)

#!/bin/bash
#定义函数 getSum 
function getSum() {
    SUM=$[$n1+$n2] 
    echo "和是=$SUM"
}

#输入两个值
read -p "请输入一个数 n1=" n1 
read -p "请输入一个数 n2=" n2

#调用自定义函数
getSum $n1 $n2


sh testFun.sh 
请输入一个数 n1=10
请输入一个数 n2=90
和是=100

Regularly back up the database

the case

(1) 每天凌晨 2:30 备份 数据库 hspedu 到 /data/backup/db
(2) 备份开始和备份结束能够给出相应的提示信息
(3) 备份后的文件要求以备份时间为文件名,并打包成 .tar.gz 的形式,比如:2021-03-12_230201.tar.gz
(4) 在备份的同时,检查是否有 10 天前备份的数据库文件,如果有就将其删除。
(5) 画一个思路分析图

the code

切换到/usr/sbin/目录下(该目录为root用户执行权限,使用root执行)
vim mysql_db.backup.sh
写入:
    #备份目录
    BACKUP=/data/backup/db
    
    #当前时间
    DATETIME=$(date +%Y-%m-%d_%H%M%S)
    echo $DATETIME
    
    #数据库的地址
    HOST=localhost
    
    #数据库用户名
    DB_USER=root
    
    #数据库密码
    DB_PW=hspedu100
    
    #备份的数据库名
    DATABASE=hspedu

    #创建备份目录, 如果不存在,就创建(这个应该可以用if语句写)
    [ ! -d "${BACKUP}/${DATETIME}" ] && mkdir -p "${BACKUP}/${DATETIME}"

    #备份数据库
    mysqldump    -u${DB_USER}    -p${DB_PW}    --host=${HOST}    -q    -R    --databases    ${DATABASE}    | gzip > ${BACKUP}/${DATETIME}/$DATETIME.sql.gz


    #将文件处理成 tar.gz 
    cd ${BACKUP}
    tar -zcvf $DATETIME.tar.gz ${DATETIME}
    
    #删除对应的备份目录
    rm -rf ${BACKUP}/${DATETIME}

    #删除 10 天前的备份文件
    #查找BACKUP目录下10天前的备份文件 备份文件名字为 *.tar.gz 如果有删除
    find ${BACKUP} -atime +10 -name "*.tar.gz" -exec rm -rf {} \;
    echo "备份数据库${DATABASE} 成功~"

    保存并退出
    
sh /user/sbin/mysql_db.backup.sh

定时:
    crontab -e
    30 2 * * * /user/sbin/mysql_db.backup.sh
    保存并退出

Guess you like

Origin blog.csdn.net/2301_76354366/article/details/129074242