• 一篇文章教会你如何编写一个简单的Shell脚本


    简单Shell脚本编写

    Shell脚本概念

    Shell 脚本是一种用于自动化执行一系列命令和操作的脚本文件。它使用的是 Shell 解释器(如 Bash、Korn Shell、Zsh 等)来解释和执行其中的命令。Shell 脚本通常用于编写简单的任务和工作流程,可以帮助我们进行系统管理、批量处理、自动化部署等任务。

    以.sh后缀名结尾的文件来表示该文件是一个Shell脚本。

    Shell脚本就是将命令写入文本中,文本可以被执行。

    1. 简单脚本编写

    文件内容如下:

    image-20230903114629343

    编写完脚本后,赋权文件的执行权限

    方式一

    chmod +x 脚本文件
    
    • 1

    image-20230903114742333

    方式二

    bash 脚本文件
    
    • 1

    image-20230903114659648

    2. Shell脚本参数

    $0:表示当前脚本的名称。

    $*:表示脚本的所有参数。

    $#:表示脚本的参数的个数。

    $n:表示脚本的第n个参数,n=1,2,3…

    $? :程序执行完后的结果,返回值0表示执行成功。

    #!/bin/bash
    echo "当前脚本名称$0"
    echo "总共有$#个参数,分别是$*。"
    echo "第一个参数为$1,第三个参数为$3"
    
    • 1
    • 2
    • 3
    • 4

    image-20230903120223123

    在执行该Shell脚本文件的时候在后面添加三个参数分别是wuhu1,wuhu2,wuhu3。

    执行结果:

    image-20230903120259036

    注意

    • 双引号会解释变量

    • 单引号会把变量当成字符串表示

    2.1 Shell脚本参数判断

    2.1.1 文件测试语句
    • -d:测试文件是否为目录类型,是目录返回0,不是目录返回非0值。
    • -e:测试文件是否存在。
    • -f:判断是否为一般文件。
    • -r:判断当前用户对该文件是否有读取权限。
    • -w:判断当前用户对该文件是否有写入权限。
    • -x:判断当前用户对该文件是否有执行权限。

    判读是否为目录

    [ -d /etc/passwd ]
    echo $?				# $?返回上一次执行命令的结果
    
    • 1
    • 2

    说明:这里的[]中输入的内容前后需要加空格

    image-20230903123048335

    返回值为1,表示/etc/passwd不是目录。

    判断当前目录下的wuhu是否为目录

    image-20230903123346602

    判断是否为文件

    [ -f /etc/passwd ]
    echo $?				# $?返回上一次执行命令的结果
    
    • 1
    • 2

    image-20230903123516341

    返回值为0,表示/etc/passwd是文件。

    2.1.2 逻辑测试语句

    逻辑运算符:

    • &&
    • ||

    问题:上面所输入命令十分的繁琐,是否可以使用一条命令来完成上面的操作?

    注意:这里是不能使用管道符的,使用管道符发现两次的输出值是不一样的。

    image-20230903124043040

    可以使用**&&**符号

    • && 必须保证两边都为真,条件才会成立,只要有一个为假条件都不会成立。
    • 只有当左侧命令执行成功时,右侧的命令才会被执行。
    [ -f /etc/passwd ] && echo  "/etc/passwd是一个文件"
    [ -d wuhu ] && echo  "wuhu是一个目录"
    
    • 1
    • 2

    image-20230903124711636

    [ $USER = root ] && echo  "该用户是超级管理员用户"
    
    • 1

    image-20230903125212876

    还可以使用**|| **符号

    • || 两边有一个为真就为真,两边都为真也为真,两边为假才为假。
    • 如果左侧命令执行成功(返回值为零),则右侧的命令将不会被执行。
    [ $USER = root ] || echo  "该用户是超级管理员用户"		# 表示当前用户不是root输出对应的语句
    
    [ ! $USER = root ] || echo  "该用户是超级管理员用户"	# 表示当前用户是root输出对应的语句
    
    • 1
    • 2
    • 3

    image-20230903125749282

    例如:要求普通用户输出user,管理员用户输出superuser

    [ ! $USER = root ] && echo "user" || echo "superuser"
    
    • 1

    image-20230903131030219

    切换回普通用户,执行该命令

    image-20230903131230506

    2.1.3 整数值测试语句

    整数的比较运输符

    • -eq:是否等于
    • -ne:是否不等于
    • -gt:是否大于
    • -lt:是否小于
    • -le:是否等于或小于
    • -ge:是否等于或大于
    [ 9 -eq 8 ]
    echo $?
    
    [ 9 -ne 8 ]
    echo $?
    
    • 1
    • 2
    • 3
    • 4
    • 5

    image-20230903134238723

    free:查看内存

    image-20230903134650248

    现在需要输出free中的Mem这一行

    free -m | grep Mem | awk '{print $4}'
    
    • 1

    image-20230903134734422

    定义变量

    Freemem=`free -m | grep Mem | awk '{print $4}'`
    echo $Freemem			# 输出变量
    
    • 1
    • 2

    image-20230903135523368

    例如:如果这个值小于1024的时候,会输出内容不足的提示信息。

    [ $Freemem -gt 1024 ] && echo "内存不足"
    [ $Freemem -lt 1024 ] && echo "内存不足"
    
    • 1
    • 2

    image-20230903135912372

    2.1.4 字符串比较语句

    字符串比较:

    • =:比较字符串内容是否相同。
    • !=:比较字符串内容是否不同。
    • -z:判断字符串内容是否为空,如果为空返回0表示真,如果不为空返回1。
    [ -z $String ]
    echo $?			# 返回结果为0,因为没有定义过这个变量
    
    [ -z $USER ]
    echo $?			# 返回结果为1,因为当前用户不为空
    
    • 1
    • 2
    • 3
    • 4
    • 5

    image-20230903140444779

    判断当前系统是否支持中文。

    [ $LANG = zh_CN.UTF-8 ] && echo "支持中文" || echo "不支持中文"
    
    • 1

    image-20230903141125055

    3. Shell流程控制语句

    流程控制语句

    • if
    • then
    • else
    • fi

    3.1 if 条件测试语句

    3.1.1 if…

    基本格式如下:

    if 条件测试语句		
    then 
    	命令序列
    fi  结束if语句
    
    • 1
    • 2
    • 3
    • 4

    例如:判断home目录下是否存在test目录,如果不存在则创建一个。

    #!/bin/bash
    DIR="/home/test"
    if [ ! -e $DIR ]
    then
            mkdir -p $DIR
    fi
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    image-20230903142903331

    执行结果

    image-20230903143054035

    3.1.2 if…else…

    基本格式如下:

    if 条件测试语句		
    then 
    	命令序列
    else 
    	命令序列
    fi  结束if语句
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    例如:判断给定的IP是否正常

    #!/bin/bash
    ping -c 3 -i 0.2 -W 3 $1 &>/dev/null
    if [ $? -eq 0 ]
    then
            echo "$1该IP是正常的"
    else 
            echo "$1该IP无法ping通" 
    fi 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    说明:&>/dev/null在 Linux/Unix 系统中,“/dev/null” 是一个空设备文件,它可以用于丢弃不需要的输出,相当于一个黑洞。

    image-20230903144743570

    执行结果

    image-20230903144820330

    然后就可以完善一下脚本内容

    #!/bin/bash
    if [ -z $1 ]
    then
            echo "作者:小薛"
            echo "该命令检测服务器IP是否正常"
            echo "直接在命令后面加参数IP就可以执行"
    else
            ping -c 3 -i 0.2 -W 3 $1 &>/dev/null
            if [ $? -eq 0 ]
            then
                    echo "$1该IP是正常的"
            else
                    echo "$1该IP无法ping通" 
            fi
    fi
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    说明

    • “-c 3” 选项表示发送 3 个 ICMP 请求消息,并等待每个请求的响应。
    • “-i 0.2” 选项表示设置每个 ICMP 请求的时间间隔为 0.2 秒(即每 200 毫秒发送一个请求)。
    • “-W 3” 选项表示设置等待响应的超时时间为 3 秒。

    image-20230903150021885

    执行效果

    image-20230903150119546

    3.1.3 if…elif…else

    基本格式如下:

    if 条件测试语句1	
    then 
    	命令序列1
    elif 条件测试语句2
    then 
    	命令序列2
    else 
    	命令序列3
    fi  结束if语句
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    例如:判断学员考试分数如何

    #!/bin/bash
    read -p "请输入分数(1-100):" fenshu
    if [ $fenshu -ge 85 ] && [ $fenshu -le 100 ];then
            echo "该学生成绩为优秀"
    elif [ $fenshu -ge 70 ] && [ $fenshu -le 84 ];then
            echo "该学生成绩为合格"
    else
            echo "该学生成绩为不合格"               
    fi
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    说明:

    • “-p” 选项用于在用户输入之前显示一个提示信息。
    • “read” 是一个 Bash 内置命令,用于从标准输入中读取用户输入并将其赋值给一个变量。
    • “fenshu” 是用于存储用户输入值的变量名。

    image-20230903152258328

    执行效果如下

    image-20230903152359934

    4. Shell脚本循环

    4.1 for循环

    基本格式:

    for 变量名 in 取值列表
    do
    	命令序列
    done
    
    • 1
    • 2
    • 3
    • 4
    4.1.1 批量添加用户

    创建一个用户名的txt文件

    image-20230903153430251

    编写Shell脚本

    #!/bin/bash
    read -p "请输入密码:" PASSWORD
    for USERNAME in `cat user.txt`
    do      
            id $USERNAME &> /dev/null
            if [ $? -eq 0 ]
            then    
                    echo "$USERNAME用户已存在!"
            else    
                    useradd $USERNAME &> /dev/null
                    echo "$PASSWORD" | passwd --stdin $USERNAME &> /dev/null
                    echo "$USERNAME用户创建成功"
            fi      
    done
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    说明

    • –stdin:选项告诉passwd命令从标准输入(stdin)读取密码,而不是要求用户手动输入密码。

    image-20230903154931261

    执行结果如下:

    image-20230903155507018

    创建前

    image-20230903155024371

    创建后image-20230903155524208

    4.1.2 批量删除用户

    编写Shell脚本

    #!/bin/bash
    for USERNAME in `cat user.txt`
    do
            id $USERNAME &> /dev/null
            if [ $? -eq 0 ]
            then
                    userdel -r $USERNAME &>/dev/null
                    echo "$USERNAME用户已删除"
            else
                    echo "$USERNAME用户不存在!"
            fi
    done
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    image-20230903161734398

    执行结果

    image-20230903161831687

    4.1.3 批量ping IP 地址

    创建一个IP地址的txt文件

    image-20230903162332275

    编写Shell脚本

    #!/bin/bash
    HOSTLIST=$(cat /root/iplist.txt)
    for IP in $HOSTLIST
    do
            ping -c 3 -i 0.2 -W 3 $IP &>/dev/null
            if [ $? -eq 0 ]
            then    
                    echo "$IP该IP是正常的"
            else    
                    echo "$IP该IP无法ping通"
            fi      
    done
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    说明

    • “$()” 是 Bash 中的命令替换语法,它表示将命令的输出结果作为一个整体嵌入到命令行中。

    image-20230903162909854

    执行效果如下:

    image-20230903163034465

    4.1.4 检测同一局域网,多台主机存活情况

    方式一

    #!/bin/bash
    read -p "请输入网络位:" NETWORK
    for ((IP=1;IP<=100;IP++))
    do
            ping -c 3 -i 0.2 -W 3 $NETWORK.$IP &> /dev/null
            if [ $? -eq 0 ]
            then
                    echo "$NETWORK.$IP该IP可以ping通"
    
            else
                    echo "$NETWORK.$IP该IP无法ping通!!!!!!!"
            fi
    done
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    执行结果:

    image-20230903165538490

    方式二

    #!/bin/bash
    read -p "请输入网络位:" NETWORK
    for IP in `seq 1 254`
    do
            ping -c 3 -i 0.2 -W 3 $NETWORK.$IP &> /dev/null
            if [ $? -eq 0 ]
            then
                    echo "$NETWORK.$IP该IP可以ping通"
    
            else
                    echo "$NETWORK.$IP该IP无法ping通!!!!!!!"
            fi
    done
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    说明:

    • “seq” 是一个用于生成序列的命令。
    • “1” 是序列的起始值。
    • “254” 是序列的结束值。

    执行结果:

    image-20230903165524898

    4.2 while循环

    基本格式如下:

    while 条件
    do
    	命令序列
    done
    
    • 1
    • 2
    • 3
    • 4

    例如:猜测商品价格

    编写Shell脚本

    #!/bin/bash
    echo "该商品价格在0~1000之间,输入价格来猜一猜"
    TIMES=0
    PRICE=$(expr $RANDOM % 1000 )
    while true
    do
            read -p "请输入价格:" INT
            let TIMES++
            if [ $INT -eq $PRICE ]
            then    
                    echo "恭喜您猜对了该商品的及格,价格为$INT"
                    echo "您猜了$TIMES次"
                    exit
            elif [ $INT -gt $PRICE ];then
                    echo "您所输入的价格高了"
            else
                    echo "您所输入的价格低了"
            fi      
    done
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    说明

    • $RANDOM是linux中的内置变量,可以随机生成0-32767之间的整数数字。
    • “expr” 是一个用于执行基本数学运算或字符串操作的命令。

    image-20230903171930137

    执行结果

    image-20230903172221018

    4.3 case条件测试语句

    基本格式如下:

    case 变量值 in 
    模式1
    	命令序列1
    模式2 
    	命令序列2
    ....
    	默认命令序列
    esac
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    例如:判断输入的是字母,数字,还是特殊符号

    编写Shell脚本

    #!/bin/bash
    read -p "请输入一个字符:" KEY
    case "$KEY" in
            [a-z]|[A-Z])
                    echo "这是字母"
                    ;;
            [0-9])
                    echo "这是数字"
                    ;;
            *)
                    echo "这是特殊符号"
    esac
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    image-20230903173802938

    执行效果如下:

    image-20230903173832062

  • 相关阅读:
    tp5事务和加锁
    【6】Kalibr 对单目相机 + IMU 联合标定
    偏微分方程的人工智能
    Java书签 #获取项目应用中所有Mapper接口并打印URL
    【测控电路】信号分离电路 二阶滤波器 RC滤波电路
    Arya科普 | 程序员常用英语 & Java常用名词解释 & 计算机常用英语汇总
    【Java SE】基本数据类型
    金仓数据库 KingbaseES V8 GIS 数据迁移方案(5. 第三方通用格式 GIS 数据迁移到 KES)
    Springboot 实践(12)RabbitMq server 安装调试(Windows环境)
    巨杉湖仓一体技术解读|实时对客释放全量数据价值
  • 原文地址:https://blog.csdn.net/weixin_58783105/article/details/132652789