(七)学习笔记:shell基础

1.shell基础

1.1.解释器的基本操作

bash 解释器基本特性
Tab键补齐
历史命令 history
标准输入输出 > >> < << 2> &>
管道操作 |
我们常用的ls、cd等就是base shell。

1.2.重定向操作

在这里插入图片描述

1.3.什么是Shell

提前设计可执行语句用来完成特定任务的文件
解释型程序
顺序、批量执行

常见的shell种类
/bin/sh
/bin/bash
/usr/bin/sh
/usr/bin/bash
/sbin/nologin

1.4.Shell编写说明

1.开头
#!/bin/bash (环境声明)
#注释文本
可执行的代码
2.如何写好一个shell脚本
如何写好一个shell脚本?
1、明确任务需求按照自然语言拆分小步骤
2、按顺序整理好每一个步骤,先做什么,后做什么
3、每一步骤该怎么实现
4、运行脚本,并根据运行结果排除错误
5、优化脚本并达到最终效果

1.5.shell编写实例

1.利用vim编写新增tom用户
[root@test ~]# vim user.sh
#!/bin/bash
useradd tom
echo 1234 | passwd --stdin tom

vim useradd.sh
bash useradd.sh 
更改用户 tom 的密码 。
passwd:所有的身份验证令牌已经成功更新。

2.编写一个脚本查看当前信息
显示当前系统版本、内核信息、当前主机名、网卡IP地址
#!/bin/bash
cat /etc/redhat-release
uname -r
hostname
ifconfig ens160 | head -2

[root@localhost test]# vim info.sh
[root@localhost test]# bash info.sh 
Red Hat Enterprise Linux release 8.0 (Ootpa)
4.18.0-80.el8.x86_64
localhost.localdomain
ens160: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.1.102  netmask 255.255.255.0  broadcast 192.168.1.255

若使文件可直接执行

[root@localhost test]# chmod 744 info.sh 
[root@localhost test]# ./info.sh 
Red Hat Enterprise Linux release 8.0 (Ootpa)
4.18.0-80.el8.x86_64
localhost.localdomain
ens160: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.1.102  netmask 255.255.255.0  broadcast 192.168.1.255

特殊符号说明:

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

1.6.变量

什么是变量?
以固定名称存放可能会变化的值
提高脚本对任务的需求,运行环境变化的适应能力
方便在脚本中重复使用

定义变量
变量名=变量值
设置便往wangzhan为baidu,对比设置后与取消变量后的情况

wangzhan=www.baidu.com
ping $wangzhan
PING www.wshifen.com (104.193.88.123) 56(84) bytes of data.
64 bytes from 104.193.88.123 (104.193.88.123): icmp_seq=1 ttl=128 time=220 ms
64 bytes from 104.193.88.123 (104.193.88.123): icmp_seq=2 ttl=128 time=219 ms
64 bytes from 104.193.88.123 (104.193.88.123): icmp_seq=3 ttl=128 time=219 ms
64 bytes from 104.193.88.123 (104.193.88.123): icmp_seq=4 ttl=128 time=219 ms
^C
--- www.wshifen.com ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 534ms
rtt min/avg/max/mdev = 218.672/219.183/219.554/0.362 ms
unset wangzhan
ping $wangzhan
Usage: ping [-aAbBdDfhLnOqrRUvV64] [-c count] [-i interval] [-I interface]
            [-m mark] [-M pmtudisc_option] [-l preload] [-p pattern] [-Q tos]
            [-s packetsize] [-S sndbuf] [-t ttl] [-T timestamp_option]
            [-w deadline] [-W timeout] [hop1 ...] destination
Usage: ping -6 [-aAbBdDfhLnOqrRUvV] [-c count] [-i interval] [-I interface]
             [-l preload] [-m mark] [-M pmtudisc_option]
             [-N nodeinfo_option] [-p pattern] [-Q tclass] [-s packetsize]
             [-S sndbuf] [-t ttl] [-T timestamp_option] [-w deadline]
             [-W timeout] destination

1.7.read的使用

read标准输入取值
read 读取用户在键盘上输入的内容,并把内容存放在变量里
read 可以降低脚本的使用难度
—格式:read -p “提示信息” 变量名

1.8.变量的种类

1.环境变量
以不变的名称存放可能会变化的值,提高对任务需求、运行环境变化的适应能力
查看系统所有环境变量:env
查看系统所有变量包括用户自己定义的变量:set
USER
PATH
HISTSIZE
PWD
HOSTNAME
HOME

