shell脚本编程

Shell概述

  • shell连接了用户和Linux内核,它可以解释用户输入的命令传递给内核,让用户可以更加方便的使用Linux系统

  • shell 本身并不是内核的一部分,它只是站在内核的基础上编写的一个应用程序

  • shell具备编程的能力,shell也是一种语言,C,C++,java,php,Python,Go等

  • 语言分为编译型语言,C,C++,Go,需要提前编译,编译语言都有编译器

  • 解释型语言,shell,Python,php,不需要提前编译,一边执行,一边解释,每种解释型语言都有解释器

  • shell语言支持大部分编程语言都具备的功能:if判断,for循环,变量,数组,函数,加减乘除,逻辑运算

规范shell脚本组成

[root@test ~]# vim user.sh
#!/bin/bash(环境声明)
#注释信息
可执行代码…

如何写好一个shell脚本

  • 明确任务需求
  • 按需求整理好每一个步骤,先做什么,后做什么
  • 运行脚本,并根据运行结果排除错误
  • 优化脚本并达到最终效果

编写脚本

  • 编写第一个脚本
[root@localhost ~]# vim hello.sh
#!/bin/bash
#hello word
echo hello word

#赋予执行权限
[root@localhost ~]# chmod u+x hello.sh

#执行脚本
[root@localhost ~]# /root/hello.sh 
hello word
  • 编写创建用户脚本
[root@localhost ~]# vim user.sh
#!/bin/bash
useradd abc  
passwd abc

[root@localhost ~]# chmod u+x user.sh 

#非交互
[root@localhost ~]# vim user.sh
#!/bin/bash
useradd yyyy
echo 1 | passwd --stdin yyyy

[root@localhost ~]# ./user.sh 
更改用户 yyyy 的密码 。
passwd:所有的身份验证令牌已经成功更新。
  • 编写批量查看脚本
#查看系统版本信息,查看系统内核信息,查看系统内存信息,查看系统网卡信息,查看当前主机名
[root@localhost ~]# vim info.sh
cat /etc/redhat-release
uname -r
free -h
ifconfig ens32
hostname

#赋予执行权限
[root@localhost ~]# chmod u+x info.sh 

#执行脚本
[root@localhost ~]# ./info.sh 
CentOS Linux release 7.6.1810 (Core) 
3.10.0-957.el7.x86_64
              total        used        free      shared  buff/cache   available
