shell脚本编程

shell概述

什么是shell:shell是Linux内核与用户之间的解释器程序,通常指bash,负责向内核翻译及传达用户/程序指令,相当于操作系统的“外壳”。

切换解释器:如果需要使用另一种解释器,可以直接执行对应的shell解释器程序,比如可以通过sh指令切换到sh命令行环境。管理员也可以通过usermod修改用户的登陆shell。当前系统可使用的shell程序存放在/etc/shells中。

bash基本特性

  • 支持快捷键、tab补全
  • 支持历史命令
  • 支持别名
  • 支持标准输入输出
  • 支持重定向
  • 支持管道

shell的使用方式

  • 交互式:人工干预,执行效率低
  • 非交互式:安静的在后台执行,效率高,方便编写脚本

shell脚本

shelll脚本指提前写好的可执行语句,可以完成特定任务的文件

特点:

  • 顺序、批量化执行
  • 解释型程序

规范的脚本构成:

#!/bin/bash		#脚本声明(声明使用解释器类型)
#注释信息
echo "hello world"	#可执行的脚本语句或命令行

脚本的执行方式:

  1. 作为“命令字”

    必须在脚本有x权限的前提下,通过./脚本名执行该脚本

  2. 作为“参数”

    • bash 脚本解释器
    • source 脚本解释器
    • . 脚本解释器

调试shell脚本:

  • 直接观察执行中的输出、报错信息
  • 通过sh -x 开启调试模式
  • 在可能出错的地方设置echo

简单的脚本应用

搭建本地yum服务

#!/bin/bash
#create yum service
[ ! -e /dev/cdrom ] && echo 'image not exists'
mount /dev/cdrom /media &> /dev/null