2.位置变量
位置变量的使用方法是在执行脚本时提供命令行的参数
$0
$1 #第一个参数
$2 #第二个参数
$3 #第三个参数
$4 #第四个参数
$n… #第n个参数

3.预定义变量
预定义变量用来保存脚本程序的执行信息
预定义变量的特点可以直接使用这些变量但不能直接为这些变量赋值
$0 #代表脚本本身
$* #显示所有参数内容
$# #显示有多少个参数
$$ #显示脚本进程号(PID)
$? #显示上一条命令的执行结果(0代表正确,非0代表错误)

4.自定义变量
自己定义,自己赋值。

1.9.条件测试

测试文件状态
常用测试选项:
-e 判断文档是否存在,存在为真
-d 判断目录是否存在,存在为真
-f 判断文件是否存在,存在为真
-r 可读为真
-w 可写为真
-x 可执行为真

[root@localhost backup]# [ -e /etc/passwd ]
[root@localhost backup]# echo $?
0

判断文件/etc/passwd存在。

1.10.整数比较

比较整数大小
常用选项:
-gt 大于
-ge 大于等于
-eq 等于
-lt 小于
-le 小于等于
-ne 不等于

[ 9 -ge 9  ]
echo $?
0

总结来说:greater than大于、less than小于、equal等于、not equal不等于

1.11.字符串比较

字符串比较
== 相等
!= 不相等

[ $USER == root ]
echo $?
0

-z 字符串的值为空为真
-n 字符串的值不为空为真(相当于 ! -z)

[ -z /etc/passwd ]
echo $?
1

2.数值运算

2.1.常用的数值运算方式

[ ] 整 数 运 算 特 点 : 运 算 符 两 侧 可 以 无 空 格 引 用 变 量 可 省 略 []整数运算特点: 运算符两侧可以无空格 引用变量可省略 []符号
计算结果替换表达式本身,可结合echo命令输出
格式:$[整数1 运算符 整数2… …]

temp1=10
echo $[temp1+1]
11

使用$[] 或者 let 命令来完成
结合echo命令查看结果
在这里插入图片描述

let temp1=temp1+2;echo $temp1
12

2.2.逻辑分隔结构

主要用法:
1.命令条件下
命令1 操作符 命令2 … …
&&给定条件成立,结果才为真。与
||只要其中一个条件成立,就为真。或
2.[ 条件1 ] 操作符 [ 条件2 ] … …
A && B #仅当A命令执行成功,才执行B命令
A || B #仅当A命令执行失败,才执行B命令
A ; B #执行A命令后执行B命令,两者没有逻辑关系

2.3.作业练习

编写一个脚本,在每周五 3:00 备份 /var/log/目录下所有日志

vim log_all.sh
//键入:#!/bin/bash
//tar -czf log-`date +%Y%m%d`.tar.gz  /var/log/*.log
chmod +x log_all.sh 
crontab -e
//键入:00 3 * * 5  /root/log_all.sh
no crontab for root - using an empty one
crontab: installing new crontab

2.4.if单分支结构

单分支:当条件满足时,做xxx处理
if 条件测试;then
命令序列xxx
fi

2.5.if 双分支

if 双分支处理:当条件满足/不满足时,分别做xxx操作
if 条件测试 ;then
命令序列xxx
else
命令序列yyyy
fi

练习1:
编写SupeiUser.sh;测试登录的用户是否为root
脚本内容:

#!/bin/bash
if [ $USER = root ];then
        echo "this is sbin"
else
        echo "this is bin"
fi

运行结果:

bash SuperUser.sh 
this is sbin

bash说明:
bash -n测试语法是否正确。
bash -x进入调试模式,在遇到问题后输出错误行信息并结束运行。

练习2:
利用RANDOM变量编写一个随机产生0~9之间的随机数脚本让用户猜
如果用户猜对了则输出一句恭喜您猜对了,如果猜错了则输出猜错了

写入RandomNumber.sh,猜测数字
#!/bin/bash
read -p “请输入0到9之间的一个数字:” num1
num2=$[RANDOM%10]
if [ $num1 -eq n u m 2 ] ; t h e n e c h o “ 恭 喜 您 猜 对 了 ” e l s e e c h o “ 猜 错 了 ” e c h o " 正 确 的 结 果 为 num2 ];then echo “恭喜您猜对了” else echo “猜错了” echo "正确的结果为 num2];thenechoelseechoecho"num2"
fi

运行代码:

vim RandomNumber.sh
bash RandomNumber.sh 
请输入0到9之间的一个数字:9
“猜错了”
正确的结果为1

