Linux-Shell编程

Linux Shell编程

Shell

shell是一个命令行解释器, 它为用户提供了一个向Linux内核发送请求以便运行程序的界面系统级程序,用户可以用Shell来启动,挂起,停止甚至编写程序

编写

格式要求

  1. 脚本以#!/bin/bash开头
  2. 脚本需要有可执行权限

执行方式

  1. 输入脚本的绝对路径或相对路径
    1. 首先要赋予脚本+x权限: chmod 744 myShell.sh
    2. 执行脚本
  2. sh + 脚本直接执行

Shell变量

介绍

  1. 分为两种:
    1. 系统变量: $HOME, $PWD, $SHELL, $USER
    2. 用户自定义变量
  2. 显示当前shell中所有变量: set
1
2
echo "PATH=$PATH"
echo "USER=$USER"

定义

语法

  1. 定义变量: 变量=值
  2. 撤销变量: unset 变量
  3. 声明静态变量: readonly 变量. 注意: 不能unset
1
2
3
4
5
6
7
8
9
#A=100
#echo "A=$A"
#unset A
#echo "A=$A"

readonly A=99
echo "A=$A"
unset A
echo "A=$A"

规则

  1. 变量名称可以由字母,数字和下划线组成,但是不能以数字开头
  2. 等号两侧不能有空格
  3. 变量名称一般习惯为大写
  4. 将命令的返回值赋给变量
    1. A=`ls -la` 反引号,运行里面的命令,并把结果赋值给变量A
    2. A=$(ls-la) 等价于反引号
  5. 注释
    1. 单行: #
    2. 多行: 以 :<<!开头,!结尾

设置环境变量

在/etc/profile文件中加入

1
2
TOMCAT_HOME=/opt/apache-tomcat-10.0.2
export TOMCAT_HOME

使用echo查看

注意要使用source /etc/profile重新加载

位置参数变量

当我们执行脚本时,如果希望获取到命令行的参数信息,就可以使用到位置参数变量

语法

选项 描述
$n n为数字,$0代表命令本身,$1-$9代表第1到9个参数,10以上的参数需要用大括号包含: ${10}
$* 代表命令行中所有的参数,$8把所有的参数看成一个整体
$@ 代表命令行中所有的参数,吧每个参数区分对待
$# 代表命令行中所有参数的个数

预定义变量

就是shell设计者事先定义好的变量,可直接在shell脚本中使用

语法

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

运算符

语法

  1. $((运算式))
  2. $[运算式](推荐)
  3. expr m + n
    1. 注意expr运算符间要有空格
  4. ```expr m - n ````
  5. expr \*,/,% 乘,除,取余

条件判断

语法

  • [ condition ]
  • 注意:condition前后要有空格
  • 非空返回true,可使用$?验证(0为true,>1为false)
  • 实例:
    • [ yiqing ] 返回true
    • [] 返回false
    • [ condition ] && OK || echo notok 条件满足执行后面的语句

常用判断条件

  1. 两个整数的比较
    1. = 字符串比较
    2. -lt 小于
    3. -le 小于等于
    4. -eq 等于
    5. -gt 大于
    6. -ge 大于等于
    7. -ne 不等于
  2. 按照文件权限进行判断
    1. -r 有读权限
    2. -w 有写权限
    3. -x 有执行权限
  3. 按照文件类型进行判断
    1. -f 文件存在且是一个常规的文件
    2. -e 文件存在
    3. -d 文件存在且是一个目录
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/bin/bash

#1.
if [ "ok" = "ok" ]
then
echo "equal"
fi

#2.
if [ 23 -gt 22 ]
then
echo "大于"
fi

#3: /root/shell/aaa.txt 目录中的文件是否存在
if [ -e /root/shell/aaa.txt ]
then
echo "存在"
fi

流程控制

if

语法

  1. if [ 条件判断式 ];then
            程序
    fi
    
    1
    2
    3
    4
    5
    6

    2. ```shell
    if [ 条件判断式 ]
    then
    程序
    elif [ 条件判断式 ]

注意

  1. [ 条件判断式 ], 中括号和条件判断式之间必须有空格
  2. if 和后面的中括号之间也要有空格
  3. 推荐第二种方式

示例

1
2
3
4
5
6
7
if [ $1 -ge 60 ]
then
echo "及格了"
elif [ $1 -lt 60 ]
then
echo "不及格"
fi

case

语法

1
2
3
4
5
6
7
8
9
10
11
12
case $变量名 in
"值1")
如果变量的值等于值1, 执行程序1
;;
"值2")
如果变量的值等于值2, 执行程序2
;;
...省略其他分支
*)
如果变量的值都不是以上的值, 执行此程序
;;
esac

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/bin/bash

# 参数是1,输出周一,是2,输出周二,其他情况输出other

case $1 in
"1")
echo "周一"
;;
"2")
echo "周二"
;;
*)
echo "other"
;;
esac

for

