作者主页
目录
为什么要学习Shell?
1、什么是Shell
Shell是一种用户使用的解释型程序,它是操作系统的一部分,派生自多种不同的系统。它是一种命令解释器,它可以读取用户的输入,解释该输入,并执行相应的命令。 Linux的Shell有很多种,如bash,csh,ksh等。当前常用的为bash
2、Shell 的特性
(1)交互式:用户可以通过Shell的界面实现与计算机的交互,以便用户和计算机之间的信息交换。
(2)自动化: Shell 可以将用户编写的一系列命令,保存为脚本,并在需要的时候自.动执行,以减少用户的工作量。
(3)扩展性: Shell 可以实现过滤和管道功能,可以与其他应用程序和编程语言结合使用,实现不同应用程序、不同编程语言之间的信息传递
#!/bin/bash #shell脚本应以此开头 chmod +x test.sh #新脚本完成后需要给予运行权限
#脚本运行方法 ./test.sh #用户身份执行 /sh/test.sh #用户身份执行 sh test.sh #管理员身份执行 source test.sh #管理员身份执行 . test.sh #管理员身份执行
shell变量概述
变量是shell传递数据的一种方法,即用一个固定的字符串去表示不固定的值,便于后期引用
变量使用
a=34 #将固定字符a表示为34 echo $a #返回a 34 #返回的执行结果 name="zhangsan" #定义变量 age=19 #定义变量 score=90 #定义变量 id=1 #定义变量 info="ID:$id Name:$name Age:$age Score:$score" #在变量中引用变量 eccho $info #返回info ID:1 Name:zhangsan Age:19 Score:90 #返回结果 time=$(date +%F) #变量中套用命令 echo $time #返回time 2023-07-25 #返回的执行结果
变量定义方式
- 用户自定义变量:人为定义变量
- 系统环境变量:系统操作环境相对自带的
- 位置参数变量:向脚本传递参数的变量
- 预定义变量:bash定义好的变量
1.变量名不能出现"-",有空格时需要用引号括起来
var=“hello word”
2.引用变量,$+变量名或者${变量名}
id=1 #定义变量 info="ID:$id" #引用id变量 name=zhangsan #定义name变量 echo "${name}_is" #引用name变量时后缀加_is zhangsan_is #返回结果 例: id=1 name=zhangsan age=19 score=90 student="ID:${id}姓名:${name}年龄:${age}成绩:${score}" echo $student ID:1姓名:zhangsan年龄:19成绩:90
截取
ifconfig ens33|head -2|tail -1|awk '{print $2}' #截取ip df -hT|head -7|tail -1|awk '{print $6}' #截取硬盘使用百分比 used *100 / buff/cache #内存占比公式定义为变量时双嵌套 mem=$((used *100 / buff/cache)) #计算
查看变量
set |grep ip
清除变量
unset ip
引用变量,双引号属于弱引用取变量的值,单引号属于强引用原封不动引用变量
echo "$var hello china" #需要引用变量值 echo '$var hello china' #只想引用变量名,不执行$特殊符号 echo "$var hello china \$SHELL" #部分变量执行,部分变量不执行
变量嵌套
aa=$(rpm -e $(rpm -qa|grep java)) #将由里向外运行命令
开启新shell 全局变量
bash #开启一个新的shell,之前设定的所有局部变量将清空 export ip=$(ifconfig ens33|head -2|tail -1|awk '{print $2}') #变量前加export时变量变为全局变量可在多个shell中使用,不加时默认为局部变量
系统环境变量
echo $PATH #PATH路径,系统命令查找路径 /usr/local/bin:/usr/local/sbin:/usr/bin:usr/sbin #PATH返回结果 export PATH=${PATH}:/sh #在PATH中添加路径(重启丢失) echo "export PATH=${PATH}:/sh" >> /etc/profile #永久追加路径 echo "宿主目录: $HOME" echo "当前目录: $PWD" echo "主机名: $HOSTNAME" echo "客户端地址和端口: $SSH_CONNECTION"
位置参数
vim variable.sh #!/bin/bash echo "当前shell脚本的文件名:$0" echo "第1个shell脚本位置参数:$1" echo "第2个shell脚本位置参数:$2" echo "第3个shell脚本位置参数:$3" echo "第10个shell脚本位置参数:${10}"
例:
vi test.sh #!/bin/bash echo $(($1 + $2)) # ./test.sh 34 56 #34即为$1 56即为$2 90 #返回的值
vi test.sh #!/bin/bash echo $1 echo $2 echo $3 echo $4 echo $5 # ./test.sh 23 34 45 23 #返回的值 34 #返回的值 45 #返回的值
预定义变量
echo $* #所有传递的位置参数: echo $@ #所有传递的位置参数: echo $# #共传递的参数数量 echo $$ #当前程序运行的PID: echo $? #返回上一个命令执行的返回结果为0时代表上一个命令成功其他为错误
例
vi test.sh #!/bin/bash echo $* echo $@ # ./test.sh 2 34 535 54 35 345 2 34 535 54 35 345 #返回的值所有传递的位置参数 2 34 535 54 35 345 #返回的值所有传递的位置参数 vi test.sh #!/bin/bash echo $# # ./test.sh 2 34 535 54 35 345 6 #返回的值总共传递的参数数量 vi test.sh #!/bin/bash echo $$ # ./test.sh 6667 #返回的值脚本本身pid
shell变量赋值
例:read -p 交互方式变量赋值
vi test.sh #!/bin/bash read -p "请输入第一个值:" num1 read -p "请输入第二个值:" num2 sum=$((num1 + num2)) echo "$num1 + $num2 = $sum" #执行以上脚本 ./test.sh 请输入第一个值:4 #返回结果 请输入第二个值:8 #返回结果 4 + 8 = 12 #返回结果
&> #混合输出将覆盖原文件的信息,&>>将追加至源文件信息后
ping -w1 -c1 baidu.com &> file cat file PING baidu.com (110.242.68.66) 56(84) bytes of data. #file文件信息 64 bytes from 110.242.68.66 (110.242.68.66): icmp_seq=1 ttl=128 time=21.5 ms #file文件信息 #file文件信息 --- baidu.com ping statistics --- #file文件信息 1 packets transmitted, 1 received, 0% packet loss, time 0ms #file文件信息 rtt min/avg/max/mdev = 21.571/21.571/21.571/0.000 ms #file文件信息 ping -c1 -w1 www.baidu.com &> /dev/null #/dev/null为系统自带垃圾箱,放此后会删除 echo $? #返回上一个命令执行的返回结果 0 0为真其他为假
if比较
-e 文件名 如果文件存在则为真
-r 文件名 如果文件存在且可读则为真
-w 文件名 如果文件存在且可写则为真
-x 文件名 如果文件存在且可执行则为真
-s 文件名 如果文件存在且至少有一个字符则为真
-d 文件名 如果文件存在且为目录则为真
-f 文件名 如果文件存在且为普通文件则为真
-c 文件名 如果文件存在且为字符型特殊文件则为真
-b 文件名 如果文件存在且为块特殊文件则为真
= 等于则为真
!= 不相等则为真
-z 字符串 字符串的长度为零则为真
-n 字符串 字符串的长度不为零则为真
-eq 等于则为真
-ne 不等于则为真
-gt 大于则为真
-ge 大于等于则为真
-lt 小于则为真
-le 小于等于则为真
例
vi read3.sh #!/bin/bash read -p "请输入需要检测的ip地址:"IP ping -w1 -c1 ${IP} &> /dev/null #-c指定包的数量,-w为等待时间秒为单位 &>:混合输出至 #/dev/null:系统自带垃圾箱 if [ $? -eq 0 ];then #if [];then 条件,then满足时返回 #$? -eq 0 $?返回的值等于0 echo "${IP} 可以通信" #满足$? -eq 0时返回 else #不满足上面条件时 echo "${IP} 无法通信" fi
for循环
for 将要使用的变量名 in 一个数列
do
要做的事情
done
#!/bin/bash read -p "请输入网段:" IP for i in {1..254} do ping -c 1 -w 1 ${IP}.${i} &> /dev/null if [ $? -eq 0 ];then echo -e "\033[32m ${IP}.${i}可以通信 \033[0m" else echo -e "\033[31m ${IP}.${i}无法通信 \033[0m" fi done
脚本题
在每月第一天备份并压缩/etc目录的所有内容,放到/backup,备份文件以时间戳命名。 (1) 备份目录在哪,/backup (2) 备份目标是谁,/etc (3) 命令,tar (4) 时间戳命名,$(date +%F)
变量替换
url="www.baidu.com" echo $url www.baidu.com #返回的值 echo ${url#*.} baidu.com #返回的值 ${变量#匹配规则} #从头开始匹配,最短删除 ${变量##匹配规则} #从头开始匹配,最长删除 ${变量%匹配规则} #从尾开始匹配,最短删除 ${变量%%匹配规则} #从尾开始匹配,最长删除 ${变量/旧字符串/新字符串} #替换字符串,仅替换第一个 ${变量//旧字符串/新字符串} #替换字符串,替换全部
例1:从前往后删变量内容
Qh_url=mirrors.tuna.tsinghua.edu.cn echo $Qh_url #直接返回变量 echo ${Qh_url#*.} #删除.分隔的第一个字段 echo ${Qh_url##*.} #仅保留最后一个字段
例2:从后往前删变量内容
Qh_url=mirrors.tuna.tsinghua.edu.cn echo $Qh_url echo ${Qh_url%.*} #删除最后一个字段 echo ${Qh_url%%.*} #仅保留第一个字段
例3:变量内容替换
Qh_url=mirrors.tuna.tsinghua.edu.cn echo $Qh_url echo ${Qh_url/u/U} #替换从左往右第一个 echo ${Qh_url//u/U} #替换所有
shell变量运算
1.整数运算,expr、$(())、$[],不支持小数运算
a+b 加 a-b 减 a*b 乘(expr计算时,用 \ *) a/b 除 a%b 余
例1:
#只能进行整数之间的运算 a=20 b=10 #运算方式 expr $a + $b echo $(( $a + $b )) echo $[ $a + $b ]
例2:递增和递减
#每运行一次对应的数值就加1 echo $((a++)) echo $((a--)) echo $((++b)) echo $((--b)) echo $((100*(1+100)/2)) 求1到100之和
脚本题: 例:查看内存使用率,仅保留整数
#!/bin/bash Mem_use=$(free -m |grep ^M |awk '{print $3/$2*100}') if [ ${Mem_use%.*} -ge 80 ];then # -ge 大于等于 echo "memory is overfull: ${Mem_use%.*}%" else echo "memory is OK: ${Mem_use%.*}%" fi
例:查看磁盘使用状态,使用率超出80%就报警 思路: 怎么查看磁盘 怎么提取使用率 整数判断
#!/bin/bash Disk=$(df -h |grep /$ |awk '{print $(NF-1)}') #NF代表列的数量 if [ ${Disk%\%} -ge 80 ];then echo "你的磁盘使用率过高:$Disk" else echo "你的磁盘使用率正常:$Disk" fi