2.6.if 多分支处理

当条件1满足时,做aa动作,判断结束
如果条件1不满足则继续检查条件2,如果条件2满足,做bb动作,判断结束
如果条件2还不满足,继续检查条件3,如果条件3满足,做cc动作,判断结束
如果条件3还不满足,则执行dd动作,判断结束

if 条件测试1;then
命令序列aa
elif 条件测试2;then
命令序列bb
elif 条件测试3;then
命令序列cc
else
命令序列dd
fi
练习3:
利用 if 多分支编写一个考试成绩脚本
利用read 获取用户在键盘输入的分数判断成绩
如果分数大于60分则输出及格
如果分数大于70分则输出良好
如果分数大于80分则输出优秀
如果分数大于90分则输出非常优秀
如果以上条件都不满足则输出仍需努力
键入:
#!/bin/bash
read -p “请输入您的成绩:” 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 test]# vim ExamGrade.sh
[root@localhost test]# bash ExamGrade.sh 
请输入您的成绩:66
及格

2.7.for循环结构

for 循环处理
遍历/列表式循环
根据变量的不同取值,重复执行xx处理
for 变量名 in 值列表
do
循环的操作
done

练习4
利用for循环实现一个批量创建用户并设置密码的脚本
编写脚本:
#!/bin/bash
for user in xiaoming xiaozhang lixaoli dahuang laowang
do
useradd $user
echo 123456 | passwd --stdin u s e r e c h o " user echo " userecho"user创建成功"
done
编写并运行:

[root@localhost test]# vim BatchAdmin.sh
[root@localhost test]# bash BatchAdmin.sh 
更改用户 xiaoming 的密码 。
passwd:所有的身份验证令牌已经成功更新。
xiaoming创建成功
更改用户 xiaozhang 的密码 。
passwd:所有的身份验证令牌已经成功更新。
xiaozhang创建成功
更改用户 lixaoli 的密码 。
passwd:所有的身份验证令牌已经成功更新。
lixaoli创建成功
更改用户 dahuang 的密码 。
passwd:所有的身份验证令牌已经成功更新。
dahuang创建成功
更改用户 laowang 的密码 。
passwd:所有的身份验证令牌已经成功更新。
laowang创建成功

练习4:
检测并判断指定的主机是否可ping通,ping10次
脚本参考:-c 发送的数据包 -i 测试时间间隔 -W 等待反馈的超时秒数
#!/bin/bash
for i in {1…10}
do
ping -c 3 -i 0.2 -W 3 $1 &> /dev/null
if [ $? -eq 0 ];then
echo “Host $1 is up”
else
echo “Host $1 is down”
fi
done

[root@test ~]# chmod +x ping.sh 
[root@localhost test]# bash PingHost.sh 192.168.1.254
Host 192.168.1.254 is up
Host 192.168.1.254 is up
Host 192.168.1.254 is up
Host 192.168.1.254 is up
Host 192.168.1.254 is up
Host 192.168.1.254 is up
Host 192.168.1.254 is up
Host 192.168.1.254 is up
Host 192.168.1.254 is up
Host 192.168.1.254 is up

2.8.while循环

语法结构及特点
条件式循环:反复测试条件,只要条件成立就执行命令序列

格式:
while 条件测试
do
命令序列
done

练习5:死循环,每执行一次输出”1“并延时1s
编写脚本
#!/bin/bash
i=1
while [ $i -le 5 ]
do
echo $i
sleep 1
done
执行:

[root@localhost test]# vim WhileLoop.sh
[root@localhost test]# bash WhileLoop.sh 
1
1
1
1
1
1
1
^C

死循环需要按ctrl+c结束运行。

练习6:
使用系统自带变量RANDOM提取随机数,使用while :制作死循环

编写脚本:
#!/bin/bash
num2=$[RANDOM%10]
while :
do
read -p “请输入0到9之间的一个数字:” num1
if [ $num1 -eq $num2 ];then
echo “恭喜您猜对了"
exit
else
echo “请继续努力!”
fi
done
执行:

[root@localhost test]# vim RandomLoop.sh
[root@localhost test]# bash RandomLoop.sh 
请输入0到9之间的一个数字:0
请继续努力!
请输入0到9之间的一个数字:1
请继续努力!
请输入0到9之间的一个数字:2
请继续努力!
请输入0到9之间的一个数字:3
恭喜您猜对了