语法

  1. for 变量 in 值1 值2 值3...
        do
            程序
        done
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24

    1. 示例:

    ```shell
    #!/bin/bash
    及格了
    [root@VM-0-14-centos shell]# ./testIf.sh 61
    及格了
    [root@VM-0-14-centos shell]# ./testIf.sh 22
    不及格
    [root@VM-0-14-centos shell]# vim testIf.sh
    #!/bin/bash

    #打印命令行输入的参数
    #使用$*
    for i in "$*"
    do
    echo "the number is $i"
    done
    #使用$@
    for j in "$@"
    do
    echo "the number is $j"
    done
    2. 结果为:
    1
    2
    3
    4
    5
    [root@VM-0-14-centos shell]# ./testFor.sh 10 20 30
    the number is 10 20 30
    the number is 10
    the number is 20
    the number is 30
  2. for((初始值;循环控制条件;变量变化))
    do
        程序
    done
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15

    1. 示例:

    ```bash
    #!/bin/bash

    #从1加到100的值输出显示

    #定义一个变量
    SUM=0
    for((i=1;i<=100;i++))
    do
    SUM=$[$SUM+$i]
    done
    echo "SUM=$SUM"
    2. 结果
    1
    2
    [root@VM-0-14-centos shell]# ./testFor2.sh
    SUM=5050

while

语法

1
2
3
4
while [ 条件判断式 ] #注意while和条件判断式与中括号之间要有空格
do
程序
done

示例

1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/bash

#从命令行输入一个参数n,统计从1+..+n的值

SUM=0
i=0
while [ $i -le $1 ]
do
SUM=$[$SUM+$i]
i=$[$i+1]
done
echo "SUM=$SUM"

读取控制台输入

read

语法

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

示例

1
2
3
4
5
6
7
8
9
10
11
#!/bin/bash

#1.读取控制台输入一个num的值

read -p "请输入一个数num1=" NUM1
echo "你输入的值是 num1=$NUM1"

#2.读取控制台输入一个num的值,十秒内输入

read -t 10 -p "请输入一个数num2=" NUM2
echo "你输入的值是 num2=$NUM2"

函数

shell有系统函数,也可以自定义函数.

系统函数

basename

  • 返回完整路径最后/的部分,常用于获取文件名

  • basename [pathname] [suffix]

  • basename [string] [suffix]

  • suffix为后缀,如果suffix被指定了, basename会将pathname或string中的suffix去掉

  • 示例

    • [root@VM-0-14-centos shell]# basename /home/aaa.txt
      aaa.txt
      [root@VM-0-14-centos shell]# basename /home/aaa.txt .txt
      aaa
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12

      #### dirname

      * 返回完整路径最后/的前面的部分,常用于返回路径部分

      * ```dirname 文件绝对路径```

      * 示例

      * ```bash
      root@VM-0-14-centos shell]# dirname /home/aaa.txt
      /home

自定义函数

  • 语法

    • [ function ] funname[()]
      {
              Action;
              [return int;]
      }
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21

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

      * 示例

      * 计算两个参数的和(read)

      * ```shell
      #!/bin/bash

      function getSum(){

      SUM=$[$n1+$n2]
      echo "和=$SUM"
      }

      read -p "请输入第一个n1" n1
      read -p "请输入第一个n2" n2

      #调用getSum
      getSum $n1 $n2

综合案例

需求

  1. 每天凌晨2.10备份数据库到 /data/backup/db
  2. 备份开始和备份结束能够给出相应的提示信息
  3. 备份后的文件要求以备份时间为文件名,并打包成.tar.gz的形式
  4. 在备份的同时,检查是否有10天前备份的数据库文件,如果有就将其删除

代码

在/usr/sbin下面创建脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#!/bin/bash

#完成数据库的定时备份
#备份的路径
BACKUP=/data/backup/db
#当前的时间作为文件名
#+和后面不能有空格
DATETIME=$(date +%Y_%m_%d_%H%M%S)
#可以输出变量调试
echo $DATETIME

echo "==========开始备份========="
echo "==========备份的路径是 $BACKUP/$DATETIME.tar.gz"

#主机
HOST=localhost
#用户名
DB_USER=root
#密码
DB_PWD=root
#备份数据库名
DATABASE=test

#创建备份的路径
#如果备份的路径文件夹存在,就使用,否则就创建
[ ! -d "$BACKUP/$DATETIME" ] && mkdir -p "$BACKUP/$DATETIME"
#执行mysql的备份数据库的指令
mysqldump -u${DB_USER} -p${DB_PWD} --host=$HOST $DATABASE | gzip > $BACKUP/$DATETIME/$DATETIME.sql.gz
#打包备份文件
cd $BACKUP
tar -zcvf $DATETIME.tar.gz $DATETIME
#删除临时目录
rm -rf $BACKUP/$DATETIME

#删除十天前的备份文件
find $BACKUP -mtime +10 -name "*.tar.gz" -exec rm -rf {} \;
echo "==========备份成功==========""

添加到定时任务中

crontab -e

写入

10 2 * * * /usr/sbin/backup/mysql_db_backup.sh