#backup file
[ ! -d /etc/yum.repos.d/backup ]&&mkdir /etc/yum.repos.d/backup
[ -f /etc/yum.repos.d/ ]&&mv /etc/yum.repos.d/*.repo /etc/yum.repos.d/backup

#edit '.repo' file
echo '
[app]
baseurl=file:///media/AppStream
gpgcheck=0
[base]
baseurl=file:///media/BaseOS
gpgcheck=0
'> /etc/yum.repos.d/dvd.repo

#yum test
yum clean all &> /dev/null
yum repoinfo &> /dev/null
[ $? -ne 0 ] && echo 'create yum filed' && exit
echo 'create yum successfully'

搭建ftp服务

#!/bin/bash
yum -y install vsftpd &> /dev/null
systemctl restart vsftpd
systemctl enable vsftpd
echo 'vsftpd start successfully'

shell变量

定义:以固定的名称存放可能会变化的值,

优点:

  • 提高脚本对任务需求、运行环境变化的适应能力
  • 方便在脚本中重复使用

变量操作:

  • 定义/赋值

    变量名=变量值

    • 变量未赋值时默认为空
    • 如果变量名已存在,再次赋值相当于重新为变量赋值
    • 等号两边不能有空格
    • 变量名由数字、字母、下划线组成,且区分大小写
    • 变量名不能以数字开头,不能使用关键字和特殊字符
  • 查看变量

    • 引用变量值:$变量名
    • 查看变量值:echo $变量名echo ${变量名}(${变量名}可以将变量名和其前后的字符分隔开来)
  • 取消变量

    • 推出定义变量的shell环境时,变量会自动消失
    • unset 变量名可以手动取消变量

变量的类型:

  • 按存储类型分类:

    • 整形、浮点型、双精度浮点型、字符型、...
    • shell对存储类型的要求比较松散
  • 按使用类型分类:

    • 环境变量:变量名通常为大写,由系统维护,用于设置工作环境,只有个别变量用户可以直接更改

      相关操作:

      • env:列出所有环境变量
      • set:列出所有变量
      • 配合grep使用

      常见环境变量:PWD、PATH、USER、LOGNAME、UID、SHELL、HOME、PS1、PS2...

    • 位置变量:bash内置,存储执行脚本是提供的参数

      $n表示,n为序号,在执行脚本时提供的命令行参数

    • 预定义变量:bash内置,一类有特殊用途的变量,可以直接调用,但不能直接赋值或修改

      $0:当前所在的进程或脚本名

      $$:当前运行进程的PID

      $?:命令执行后的返回状态,0为正常,非0为异常

      $#:已加载的位置变量的个数

      $*:所有位置变量的值

    • 自定义变量:由用户自主设置、修改及使用

变量值及范围控制

三种定界符:

  • 双引号:"": 允许使用扩展,以$引用其他变量
  • 单引号:'':禁用扩展,所有特殊字符都视为普通字符
  • 反撇号:``:将命令运行结果输出。

read标准输入取值

  • read 从键盘读入变量值完成赋值:

    格式:read [-p "提示信息"] 变量名

    -p可输入提示信息,-t可指定超时秒数。

  • 终端显示控制:

    stty -echo:关闭终端输出(无显示)

    stty echo:恢复终端输出(显示)

    可以用来在输入密码时屏蔽密码显示。

变量的作用范围

局部变量只能在当前shell环境中使用,进入子shell后无法使用。

可以通过export 变量名将变量声明为全局变量,通过export -n 变量名取消全局变量。

数值运算

基本运算类型:

加:num1 + num2

减:num1 - num2

乘:num1 * num2

除:num1 / num2

求模:num1 % num2

运算工具

  1. expr:

    格式:expr 整数1 运算符 整数2

    注:

    • 乘法操作应采用\*转义,避免被shell当作通配符。
    • expr只能用与整数运算,计算结果均只保留整数位。
  2. $[]运算替换

    使用$[]或$(())表达式可以直接得出计算结果

    格式:$[整数1 运算符 整数2]

    注:

    • 乘法操作无需转义
    • 可以与echo结合,输出计算结果
    • 只能进行整数运算
  3. let实现变量的自增减

    let i++ #i+1

    let i-- #i-1

    let i*=2 #i=i*2
    ...

  4. bc:

    • 支持小数运算
    • 通过scale=n指定小数的位数
    • echo "scale=4;10/3;2.2*4.1" | bc通过echo输出多个表达式的计算结果

逻辑判断

语法:test 选项 参数[ 选项 参数 ]

常见的测试操作:

  • 字符串比较

    [ 操作符 字符串 ]

    操作符:

    -z判断字符串的值为空;-n判断字符串的值非空

    ==两个字符串相同;!=两个字符串不同

  • 整数值比较

    [ 整数1 操作符 整数2 ]

    -eq等于

    -ne不等于

    -ge大于等于

    -le小于等于

    -gt大于

    -lt小于

  • 文件状态测试

    [ 操作符 文件或目录 ]

    -e判断是否存在

    -d判断是否是目录

    -f判断是否是一般文件

    -r判断是否有读权限

    -w判断是否有写权限

    -x判断是否有可执行权限

循环

格式:

  1. 单分支结构

    if 条件测试;then

    ​ 命令序列

    fi

  2. 双分支结构

    if 条件测试;then

    ​ 命令序列1

    else

    ​ 命令序列2

    fi

  3. 多分支结构

    if 条件测试1;then

    ​ 命令序列1

    elif 条件测试2;then

    ​ 命令序列2

    else

    ​ 命令序列3

    fi

相关练习

  1. 检测/if_test/cdrom/目录是否存在,不存在则创建

    #!/bin/bash
    dir=/if_test/cdrom/
    if [ -d $dir ];then
            echo ${dir} exist. && exit
    else    
            mkdir -p $dir
    fi
    
  2. 编写脚本,检测并判断指定的主机是否可ping通

    #!/bin/bash
    # ping命令个参数作用:可以只发送3个测试包(-c 3)、缩短发送测试包的间隔秒数(-i 0.2)、等待反馈的超时秒数(-W 1)
    ip=192.168.99.100
    ping -c3 -i 0.2 -W 1 $ip &> /dev/null
    if [ $? -eq 0 ];then
            echo 'host $1 is up'
    else
            echo 'host $1 is down'
    fi
    
  3. 判断成绩

    #!/bin/bash
    read -p 'press your grade: ' n
    if [ $n -gt 100 ] || [ $n -lt 0 ];then
            echo 'press a number(0-100)' && exit
    elif [ $n -ge 90 ];then
            echo great
    elif [ $n -ge 80 ];then
            echo nice
    else
            echo good
    fi
    

循环

for循环:

  • 格式:

    for 变量名 in 值列表

    do

    ​ 命令序列

    done

  • c语言风格:

    for((i=1;i<=5;i++))

    do

    ​ 命令序列

    done

练习

  1. 写一个Shell脚本chkhosts.sh,利用for循环来检测多个主机的存活状态,并显示最后统计结果

    #!/bin/bash
    up=0
    down=0
    for i in {100..110}
    do
            ping -c 3 -i 0.2 -w 1 192.168.99.$i &> /dev/null
            if [ $? -eq 0 ];then
                    let up++
            else
                    let down++
            fi
    done
    echo $up
    echo $down
    

while循环:

  • 格式:

    while 条件测试

    do

    ​ 命令序列

    done

while死循环

  • 格式:

    while :

    do

    ​ 命令序列

    done

中断及退出

  • exit:退出整个脚本
  • break:结束当前循环,继续执行循环之后的语句
  • continue:跳过本次循环中剩余语句

练习

  1. 从键盘循环取整数(0结束)并求和,输出最终结果

    #!/bin/bash
    sum=0
    while :
    do
            read -p 'press a number: ' n
            if [ -z $n ];then
                    continue
            elif [ $n -eq 0 ];then
                    break
            else
                    let sum+=n
            fi
    done
    echo sum=$sum
    

case语句

  • 语法

        case  变量  in
        模式1)
            命令序列1 ;;
        模式2)
            命令序列2 ;;
            .. ..
        *)
            默认命令序列
        esac
    
  • 练习

    编写一键部署Nginx脚本

    • 一键源码安装Nginx软件
    • 脚本自动安装相关软件的依赖包
    • 源码安装Nginx需要提前安装依赖包软件gcc,openssl-devel,pcre-devel
    #!/bin/bash
    yum -y install gcc openssl-devel pcre-devel
    tar -xf nginx-1.22.1.tar.gz
    cd nginx-1.22.1
    ./configure
    make
    make install
    

    编写Ngin启动脚本,要求如下:

    • 脚本支持start、stop、restart、status
    • 脚本支持报错提示
    • 脚本具有判断是否已经开启或关闭的功能
  • #!/bin/bash
    case $1 in
    start|kai)
            /usr/local/nginx/sbin/nginx;;
    stop|guan)
            /usr/local/nginx/sbin/nginx -s stop;;
    restart|cq)
            /usr/local/nginx/sbin/nginx -s stop
            /usr/local/nignx/sbin/nginx;;
    status|zt)
            ss -ntulp |grep -q nginx
            if [ $? -eq 0 ];then
    echo 服务已启动
    else
    echo 服务未启动
    fi;;
    *)
            echo Error;;
    esac
    

函数

  • 函数格式

    # 格式1
    function  函数名 {
        命令序列
        .. ..
    }
    
    # 格式2
    函数名() {
        命令序列
        .. ..
    }
    
  • 函数调用

    直接使用“函数名”的形式调用,如果该函数能够处理位置参数,则可以使用“函数名 参数1 参数2 .. ..”的形式调用。

    注意:函数的定义语句必须出现在调用之前,否则无法执行。

  • 练习

    用户在执行时提供2个整数参数,这个可以通过位置变量$1、$2读入。

    调用函数时,将用户提供的两个参数传递给函数处理。

    颜色输出的命令:echo -e "\033[32mOK\033[0m"。

    3X为字体颜色,4X为背景颜色。

    #!/bin/bash
    #echo -e "\033[$1m$2\033[0m"中$1表示显示输出文本的颜色。3X为字体颜色,4X为背景颜色
    
    cecho(){
            echo -e "\033[$1m$2\033[0m"
    }
    cecho 32 ok
    cecho 33 ok
    

字符串操作

  1. 字符串的截取

    格式:${var:起始位置:长度}

  2. 字符串的替换

    格式:只替换第一个匹配的结果${var/old/new}

    ​ 替换全部匹配结果:${var//old/new}

  3. 掐头

    • 从左往右,最短匹配删除

      格式:${变量名#*关键词}

    • 从左往右,最长匹配删除

      格式:${变量名##*关键词}

  4. 去尾

    • 从右往左,最短匹配

      格式:${变量名%关键词*}

    • 从右往左,最长匹配

      格式:${变量名%%关键词*}

  5. 设置变量初值

    格式:${var:-word}

    若var已存在,且非空,则返回$var的值

    否则返回字符串‘word’,变量var值不变。

sed入门

未完待续。。。

awk入门

未完待续。。。

posted on 2023-06-03 16:30  紫罗兰花园  阅读(11)  评论(0)    收藏  举报

导航