练习7:
利用while 循环检测192.168.0.0/24网段,列出不在线的主机地址
编写脚本:
#!/bin/bash
i=1
while [ i − l e 245 ] d o I P = " 192.168.0. i -le 245 ] do IP="192.168.0. ile245]doIP="192.168.0.i"
ping -c2 -i0.2 -W1 $IP &> /dev/null
if [ $? -eq 0 ];then
echo “HOST $IP is UP”
else
echo “HOST $IP is down”
fi
let i++
done
执行:

bash IPALL.sh 
HOST 192.168.0.1 is down
HOST 192.168.0.2 is down
...
HOST 192.168.0.244 is down
HOST 192.168.0.245 is down

2.9.case语句

语法结构及特点
检查变量的实际取值,如果与预设的值相匹配,则执行对应的操作
case 分支语法结构:
case 变量值 in
模式1)
命令序列1;;
模式2)
命令序列2;;
… …
*)
默认命令序列
esac
练习8:
判断用户输入的内容和case变量值进行对比
编写代码:
#!/bin/bash
case $1 in
redhat)
echo “红帽系列企业版”;;
centos)
echo “centos社区企业版”;;
*)
echo “请输入centos或redhat!”;;
esac
执行:

vim CaseSystem.sh
bash CaseSystem.sh 
请输入centos或redhat!
bash CaseSystem.sh centos
centos社区企业版

3.函数的用法

3.1.关于函数

关于函数的认识
什么是函数?
— 在shell环境中,将一些需要重复使用的操作,定义为公共的语句块,即可成为函数

使用函数的好处?
— 使脚本代码更简洁,增强易读性
— 提高shell脚本的执行效率

3.2.函数定义格式

函数的定义格式1:

function 函数名 {
命令序列
… …
}

函数的定义格式2:

函数名() {
命令序列
… …
}

3.3.函数相关语句

3.3.1.中断及退出

对比break、continue、exit在for语句中的执行效果。
break结束整个循环

[root@localhost test]# vim InteraputExit.sh
#!/bin/bash
for i in {1..5}
do
        [ $i -eq 3 ] && break
                echo $i
        done
echo over

[root@localhost test]# bash InteraputExit.sh 
1
2
over

continue结束本次循环,进入下一次循环

[root@localhost test]# vim InteraputExit.sh
#!/bin/bash
for i in {1..5}
do
        [ $i -eq 3 ] && continue
                echo $i
        done
echo over

[root@localhost test]# bash InteraputExit.sh 
1
2
4
5
over

exit退出脚本

[root@localhost test]# vim InteraputExit.sh
#!/bin/bash
for i in {1..5}
do
        [ $i -eq 3 ] && exit
                echo $i
        done
echo over

[root@localhost test]# bash InteraputExit.sh 
1
2

3.3.2.字符串处理

使用shell完成各种Linux运维任务时,一旦涉及到判断、条件测试等相关操作时往往需要对相关的命令输出进行过滤,提取出符合要求的字符串
1.字符串截取
字符串截取的常用方法:${变量名:起始位置:长度}
${}截取字符串时,起始位置是从0开始的

[root@test ~]# x=12345678912
[root@test ~]# echo ${x:0:3}
123


2.字符串的拼接
无符号,直接连接