Mem:           972M        480M        147M         16M        344M        260M
Swap:          2.0G        239M        1.8G
ens32: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.0.100  netmask 255.255.255.0  broadcast 192.168.0.255
        inet6 fe80::8903:cb8:127b:dbc8  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:a0:e8:12  txqueuelen 1000  (Ethernet)
        RX packets 230110  bytes 325471733 (310.3 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 20635  bytes 1385581 (1.3 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

localhost.localdomain

  • 编写配置本地yum源脚本
#编写搭建本地yum仓库脚本【版1,丢人版】
[root@localhost ~]# vim yum.sh 
#!/bin/bash
mkdir /mnt/centos
mount /dev/cdrom /mnt/centos
echo '/dev/cdrom /mnt/centos iso9660 defaults 0 0' >> /etc/fstab
rm -rf /etc/yum.repos.d/*
touch  /etc/yum.repos.d/local.repo
echo "[local]" > /etc/yum.repos.d/local.repo
echo "name=local_centos" >> /etc/yum.repos.d/local.repo
echo "baseurl=file:///mnt/centos" >> /etc/yum.repos.d/local.repo
echo "enabled=1" >> /etc/yum.repos.d/local.repo
echo "gpgcheck=0" >> /etc/yum.repos.d/local.repo

#编写搭建本地yum仓库脚本【版2,正常版】
[root@localhost ~]# vim yum.sh 
#!/bin/bash
mkdir /mnt/centos
mount /dev/cdrom /mnt/centos
echo '/dev/cdrom /mnt/centos iso9660 defaults 0 0' >> /etc/fstab
mount -a
rm -rf /etc/yum.repos.d/*
echo "[local] 
name=local_centos 
baseurl=file:///mnt/centos 
enabled=1 
gpgcheck=0" > /etc/yum.repos.d/local.repo

#编写搭建本地yum仓库脚本【升级版】
[root@localhost ~]# vim yum.sh 
#!/bin/bash
echo "正在配置本地yum仓库..."
mkdir /mnt/centos
mount /dev/cdrom /mnt/centos &> /dev/null
echo '/dev/cdrom /mnt/centos iso9660 defaults 0 0' >> /etc/fstab
mount -a
rm -rf /etc/yum.repos.d/*
echo "[local] 
name=local_centos 
baseurl=file:///mnt/centos 
enabled=1 
gpgcheck=0" > /etc/yum.repos.d/local.repo
echo "本地yum仓库配置以完成..."
yum clean all &> /dev/null
yum repolist | tail -1


#执行脚本
[root@localhost ~]# ./yum.sh
正在配置本地yum仓库...
本地yum仓库配置以完成...
repolist: 4,021

脚本的执行方式

  • 执行一个脚本的方法有很多种
  • 方法一:赋予脚本执行权限后,可用绝对路径或者当前路径执行
  • 方法二:调用解释器执行脚本文件
#绝对路径执行脚本
[root@localhost ~]# /root/hello.sh 

#相对路径执行脚本
[root@localhost ~]# ./hello.sh 

#去除执行权限
[root@localhost ~]# chmod u-x hello.sh 

#执行脚本
[root@localhost ~]# /root/hello.sh
-bash: /root/hello.sh: 权限不够

[root@localhost ~]# ./hello.sh
-bash: ./hello.sh: 权限不够

#调用解释器执行脚本
[root@localhost ~]# bash hello.sh
hello word

[root@localhost ~]# cat /etc/shells 
/bin/sh
/bin/bash
/usr/bin/sh
/usr/bin/bash
/bin/tcsh
/bin/csh
[root@localhost ~]# sh hello.sh
hello word
[root@localhost ~]# tcsh hello.sh
hello word
[root@localhost ~]# csh hello.sh
hello word

常用特殊符号补充

  • “ “ #双引号,引用整体
  • ‘ ’ #单引号,引用整体并取消所有特殊字符含义
  • $[] #四则运算(+ - * / % 取余数)
  • $() #将命令的输出结果作为参数
  • 反撇 `` 将命令的输出结果作为参数

#引用整体,不屏蔽特殊符号的功能
[root@localhost ~]# echo "$PATH"
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin

#引用整体,屏蔽特殊符号的功能
[root@localhost ~]# echo '$PATH'
$PATH

#没有特殊符号单引双引都可以
[root@localhost ~]# echo "xxoo"
xxoo
[root@localhost ~]# echo 'xxoo'
xxoo

#四则运算
[root@localhost ~]# echo $[1+1]
2
[root@localhost ~]# echo $[1+5]
6
[root@localhost ~]# echo $[10-5]
5
[root@localhost ~]# echo $[10*5]
50
[root@localhost ~]# echo $[10/5]
2
[root@localhost ~]# echo $[1+3+4+5+7]
20
[root@localhost ~]# echo $[10/3]
3
[root@localhost ~]# echo $[10%3]
1

#$()取命令结果作为参数
root@localhost ~]# touch $(date +%F)-abc.txt
2021-05-09-abc.txt 

#``取命令结果作为参数
[root@localhost ~]# touch `date +%F`-xxoo.txt
2021-05-09-xxoo.txt

变量

  • 以固定的名称存放可能变化的值,提高脚本的灵活度来适应多变的环境
  • 定义变量:变量名=变量值,如:a1=abc(等号两边不要有空格)
  • 定义变量注意事项:
    • 变量名由字母/数字/下划线组成,区分大小写,不能以数字开头,不要使用命令和特殊符号
  • 若指定的变量名已经存在,相当于为此变量重新赋值
  • 取消变量:unset 变量名
root@localhost ~]# xx=haha

[root@localhost ~]# echo $xx
haha

[root@localhost ~]# xx=abcd
[root@localhost ~]# echo $xx
abcd

[root@localhost ~]# xx=5
[root@localhost ~]# echo $xx
5
[root@localhost ~]# echo $[xx+5]
10

#通过变量定义用户名
[root@localhost ~]# vim user.sh 
#!/bin/bash
user=wangxin
useradd $user   
echo 1 | passwd --stdin $user

[root@localhost ~]# ./user.sh 
更改用户 wangxin 的密码 。
passwd:所有的身份验证令牌已经成功更新。

[root@localhost ~]# vim user.sh 
#!/bin/bash
user=sdd
useradd $user
echo 1 | passwd --stdin $user

[root@localhost ~]# ./user.sh 
更改用户 sdd 的密码 。
passwd:所有的身份验证令牌已经成功更新。

[root@localhost ~]# vim user.sh 
#!/bin/bash
user=panghu
useradd $user
echo "用户$user创建成功"
echo 1 | passwd --stdin $user &> /dev/null
echo "用户$user密码设置成功"

[root@localhost ~]# ./user.sh 
用户panghu创建成功
用户panghu密码设置成功

read标准输入取值

  • read 读取用户在键盘上输入的内容,并把内容存放在变量里,可以降低脚本的使用难度
  • 命令格式:read -p “提示信息” 变量名
[root@localhost ~]# vim user.sh 
#!/bin/bash
read -p '请输入用户名:' user
useradd $user 
echo "用户$user创建成功"
read -p '请设置用户密码:' pass
echo $pass | passwd --stdin $user &> /dev/null
echo "用户$user密码设置成功"

[root@localhost ~]# ./user.sh 
请输入用户名:wuhan
用户wuhan创建成功
请设置用户密码:1
用户wuhan密码设置成功

[root@localhost ~]# ./user.sh 
请输入用户名:liangjing
用户liangjing创建成功
请设置用户密码:xxoo
用户liangjing密码设置成功

变量种类

  • 环境变量:变量名一般都大写,用来设置用户/系统环境

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

  • 预定义变量:bash内置,可直接调用的特殊值,不能直接修改

  • 自定义变量:用户自定义

  • env 命令查看系统所有环境变量

  • set 命令查看系统所有变量,包括用户自定义变量

  • 环境变量

[root@localhost etc]# env
MAIL=/var/spool/mail/root
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
PWD=/root
LANG=zh_CN.UTF-8
SELINUX_LEVEL_REQUESTED=
HISTCONTROL=ignoredups
SHLVL=1
HOME=/root
LOGNAME=root
XDG_DATA_DIRS=/root/.local/share/flatpak/exports/share:/var/lib/flatpak/exports/share:/usr/local/share:/usr/share
SSH_CONNECTION=192.168.0.1 51791 192.168.0.100 22
LESSOPEN=||/usr/bin/lesspipe.sh %s
XDG_RUNTIME_DIR=/run/user/0
DISPLAY=localhost:10.0
_=/usr/bin/env
OLDPWD=/root

#获取变量值
[root@localhost etc]# echo $SHELL
/bin/bash

[root@localhost ~]# echo $PWD
/root

#查看系统所有变量
[root@localhost ~]# set
[root@localhost ~]# set | grep $a
  • 位置变量

    $0 #脚本名称

    $1 #第一个参数

    $2 #第二个参数

    $3 #第三个参数

    $4 #第四个参数

    $n… #第n个参数

  • 预定义变量

    $0 #代表脚本本身

    $* #显示所有参数内容

    $# #显示有多少个参数

    $? #显示上一条命令的执行结果(0代表正确,非0代表错误)

    \[ #显示脚本进程号(PID) \]

[root@localhost ~]# vim test.sh

!/bin/bash

echo $0
echo $1
echo $2
echo $3
echo $*
echo $#
echo $$
echo $?

赋予执行权限,执行脚本

[root@localhost ~]# ./test.sh xx oo dd
./test.sh $0
xx $1
oo $2
dd $3
xx oo dd $*
3 $#
15594 $$
0 $?




#### 判断文件状态

- -e     #判断文档(文件/目录)是否存在,存在为真
- -d     #判断目录是否存在,存在为真
- -f      #判断文件是否存在,存在为真
- -r      #可读为真
- -w     #可写为真
- -x      #可执行为真

```shell
#判断文档是否存在
[root@localhost ~]# [ -e /etc/ ]
[root@localhost ~]# echo $?
0 #为真

#判断目录是否存在
[root@localhost ~]# [ -d /opt ]
[root@localhost ~]# echo $?
0

[root@localhost ~]# [ -d /etc/passwd ]
[root@localhost ~]# echo $?
1

[root@localhost ~]# [ -f /etc/passwd ]
[root@localhost ~]# echo $?
0

#判断是否可读(以当前用户身份判断)
[root@localhost ~]# [ -r /etc/passwd ]
[root@localhost ~]# echo $?
0

#判断是否可写
[root@localhost ~]# [ -w /etc/passwd ]
[root@localhost ~]# echo $?
0

#判断是否可执行
[root@localhost ~]# [ -x /etc/passwd ]
[root@localhost ~]# echo $?
1
[root@localhost ~]# ll /etc/passwd
-rw-r--r--. 1 root root 3294 5月   9 16:43 /etc/passwd

整数比较

  • -gt #大于
  • -ge #大于等于
  • -eq #等于
  • -lt #小于
  • -le #小于等于
  • -ne #不等于
[root@localhost ~]# [ 1 -gt 1 ]
[root@localhost ~]# echo $?
1

[root@localhost ~]# [ 1 -eq 1 ]
[root@localhost ~]# echo $?
0

[root@localhost ~]# [ 1 -ge 1 ]
[root@localhost ~]# echo $?
0

[root@localhost ~]# [ 1 -ge 2 ]
[root@localhost ~]# echo $?
1

[root@localhost ~]# [ 1 -lt 2 ]
[root@localhost ~]# echo $?
0

[root@localhost ~]# [ 1 -le 2 ]
[root@localhost ~]# echo $?
0

[root@localhost ~]# [ 1 -le 10 ]
[root@localhost ~]# echo $?
0
[root@localhost ~]# [ 10 -le 10 ]
[root@localhost ~]# echo $?
0

[root@localhost ~]# [ 1 -ne 2 ]
[root@localhost ~]# echo $?
0

[root@localhost ~]# [ 2 -ne 2 ]
[root@localhost ~]# echo $?
1

字符串对比

  • == #相等
  • != #不相等
[root@localhost ~]# [ root == xxoo ]
[root@localhost ~]# echo $?
1

[root@localhost ~]# [ root == $USER ]
[root@localhost ~]# echo $?
0

[root@localhost ~]# [ $USER == root ]
[root@localhost ~]# echo $?
0

[root@localhost ~]# [ abc == bcd ]
[root@localhost ~]# echo $?
1

[root@localhost ~]# [ abc != bcd ]
[root@localhost ~]# echo $?
0

[root@localhost ~]# [ $USER != root ]
[root@localhost ~]# echo $?
1

常用数值运算方式

  • $[] #四则运算(+ - * / % 取余数)
  • $(()) #数值运算工具
  • expr #数值运算工具
  • let #数值运算工具
[root@localhost ~]# echo $[10+5]
15
[root@localhost ~]# echo $[10-5]
5
[root@localhost ~]# echo $[10*5]
50
[root@localhost ~]# echo $[10/5]
2
[root@localhost ~]# echo $[10%3]
1

#$(())做数值运算
[root@localhost ~]# echo $((10+5))
15
[root@localhost ~]# echo $((10-5))
5
[root@localhost ~]# echo $((10*5))
50
[root@localhost ~]# echo $((10/5))
2
[root@localhost ~]# echo $((10%3))
1

#expr做数值运算
[root@localhost ~]# echo expr 2+3
expr 2+3
[root@localhost ~]# echo `expr 2+3`
2+3

#要求每一部分都要有空格
[root@localhost ~]# echo `expr 2 + 3`
5
[root@localhost ~]# echo `expr 10 - 3`
7

#当进行乘法运算时,需要实用“\”转义掉*的特殊功能
[root@localhost ~]# echo `expr 10 * 3`
expr: 语法错误

[root@localhost ~]# echo `expr 10 \* 3`
30
[root@localhost ~]# echo `expr 10 / 3`
3

#let做数值运算
[root@localhost ~]# let 1+1

#需要将运算的结果赋予一个变量存储
[root@localhost ~]# let x=1+1
[root@localhost ~]# echo $x
2
[root@localhost ~]# let a=10+5
[root@localhost ~]# echo $a
15

#通过变量的值进行运算
[root@localhost ~]# let b=a+x
[root@localhost ~]# echo $b
17

#let简写表达式	     #let完整表达式
let i++      		let i=i+1
[root@localhost ~]# i=10
[root@localhost ~]# let i++
[root@localhost ~]# echo $i
11

let i--        		let i=i-1
[root@localhost ~]# let i--
[root@localhost ~]# echo $i
10

let i+=2    		let i=i+2
[root@localhost ~]# let i+=2
[root@localhost ~]# echo $i
12

let i-=2     		let i=i-2
[root@localhost ~]# let i-=2
[root@localhost ~]# echo $i
10

let i*=2			let i=i*2
[root@localhost ~]# let i*=2
[root@localhost ~]# echo $i
20

let i/=2			let i=i/2
[root@localhost ~]# let i/=2
[root@localhost ~]# echo $i
10

let i%=2			let i=1%2
[root@localhost ~]# let i%=3
[root@localhost ~]# echo $i
1

字符串判断

  • -z #字符串的值为空为真
  • -n #字符串的值非空为真(相当于 ! -z)
#判断文件为空为真
[root@localhost ~]# [-z /etc/passwd]
bash: [-z: 未找到命令...

#判断时每一部分要有空格
[root@localhost ~]# [ -z /etc/passwd ]
[root@localhost ~]# echo $?
1

#判断文件非空为真
[root@localhost ~]# [ -n /etc/passwd ]
[root@localhost ~]# echo $?
0

[root@localhost ~]# [ -z $i ]
[root@localhost ~]# echo $?
1

[root@localhost ~]# [ -n $i ]
[root@localhost ~]# echo $?
0

[root@localhost ~]# [ ! -z $i ]
[root@localhost ~]# echo $?
0

条件判断结构

  • 当条件满足时执行什么操作,当条件不满足时执行什么操作
  • && #逻辑与(并且)
  • || #逻辑或(或者)
  • ; #条件之间没有逻辑关系
A && B  #当A命令执行成功后才会执行B,如果A执行失败则B不执行
#判断存在且是文件执行拷贝操作(并且关系)
[root@localhost ~]# [ -f /etc/passwd ] && cp /etc/passwd /opt
[root@localhost ~]# ls /opt
abc.tar.bz2  passwd

[root@thinkmo ~]# yum -y install vsftpd && systemctl start vsftpd && systemctl enable vsftpd && systemctl status vsftpd

#第一条命令执行失败,后边命令不执行
[root@localhost ~]# [ -f /etc/xxoo ] && cp /etc/passwd /opt
[root@localhost ~]# [ -f /etc/xxoo ] && cp /etc/xxoo /opt
[root@localhost ~]# ls /opt

A || B  #当A命令执行失败后才会执行B,如果A执行成功则B不执行
#前便命令执行失败,后边命令则执行
[root@localhost ~]# [ -f /opt/xxoo ] || touch /opt/xxoo.txt
[root@localhost ~]# ls /opt
abc.tar.bz2  passwd  xxoo.txt

#前边命令执行成功,后便命令则不执行
[root@localhost ~]# [ -f /etc/fstab ] || touch /opt/fs.txt
[root@localhost ~]# ls /opt

A ;  B  #执行A命令后执行B,两者没有逻辑关系
[root@localhost ~]# touch /mnt/xx.txt ; touch /opt/xx.txt
[root@localhost ~]# ls /mnt
centos  xx.txt
[root@localhost ~]# ls  /opt
abc.tar.bz2  abc.txt  fs.txt  pass.txt  passwd  xxoo.txt  xx.txt
[root@localhost ~]# touch /opt/oo.txt ; rm -rf /opt/*
[root@localhost ~]# ls /opt
[root@localhost ~]# touch /opt/oo.txt ; rm -rf /opt/* ; touch /opt/xx.txt ; rm -rf /mnt/xx.txt
[root@localhost ~]# ls /opt
xx.txt
[root@localhost ~]# ls /mnt/

if 条件判断结构

  • if 单分支语句,只能判断对,不能判断错
#第一种语法结构
if [条件判断];then
   条件成立时,执行的命令
fi

#第二种语法结构
if [条件判断]
  then
   条件成立时,执行的命令
fi

#if单分支示例
[root@localhost yunwei]# vim if1.sh 
#!/bin/bash
if [ -n /etc/passwd ];then
        echo "非空"
fi

[root@localhost yunwei]# chmod u+x if1.sh 
[root@localhost yunwei]# ./if1.sh 
非空

#只能判断对,不能判断错
[root@localhost yunwei]# vim if1.sh 
#!/bin/bash
if [ -z /etc/passwd ];then
        echo "非空"
fi
  • if 双分支语句
if [条件判断];then
     条件成立时,执行命令a
  else
     条件不成立时,执行命令b
fi

#if双分支示例
[root@localhost yunwei]# vim if2.sh 
#!/bin/bash
if [ -z /etc/passwd ];then
        echo '空值'
  else
        echo '非空'
fi

[root@localhost yunwei]# chmod u+x if2.sh 
[root@localhost yunwei]# ./if2.sh 
非空

#编写参数字的脚本,让计算机产生一个0-9随机数
#$RANDOM环境变量,里边存放的是0-65535之间的随机数
[root@localhost yunwei]# echo $RANDOM
28484
[root@localhost yunwei]# echo $RANDOM
5440
[root@localhost yunwei]# echo $RANDOM
29651
[root@localhost yunwei]# echo $RANDOM
21747
[root@localhost yunwei]# echo $RANDOM
24494

#实用$RANDOM的值对10取余
[root@localhost yunwei]# echo $[RANDOM%10]
4
[root@localhost yunwei]# echo $[RANDOM%10]
2
[root@localhost yunwei]# echo $[RANDOM%10]
5
[root@localhost yunwei]# echo $[RANDOM%10]
3
[root@localhost yunwei]# echo $[RANDOM%10]
9
[root@localhost yunwei]# echo $[RANDOM%10]
1
[root@localhost yunwei]# echo $[RANDOM%10]
0
[root@localhost yunwei]# echo $[RANDOM%10]
3
[root@localhost yunwei]# echo $[RANDOM%10]
2

#编写猜数字脚本
[root@localhost yunwei]# vim if3.sh
#!/bin/bash
read -p '请输入0-9之间的随机数:' num
num1=$[RANDOM%10]
if [ $num -eq $num1 ];then
        echo "恭喜你才对了,奖励一个哇塞女孩!"
 else
        echo "猜错了,请继续努力,奖品是一个哇塞女孩!"
        echo "正确的结果为$num1"
fi

[root@localhost yunwei]# chmod u+x if3.sh 
root@localhost yunwei]# ./if3.sh 
请输入0-9之间的随机数:1
猜错了,请继续努力,奖品是一个哇塞女孩!
正确的结果为6

[root@localhost yunwei]# ./if3.sh 
请输入0-9之间的随机数:7
猜错了,请继续努力,奖品是一个哇塞女孩!
正确的结果为3

[root@localhost yunwei]# ./if3.sh 
请输入0-9之间的随机数:3
猜错了,请继续努力,奖品是一个哇塞女孩!
正确的结果为2

[root@localhost yunwei]# ./if3.sh 
请输入0-9之间的随机数:0
猜错了,请继续努力,奖品是一个哇塞女孩!
正确的结果为5

[root@localhost yunwei]# ./if3.sh 
请输入0-9之间的随机数:9
猜错了,请继续努力,奖品是一个哇塞女孩!
正确的结果为2

[root@localhost yunwei]# ./if3.sh 
请输入0-9之间的随机数:5
猜错了,请继续努力,奖品是一个哇塞女孩!
正确的结果为7

#安装软件包脚本
root@localhost yunwei]# vim if4.sh 
#!/bin/bash
if [ `rpm -q vsftpd &> /dev/null ; echo $?` -eq 0 ];then
        systemctl start vsftpd
        systemctl enable vsftpd &> /dev/null
        echo "软件包以安装,并设置随机自启"
 else
        yum -y install vsftpd &> /dev/null
        systemctl start vsftpd
        systemctl enable vsftpd &> /dev/null
        echo "软件包以重新安装上,并设置随机自启"
fi

[root@localhost yunwei]# chmod u+x if4.sh 
[root@localhost yunwei]# ./if4.sh 
软件包以重新安装上,并设置随机自启
  • if 多分支语句
if [条件判断1];then
      条件1成立时,执行命令a
elif [条件判断2];then
      条件2成立时,执行命令b   
elif [条件判断3];then
      条件3成立时,执行命令c
...省略更多条件
else
      所有条件都不成立时,执行命令d
fi

#编写判断成绩脚本
[root@localhost yunwei]# vim if5.sh
#!/bin/bash
read -p "请输入你的成绩(满分为100分):" num
if [ $num -ge 90 ];then
        echo "成绩非常优秀!,奖励一个肤白貌美大长腿,绝世容颜哇塞女孩"
 elif [ $num -ge 80 ];then
        echo "比较优秀"
 elif [ $num -ge 70 ];then
        echo "一般一般"
 elif [ $num -ge 60 ];then
        echo "勉强及格"
else
        echo "收拾收拾,回家种地去吧!"
fi

[root@localhost yunwei]# chmod u+x if5.sh 
[root@localhost yunwei]# ./if5.sh 
请输入你的成绩:66
勉强及格
[root@localhost yunwei]# ./if5.sh 
请输入你的成绩:55
收拾收拾,回家种地去吧!
[root@localhost yunwei]# ./if5.sh 
请输入你的成绩:0
收拾收拾,回家种地去吧!
[root@localhost yunwei]# ./if5.sh 
请输入你的成绩:99
成绩非常优秀!,奖励一个肤白貌美大长腿,绝世容颜哇塞女孩
[root@localhost yunwei]# vim if5.sh
[root@localhost yunwei]# ./if5.sh 
请输入你的成绩(满分为100分):100
成绩非常优秀!,奖励一个肤白貌美大长腿,绝世容颜哇塞女孩
[root@localhost yunwei]# ./if5.sh 
请输入你的成绩(满分为100分):90
成绩非常优秀!,奖励一个肤白貌美大长腿,绝世容颜哇塞女孩
[root@localhost yunwei]# ./if5.sh 
请输入你的成绩(满分为100分):200
成绩非常优秀!,奖励一个肤白貌美大长腿,绝世容颜哇塞女孩

case条件判断结构

  • case从变量中取值,如果变量中的值与预设的值匹配,则执行对应的命令
#case语法结构
case $变量名 in
值1)
	执行的命令xx;;		#如果变量中的值等于值1,则执行的命令
值2)
	执行的命令yy;;		#如果变量中的值等于2,则执行的命令
...省略其他分支
*)
	执行的命令zz;;		#如果变量中的值都不是以上的值,则执行的命令
esac


[root@localhost yunwei]# vim case.sh
#!/bin/bash
read -p "请输入您喜爱的老师(仓老师|波多老师|小泽老师):" xxoo
case $xxoo in
仓老师)
        echo "又白又嫩又水润,上楼右转1号房间!";;
波多老师)
        echo "前凸后翘,波涛汹涌,上楼右转2号房间!";;
小泽老师)
        echo "肤白貌美大长腿,上楼右转3号房间!";;
*)
        echo "老师休假了";;
esac

[root@localhost yunwei]# chmod u+x case.sh 
[root@localhost yunwei]# ./case.sh 
请输入您喜爱的老师(仓老师|波多老师|小泽老师):仓老师
又白又嫩又水润,上楼右转1号房间!
[root@localhost yunwei]# ./case.sh 波多老师
请输入您喜爱的老师(仓老师|波多老师|小泽老师):波多老师
前凸后翘,波涛汹涌,上楼右转2号房间!
[root@localhost yunwei]# ./case.sh
请输入您喜爱的老师(仓老师|波多老师|小泽老师):小泽老师
肤白貌美大长腿,上楼右转3号房间!
[root@localhost yunwei]# ./case.sh
请输入您喜爱的老师(仓老师|波多老师|小泽老师):穆穆老师
老师休假了

for循环

  • for循环处理,根据变量的取值,重复执行xx命令
#for循环语法结构
for 变量名 in 值1 值2  值3 值N...
do
	执行的命令
done

#编写循环创建用户脚本
[root@localhost yunwei]# vim user.sh
#!/bin/bash
for user in xiaofang xiaowei jiumei alian
do
        useradd $user
        echo "$user 创建成功"
        echo 1 | passwd --stdin $user &> /dev/null
        echo "$user 密码设置成功,初始密码为“1”"
done

[root@localhost yunwei]# chmod u+x user.sh
[root@localhost yunwei]# ./user.sh 
useradd:用户“xiaofang”已存在
xiaofang 创建成功
xiaofang 密码设置成功,初始密码为“1”
xiaowei 创建成功
xiaowei 密码设置成功,初始密码为“1”
jiumei 创建成功
jiumei 密码设置成功,初始密码为“1”
alian 创建成功
alian 密码设置成功,初始密码为“1”

#测试企业的服务器联通性
#!/bin/bash
for i in `seq 254`
do
        ping -c2 -i0.1 -W1 192.168.0.$i &> /dev/null
  if [ $? -eq 0 ];then
        echo "192.168.0.$i UP" 
  else
        echo "192.168.0.$i DOWN" 
  fi
done

[root@localhost yunwei]# chmod u+x ping.sh
[root@localhost yunwei]# ./ping.sh 

#问题:如何将ping的命令结果存储到文件当中,正确的输出结果与错误的输出结果分别单独存储
#!/bin/bash
for i in `seq 254`
do
        ping -c2 -i0.1 -W1 192.168.0.$i >> /dev/null
        if [ $? -eq 0 ];then
           echo "192.168.0.$i UP" >> up.txt
        else
           echo "192.168.0.$i DOWN" >> down.txt
        fi
done

while循环

  • 死循环,只要条件成立就重复执行命令
#while循环语法结构
while 条件判断
do
	执行的命令
done

#编写while循环脚本
[root@localhost yunwei]# vim while.sh
#!/bin/bash
a=1
while [ $a -le 5 ]
do
echo $a
done

[root@localhost yunwei]# chmod u+x while.sh 

#指定循环的固定次数
[root@localhost yunwei]# vim while.sh
#!/bin/bash
a=1
while [ $a -le 5 ]
do
        echo $a
        let a++
        sleep 0.1
done

#使用while循环编写猜数字脚本
[root@localhost yunwei]# vim while1.sh 
#!/bin/bash
num=$[RANDOM%10]
while :
do
           read -p "请输入0-10之间的数字:" num1
        if [ $num -eq $num1 ];then
           echo "恭喜你才对了,奖励一个绝世容颜哇塞女孩!"
           exit  #退出脚本
         else
           echo "请继续努力,离哇塞女孩还差一步了,加油!"
        fi
done


#利用while循环监控网卡进出口流量
[root@localhost ~]# vim net_ens32.sh 
#!/bin/bash
while :
do
clear       #清屏
ifconfig ens32 | head -2      #显示网卡头两行信息
ifconfig ens32 | grep "RX p"  #网卡入口流量
ifconfig ens32 | grep "TX p"  #网卡出口流量
sleep 0.2   #休眠0.2秒
done


#使用while循环编写一个测试整个网段IP地址的联通性脚本
[root@localhost yunwei]# vim while_ping.sh 
#!/bin/bash
i=1  #定义一个变量
while [ $i -le 254 ] #循环判断变量的值小于等于254
do
        IP="192.168.0.$i"   #定义一个变量
        ping -c2 -i0.1 -W1 $IP &> /dev/null #输出结果不要
        if [ $? -eq 0 ];then    #判断上一条命令的结果,如果上一条命令的结果等于0
            echo "$IP UP"       #输出主机UP
        else
           echo "$IP DOWN"      #输出主机DOWN
        fi
   let i++       #对变量的值自加1 
done

shell函数

  • 在shell环境中,将一些需要重复使用的操作,定义为公共的语句块,即可称为函数(给一堆命令取一个别名)
  • 函数可以使脚本中的代码更加简洁,增强易读性,提高脚本的执行效率
#函数定义格式1
function 函数名 {
	执行的命令1
	执行的命令2
	...省略更多命令
}

#函数定义格式2
函数名() {
	执行的命令1
	执行的命令2
	...省略更多命令
}

#定义函数
[root@localhost ~]# net_ens32() {
> ifconfig ens32 | head -2
> ifconfig ens32 | grep "RX p"
> ifconfig ens32 | grep "TX p"
> }

#调用函数
[root@localhost ~]# net_ens32
ens32: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.0.100  netmask 255.255.255.0  broadcast 192.168.0.255
        RX packets 2337  bytes 178268 (174.0 KiB)
        TX packets 2686  bytes 467232 (456.2 KiB)

#定义函数
[root@localhost ~]# myinfo() {
> hostname
> cat /etc/redhat-release 
> uname -r
> free -h
> df -h /
> }

#调用函数
[root@localhost ~]# myinfo
localhost
CentOS Linux release 7.6.1810 (Core) 
3.10.0-957.el7.x86_64
              total        used        free      shared  buff/cache   available
Mem:           972M        393M        193M         13M        385M        374M
Swap:          2.0G          0B        2.0G
文件系统                 容量  已用  可用 已用% 挂载点
/dev/mapper/centos-root   56G  5.2G   51G   10% /

#fork炸弹
[root@localhost yunwei]# vim fork.sh 
#!/bin/bash
.() {
.|. &
}
.

[root@localhost yunwei]# chmod u+x fork.sh 
[root@localhost yunwei]# ./fork.sh 

脚本中断及退出

  • break #结束整个循环
  • continue #结束本次循环,进入下一次循环
  • exit #退出脚本
#结束第三次循环,进入下一次循环
#!/bin/bash
for i in {1..5}
do
        [ $i -eq 3 ] && continue
        echo $i
done
echo Over

[root@localhost yunwei]# ./for1.sh 
1
2
4
5
Over


#结束整个循环
#!/bin/bash
for i in {1..5}
do
        [ $i -eq 3 ] && break
        echo $i
done
echo Over

[root@localhost yunwei]# ./for1.sh 
1
2
Over

#直接退出脚本
[root@localhost yunwei]# vim for1.sh
#!/bin/bash
for i in {1..5}
do
        [ $i -eq 3 ] && exit
        echo $i
done
echo Over

[root@localhost yunwei]# ./for1.sh 
1
2

字符串截取

  • 在使用shell脚本完成各种运维任务时,一旦涉及到判断、条件测试等相关操作时往往需要对相关的命令输出进行过滤,提取出符合要求的字符串
  • 字符串截取的常用方法:$
  • ${}截取字符串时,起始位置是从0开始的
[root@localhost yunwei]# phone=13812345678
[root@localhost yunwei]# echo $phone
13812345678

#统计变量的个数
[root@localhost yunwei]# echo ${#phone}
11

#截取变量的前三位,在截取时包含数字本身
[root@localhost yunwei]# echo ${phone:0:3}
138

#截取后四位
[root@localhost yunwei]# echo ${phone:7:4}
5678

#截取中间四位
[root@localhost yunwei]# echo ${phone:3:4}
1234

#截取一个随机的8位密码
[root@localhost yunwei]# vim mima.sh
#!/bin/bash
x=qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM0123456789
for i in {1..8}
do
n=$[RANDOM%62]
p=${x:n:1}
pass=$pass$p
done
echo $pass

[root@localhost yunwei]# ./mima.sh 
42iVW9Ba
[root@localhost yunwei]# ./mima.sh 
XuEcVGoR

字符串替换

  • 只替换第一个匹配的结果:$
  • 替换全部匹配的结果:$
#只替换匹配到的第一个字符
[root@localhost yunwei]# echo $phone
13812345678

#将匹配到的第一个3替换成4
[root@localhost yunwei]# echo ${phone/3/4}
14812345678  

#将匹配到的所有3替换成4
[root@localhost yunwei]# echo ${phone//3/4}
14812445678

字符串掐头去尾

  • 从左向右,最短匹配删除:$
  • 从左向右,最长匹配删除:$
  • 从右向左,最短匹配删除:$
  • 从右向左,最长匹配删除:$
#定义素材
[root@localhost yunwei]# x=`head -1 /etc/passwd`
[root@localhost yunwei]# echo $x
root:x:0:0:root:/root:/bin/bash

#从左到右最短匹配
[root@localhost yunwei]# echo ${x#root}
:x:0:0:root:/root:/bin/bash

#从左到右最短匹配,不加*只匹配最左侧的字串
[root@localhost yunwei]# echo ${x#0}
root:x:0:0:root:/root:/bin/bash

#从左到右最短匹配,加*匹配遇到的第一个字串
[root@localhost yunwei]# echo ${x#*0}
:0:root:/root:/bin/bash

#从左到右最长匹配
[root@localhost yunwei]# echo ${x##0}
root:x:0:0:root:/root:/bin/bash

#从左到右最长匹配
[root@localhost yunwei]# echo ${x##*0}
:root:/root:/bin/bash

#从右到做最短匹配
[root@localhost yunwei]# echo ${x%/bash}
root:x:0:0:root:/root:/bin

#从右到做最短匹配
[root@localhost yunwei]# echo ${x%root*}
root:x:0:0:root:/

#从右向左最长匹配
[root@localhost yunwei]# echo ${x%%root*}

#从右向左最短匹配
[root@localhost yunwei]# echo ${x%0*}
root:x:0:

#从右向左最长匹配
[root@localhost yunwei]# echo ${x%%0*}
root:x:

#把文件以.doc结尾的扩展名,全部改为.txt
[root@localhost yunwei]# touch {1..100}.doc
[root@localhost yunwei]# ls
100.doc  17.doc  24.doc  31.doc  39.doc  46.doc  53.doc  60.doc  68.doc  75.doc  82.doc  8.doc   97.doc   if2.sh     while.sh
10.doc   18.doc  25.doc  32.doc  3.doc   47.doc  54.doc  61.doc  69.doc  76.doc  83.doc  90.doc  98.doc   if3.sh
11.doc   19.doc  26.doc  33.doc  40.doc  48.doc  55.doc  62.doc  6.doc   77.doc  84.doc  91.doc  99.doc   if4.sh
12.doc   1.doc   27.doc  34.doc  41.doc  49.doc  56.doc  63.doc  70.doc  78.doc  85.doc  92.doc  9.doc    if5.sh
13.doc   20.doc  28.doc  35.doc  42.doc  4.doc   57.doc  64.doc  71.doc  79.doc  86.doc  93.doc  case.sh  mima.sh
14.doc   21.doc  29.doc  36.doc  43.doc  50.doc  58.doc  65.doc  72.doc  7.doc   87.doc  94.doc  for1.sh  ping.sh
15.doc   22.doc  2.doc   37.doc  44.doc  51.doc  59.doc  66.doc  73.doc  80.doc  88.doc  95.doc  fork.sh  user.sh
16.doc   23.doc  30.doc  38.doc  45.doc  52.doc  5.doc   67.doc  74.doc  81.doc  89.doc  96.doc  if1.sh   while1.sh

#字符串去尾方式批量修改文件扩展名
[root@localhost yunwei]# vim file.sh 
#!/bin/bash
for i in `ls *.doc`
do
        mv $i ${i%doc}txt
done

#字符串替换方式批修改文件扩展名
[root@localhost yunwei]# vim file.sh 
#!/bin/bash
for i in `ls *.txt`
do
        mv $i ${i/txt/doc}
done

shell数组

#定义数组方式一:数组名=(值1 值2 值3 .. .. 值n)
[root@localhost yunwei]# x=(11 22 33 44 55 abc)
[root@localhost yunwei]# echo $x
11

#按照下标取值,下标从0起使,0就是数据内的第一个值
[root@localhost yunwei]# echo ${x[0]}
11
[root@localhost yunwei]# echo ${x[0]}
11
[root@localhost yunwei]# echo ${x[1]}
22
[root@localhost yunwei]# echo ${x[2]}
33
[root@localhost yunwei]# echo ${x[3]}
44
[root@localhost yunwei]# echo ${x[4]}
55

#获取数组内所有值
[root@localhost yunwei]# echo ${x[@]}
11 22 33 44 55 abc

#定义数组方式二:数组名[下标]=值
[root@localhost yunwei]# b[0]=aa
[root@localhost yunwei]# b[1]=xx
[root@localhost yunwei]# b[2]=xxoo
[root@localhost yunwei]# echo ${b[0]}
aa
[root@localhost yunwei]# echo ${b[1]}
xx
[root@localhost yunwei]# echo ${b[2]}
xxoo
[root@localhost yunwei]# echo ${b[@]}
aa xx xxoo
[root@localhost yunwei]# echo ${b[*]}
aa xx xxoo

posted on 2021-12-08 01:53  极客飞扬  阅读(154)  评论(0编辑  收藏  举报

导航