一、shell概述
1、shell概念
(1)shell 英文翻译过来是外壳的意思,作为计算机语言来理解可以认为它是操作系统的外壳。可以通过shell 命令来操作和控制操作系统,比如Linux中的shell命令就包括 ls、cd、pwd 等等。
(2)shell 在内核的基础上编写的一个应用程序,它连接了用户和 Linux 内核,从而让用户能够更加便捷、高效、安全的使用 linux 内核,这其实就是 shell 的本质。
(3)使用专业术语的说法来解释,Shell 其实是一个命令解释器,它通过接受用户输入的 Shell 命令来启动、暂停、停止程序的运行或对计算机进行控制。
2、shell脚本
shell脚本就是由Shell命令组成的执行文件,将一些命令整合到一个文件中,进行处理业务逻辑,脚本不用编译即可运行,它从一定程度上减轻了工作量,提高了工作效率,还可以批量、定时处理主机,方便管理员进行设置或者管理。
3、shell脚本编写注意事项
(1)shell命名: shel脚本名称命名一般为英文、大写、小写、后缀以.sh结尾
(2)不能使用特殊符号、空格**
(3)名称要写的一眼可以看出功能,也就是顾名思义
(4)shell脚本首行需要#!/bin/bash开头
(5)shell脚本变量不能以数字、特殊符号开头,可以使用下划线,但不能用破折号
4、编写shell脚本
(1)hello world 脚本
vim hello.sh #编辑脚本
#!bin/bashecho "hello world"
ls -lh /etc/bash hello.sh
运行脚本的命令有以下五条:
bash hello.sh
sh hello.sh
source hello.sh #在当前进程里面执行
chmod +x hello.sh
./hello.sh
(2)nginx安装脚本
[root@shell ~]# vim nginx.sh
#!/bin/bash
yum -y install gcc gcc-c++ make pcre-devel openssl-devel wget
cd /usr/local/src/
wget 'https://nginx.org/download/nginx-1.26.1.tar.gz'
tar -xf nginx-1.26.1.tar.gz
cd nginx-1.26.1
./configure --prefix=/usr/local/nginx
make -j 4
make install[root@shell ~]# sh nginx.sh
#逻辑顺序:先安装依赖关系,再进入到系统默认的安装包目录src,使用wget命令从网上下载nginx1.26.1版本的安装包,然后解压,再移动到 nginx 安装月录,执行编译安装(预配置
6、变量
(1)自定义变量
由用户自己定义、使用和修改。
[root@shell ~]# a=1314
[root@shell ~]# b=520
[root@shell ~]# echo $a $b
1314 520
[root@shell ~]# echo $a$b
1314520
(2)环境变量
由系统维护,用于设置工作环境
$PWD
$SHELL
$USER$PATH
[root@shell ~]# env #查看所有的环境变量
[root@shell ~]# echo $PWD
/root
[root@shell ~]# echo $SHELL
/bin/bash
[root@shell ~]# echo $USER
root
[root@shell ~]# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
(3)位置变量
通过命令行给脚本程序传递参数(也属于预定义变量)为了在使用Shel脚本程序时,方便通过命令行为程序提供操作参数Bash引入了位置变量的概念位置变量有0,n,n为1~9之间的数字
$0:第一个字段表示命令名或脚本名称
$1:脚本要处理的第一个参数$2:脚本要处理的第二个参数
shell脚本最多可以执行九个参数
[root@shell ~]# vim createacc
#!/bin/bash
useradd $1
echo $2|passwd --stdin $1
[root@shell ~]# bash createacc zzz zzzz
更改用户 zzz 的密码 。
passwd:所有的身份验证令牌已经成功更新。
(4)预定义变量
Bash中内置的一类变量,不能直接修改
预定义变量是Bash程序预先定义好的一类特殊变量,用户只能使用预定义变量,而不能创建新的预定义变量,也不能直接为预定义变量赋值。害光。将所有参数作为整体
$@:单个参数的组合,每个参数占一行
$0:保存了脚本名称
$?:保存命令或脚本的执行状态码
$#:保存脚本要处理的参数的个数
[root@shell ~]# vim sh001.sh
#!/bin/bash
#将所有的脚本参数输出到终端
for x in "$*"
do
echo $x
done[root@shell ~]# bash sh001.sh 1 3 5 a b c
1 3 5 a b c[root@shell ~]# vim sh001.sh
#!/bin/bash
#将所有的脚本参数输出到终端
for x in "$*"
do
echo $x
doneecho $?
echo $#
echo $0[root@shell ~]# bash sh001.sh 1 3 5 a b c
1 3 5 a b c
0
6
sh001.sh
二、判断语法
(一)条件判断
shell返回值:运行一条命令,都会有一个返回值。0代表执行正常,非0代表命令执行异常
(二)if条件语句
1、if单分支语句
if 条件判断 ; then条件成 ⽴ 执 ⾏ 的命令 ( 可以有多个命令,命令执行方式为逐行执行要么全执行,要么全不执行 )fi
2、if多分支语句
if 条件 1; then# 命令,条件 1 成 ⽴ 执 ⾏elif 条件 2;then# 命令,条件 1 不成 ⽴ ,条件 2 成 ⽴ 执 ⾏elif 条件 3;then# 命令,条件 1 不成 ⽴ ,条件 2 不成 ⽴ ,条件 3 成 ⽴ 执 ⾏else# 命令 ,以上条件都不成 ⽴ 执 ⾏fi
(1)数字判断格式
-eq : equal ,等于,一般用于 [ $? -eq 0 ] ,也就是判断上条命令返回值等于 0 ,直接数字 -eq 数字也可以 equals-ne : not equal ,不等于,一般用于 [ $? -ne 0 ] ,判断上条命令返回值不等于 0-gt : greater than ,大于-ge : greater or equal ,大于或等于-lt : less than ,小于-le : less or equal ,小于或等于
eg:数字判断脚本
[root@shell ~]# vim if.sh
#!/bin/bash
echo "请输入第一个数字"
read a
echo "请输入第二个数字"
read b
if [ $a -eq $b ]; then
echo "两个数字相等"
else
echo "两个数字不想等"
fi
[root@shell ~]# sh if.sh
请输入第一个数字
2
请输入第二个数字
4
两个数字不想等
eg:测试网络是否畅通的脚本
[root@shell ~]# vim ping.sh
#!/bin/bash
read -p "请输入要测试的网址:" web
# read:命令行内输入web的变量值
ping -c 3 $web &> /dev/null
# ping -c 3,连接某个网站三次
if [ $? -eq 0 ];then
# 如果ping命令执行成功,那么
echo "此时网络畅通!"
# 输出“此时网络畅通”
else
# 否则
echo "无法访问,请检查网址是否输入正确或检查相关的网络配置!"
# 输出“无法访问...”
fi
# if语句的结尾[root@shell ~]# bash ping.sh
请输入要测试的网址:www.baidu.com
此时网络畅通!
(三)字符串判断
(1)格式:
[ 字符串 1 == 字符串 2 ] 字符串内容相同[ 字符串 1 != 字符串 2 ] 字符串内容不同[ -z 字符串 ] 字符串内容为空[ -n 字符串 ] 字符串内容不为空
[root@shell ~]# aaa="abc"
[root@shell ~]# echo $aaa
abc
[root@shell ~]# test $aaa == "abc"
[root@shell ~]# echo $?
0
[root@shell ~]# test $aaa == "aaaa"
[root@shell ~]# echo $?
1
[root@shell ~]# test $aaa == "aaa"
[root@shell ~]# echo $?
1
eg:简单的字符串判断脚本
[root@shell ~]# vim zifu.sh
#!/bin/bash
read -p "请输入账号:" user
if [ $user == admin ] ; then
echo "欢迎登陆:$user"
else
echo "账号或密码错误!"
fi
[root@shell ~]# sh zifu.sh
请输入账号:admin
欢迎登陆:admin
[root@shell ~]# sh zifu.sh
请输入账号:aaa
账号或密码错误!
eg:测试nginx安装脚本
[root@shell ~]# vim nginxinstall.sh
#!/bin/bash
rpm -qa | grep nginxif [ $? -eq 1 ] ; then
yum -y install nginx
else
yum -y remove nginx
yum -y install nginx
fi
[root@shell ~]# bash nginxinstall.sh
(四)与或判断
判断多个条件多个条件其中一个成立,或多个条件都要成立,与或运算判断: || 或,两个条件满足其一即可,还有-o与运算判断: && 与,两个条件都得满足才行,还有 -a多项选择
(1)或运算判断
[root@localhost test] # vim huo.sh#!/bin/bashread -p "请输⼊字符串:" nameif [ "$name" == "haha" ]||[ "$name" == "hehe" ];then # 这两个条件需满足其一,也可使⽤[ "$name" =="haha" -o "$name" == "hehe" ]echo "$name is my want"elseecho "in else"fi[root@localhost test] # sh ./huo.sh请输⼊字符串:hahahaha is my want[root@localhost test] # sh ./huo.sh请输⼊字符串:hehehehe is my want[root@localhost test] # sh ./huo.sh请输⼊字符串:lalain else
(2)与运算判断
[root@localhost test] # vim yu.sh#!/bin/bashread -p "请输⼊⼀个数值:" ageif [ $age -gt 30 ]&&[ $age -lt 80 ];then # 这两个条件都得满足,大于30且小于80,可使用[ $age -gt 30 -a $age -lt 80 ]echo "age>30 and age<80"echo "working"elseecho "in else"fi[root@localhost test] # sh ./yu.sh请输⼊⼀个数值:60age>30 and age<80workin g[root@localhost test] # sh ./yu.sh请输⼊⼀个数值:90in else
(3)混合判断
[root@shell ~]# vim menu.sh
#!/bin/bash
echo "1:新增文件 2:删除文件 3:查找文件 4:修改文件"
read -p "请输入序号选择功能:" m
if [ $m == 1 ] ; then
touch aaaaa.txt
elif [ $m == 2 ]; then
rm -rf aaaaa.txt
else
echo "其他功能正在开发"
fi[root@shell ~]# sh menu.sh
1:新增文件 2:删除文件 3:查找文件 4:修改文件
请输入序号选择功能:1
[root@shell ~]# ls
aaaaa.txt createacc if.sh nginxinstall.sh ping.sh test001.sh
anaconda-ks.cfg hello.sh menu.sh nginx.sh sh001.sh zifu.sh
[root@shell ~]# sh menu.sh
1:新增文件 2:删除文件 3:查找文件 4:修改文件
请输入序号选择功能:2
[root@shell ~]# ls
anaconda-ks.cfg hello.sh menu.sh nginx.sh sh001.sh zifu.sh
createacc if.sh nginxinstall.sh ping.sh test001.sh
三、shell脚本循环语法
[root@shell ~]# yum -y install inotify #监听指定目录是否有修改
(一)for循环
1、作用
■ 读取不同的变量值,以逐个执行同一组命令
2、结构
for 变量名 in 取值列表(范围)
do
命令序列
■ 取值列表:数字范围、字符串、多个字符串、提前设定好的变量等
■ for默认以所有的空白字符进行分隔:tab、空格、回车,去循环处理
■ 分隔成几段就循环几次
[root@shell ~]# vim wait.sh
#!/bin/bash
yum -y install epel-release
yum -y install inotify-tools
inotifywait mrg $l while read events
do
echo"文件发生修改"
done
[root@shell~]# bash wait.sh
分隔值循环
[root@shell ~]# vim city.sh
#!/bin/bash
for city in 青岛 庆阳
do
echo "$city 是个好地方"
done
[root@git ~]# bash city.sh
青岛是个好地方
庆阳是个好地方
(二)while循环
while 条件测试操作do命令序列done
(1)while 循环也有条件判断,当条件成立的时候,会循环执行。当条件不成立退出(2)if判断当条件成立时,会执行一次,然后退出。当条件不成立时直接退出
[root@localhost test] # vim userdel.sh#!/bin/bashread -p "请输⼊要删除⽤户的前缀:" QZread -p "请输⼊要删除⽤户的个数:" NUMi=1while [ $i -le $NUM ]douserdel -r $QZ$ilet i++done[root@localhost test] # bash userdel.sh请输 ⼊ 要删除 ⽤ 户的前缀 :admin请输 ⼊ 要删除 ⽤ 户的个数 :5
九九乘法表脚本
[root@shell ~]# vim 99.sh
#!/bin/bash
for i in {1..9};do
for j in {1..9};do
echo -n "$j*$i=$(($i*$j)) "
if [ $j == $i ];then
echo -e '\n'
break
fi
done
done[root@shell ~]# bash 99.sh
1*1=11*2=2 2*2=4
1*3=3 2*3=6 3*3=9
1*4=4 2*4=8 3*4=12 4*4=16
1*5=5 2*5=10 3*5=15 4*5=20 5*5=25
1*6=6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36
1*7=7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49
1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64
1*9=9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81
四、sed流式编辑器
(一)概述
sed 是文本处理工具,读取文本内容,根据指定条件进行处理,可实现增删改查的功能。sed 依赖于正则表达式。
1、格式
sed ' 过滤 + 动作 ' 文件路径
2、选项
-e 指定要执行的命令 ( 操作 ) ,只有一个编辑命令 ( 操作 ) 时可省略-n 只输出处理后的行,读入时不显示,不对原文件进行修改-i 直接修改源文件,不输出结果
3、操作
p 打印(输出) d 删除(整行) s 替换(字符串匹配) c 替换(整行) r 读取指定文件(追加到行后)a ( append )追加到指定内容到行后i ( insert )追加指定内容到行前
w 另存为n 表示读入下一行内容H 复制到剪贴板g 将剪贴板中的内容覆盖到指定行G 将剪贴板中的内容追加到指定行后
(二)sed命令引用变量
sed -i '2s/node_base/'" $i "'/' /etc/libvirt/qemu/ $i .xml
sed -i "2s/node_base/ $i /" /etc/libvirt/qemu/ $i .xml
练习
1.配置一个自动设置静态ip以及关闭selinux服务 关闭防火墙服务 关闭NetWOrkManager,修改主机名称的 脚本,ip和主机名称使用read输入
[root@shell ~]# vim open.sh
#!/bin/bash
#备份
cp /etc/sysconfig/network-scripts/ifcfg-ens160 /etc/sysconfig/network-scripts/ifcfg-ens160.bak# 读取用户输入的IP地址和主机名称
read -p "请输入要设置的静态IP地址: " STATIC_IP
read -p "请输入新的主机名称: " HOSTNAME#替换DHCP为none
sed -i '/dhcp/s/dhcp/none/g' /etc/sysconfig/network-scripts/ifcfg-ens160
#在文档最后添加五行
sed -i '$aIPADDR=STATIC_IP' /etc/sysconfig/network-scripts/ifcfg-ens160sed -i '$aNETMASK=255.255.255.0' /etc/sysconfig/network-scripts/ifcfg-ens160
sed -i '$aGETWAY=192.168.1.254' /etc/sysconfig/network-scripts/ifcfg-ens160
sed -i '$aDNS1=8.8.8.8' /etc/sysconfig/network-scripts/ifcfg-ens160
sed -i '$aDNS2=114.114.114.114' /etc/sysconfig/network-scripts/ifcfg-ens160
sed -i 'UUID/cUUID='"uuidgen"'' /etc/sysconfig/network-scripts/ifcfg-ens160
# 关闭SELinux
setenforce 0
sed -i 's/^SELINUX=.*/SELINUX=disabled/' /etc/selinux/config# 关闭防火墙服务
systemctl stop firewalld
systemctl disable firewalld# 关闭NetworkManager服务
systemctl stop NetworkManager
systemctl disable NetworkManager# 修改主机名称
hostnamectl set-hostname $HOSTNAME# 重启网络服务
systemctl restart networkecho "静态IP已设置为 $STATIC_IP,主机名称已设置为 $HOSTNAME。"
[root@shell ~]# bash open.sh
请输入要设置的静态IP地址: 192.168.1.12
请输入新的主机名称: sss
sed:-e 表达式 #1,字符 1:未知的命令:“U”
setenforce: SELinux is disabled
Removed symlink /etc/systemd/system/multi-user.target.wants/NetworkManager.service.
Removed symlink /etc/systemd/system/dbus-org.freedesktop.NetworkManager.service.
Removed symlink /etc/systemd/system/dbus-org.freedesktop.nm-dispatcher.service.
Job for network.service failed because the control process exited with error code. See "systemctl status network.service" and "journalctl -xe" for details.
静态IP已设置为 192.168.1.12,主机名称已设置为 sss。