```bash
[root@localhost test]# a=rh
[root@localhost test]# b=el
[root@localhost test]# echo $a$b
rhel

3.字符串的替换
字符串替换的常用方法:
— 只替换第一个匹配的结果: 变 量 名 / x x / y y — 替 换 全 部 匹 配 结 果 : {变量名/xx/yy} — 替换全部匹配结果: /xx/yy{变量名//xx/yy}
[root@test ~]# echo $phone
13838383888
[root@test ~]# echo ${phone/3/4}
14838383888 #替换匹配到的第一个结果

[root@test ~]# echo KaTeX parse error: Expected 'EOF', got '#' at position 26: …x} 1x8x8x8x888 #̲替换匹配到的所欲结果 4.字符…{变量名#关键词}
从左向右,最长匹配删除:KaTeX parse error: Expected '}', got '#' at position 5: {变量名#̲#*关键词} 从右向左,最短匹…{变量名%关键词
}
从右向左,最长匹配删除:${变量名%%关键词*}

x=$(cat /etc/passwd | head -1)
echo $x
root:x:0:0:root:/root:/bin/bash	#初始值
echo ${x#root}
:x:0:0:root:/root:/bin/bash
echo ${x##*root}
:/bin/bash

4.查看字符串的长度

echo ${#phone}
11
echo ${#phone}#查看phone变量的字符长度。

5.大小写转换

phone=xiaoxieDAXIE
#小写转大写
echo ${phone^^}
XIAOXIEDAXIE
#大写转小写
echo ${phone,,}
xiaoxiedaxie

6.数组输入并循环输出

array=(11 22 33 44 00 xx)
for i in ${array[*]}
> do echo $i
> done
11
22
33
44
00
xx

3.4.declare用法

1.概念
declare命令用于声明和显示已存在的shell变量。当不提供变量名参数时显示所有shell变量。declare命令若不带任何参数选项,则会显示所有shell变量及其值。declare的功能与typeset命令的功能是相同的。
2.语法
declare(选项)(参数)
3.相关选项:
-p:查看变量的被声明的类型
-i:将变量声明为整型
-a:将变量声明为数组型
-r:将变量声明为只读变量
-x:将变量声明为环境变量
+x:取消声明为环境变量
-:给变量设置类型属性
+:取消变量的类型属性

3.5.正则表达式

基本正则表达式
在这里插入图片描述

1."."代表任意字符

cat /etc/passwd |grep 100.
games:x:12:100:games:/usr/games:/sbin/nologin
txy:x:1000:1000:txy:/home/txy:/bin/bash
www:x:1001:1001::/home/www:/sbin/nologin
mysql:x:1002:1002::/home/mysql:/sbin/nologin
tom:x:1003:1003::/home/tom:/bin/bash
xiaoming:x:1004:1004::/home/xiaoming:/bin/bash
xiaozhang:x:1005:1005::/home/xiaozhang:/bin/bash
lixaoli:x:1006:1006::/home/lixaoli:/bin/bash
dahuang:x:1007:1007::/home/dahuang:/bin/bash
laowang:x:1008:1008::/home/laowang:/bin/bash

测试passwd中可以发现,只要有100的都筛选出来了
2.“[]”匹配中括号中的任意字符

[root@localhost test]# cat /etc/passwd |grep [root]
#筛选出包含中括号中任意字符的所有行
[root@localhost test]# cat /etc/passwd |grep [^root]
#^代表取反,除了这四个字符的所有行

ps:^ [[:space:]]*$为空格
3.筛选行尾位bash的所有行

cat /etc/passwd |grep bash$
root:x:0:0:root:/root:/bin/bash
txy:x:1000:1000:txy:/home/txy:/bin/bash
tom:x:1003:1003::/home/tom:/bin/bash
xiaoming:x:1004:1004::/home/xiaoming:/bin/bash
xiaozhang:x:1005:1005::/home/xiaozhang:/bin/bash
lixaoli:x:1006:1006::/home/lixaoli:/bin/bash
dahuang:x:1007:1007::/home/dahuang:/bin/bash
laowang:x:1008:1008::/home/laowang:/bin/bash

3.6.egrep过滤工具

文本处理顺序
以行为单位,逐行进行处理
默认只输出与表达式相匹配的文本行

基本用法
— 格式1:egrep 选项 ‘正则表达式’ 文件… …
— 格式2:前置命令 | egrep 选项 ‘正则表达式’

3.7.练习

练习1:循环查看网络流量信息

[root@localhost function]# NetworkMonitor(){
> ifconfig ens160 |head -2
> ifconfig ens160 |grep "TX p"
> ifconfig ens160 |grep "RX p"
> }`在这里插入代码片`
[root@localhost function]# NetworkMonitor 
ens160: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.1.102  netmask 255.255.255.0  broadcast 192.168.1.255
        TX packets 4655  bytes 497754 (486.0 KiB)
        RX packets 16980  bytes 19472742 (18.5 MiB)

练习2:shell版folk炸弹
shell版fork炸弹
— 仅13个字符:.(){ .|. &};.
— 递归死循环,可逊色耗尽系统资源

#!/bin/bash
.(){ #定义一个名为 . 的函数
.|. & #在后台递归调用函数 .
}
. #再次调用函数

练习3:抓取IP地址

[root@localhost test]# vim GrepIP.sh
#!/bin/bash
x=$(ifconfig ens160 |grep inet |head -1)
echo ${x:12:16}
~                                  
[root@localhost test]# bash GrepIP.sh 
192.168.1.102

练习4:随机生成8位密码

[root@localhost test]# vim CatPasswd.sh
#!/bin/bash
x=opasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890
pass=""
for i in {1..8}
do
        n=$[RANDOM%62]
        tmp=${x:n:1}
        pass=$pass$tmp
done
echo $pass

[root@localhost test]# bash CatPasswd.sh 
pjF9ERZg
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值