shell 01
shell 翻译官
shell脚本 工具,提高工作效率
命令 交互式
脚本 非交互式
cat /etc/shells 查看拥有的解释器
yum -y install ksh 安装新解释器
bash优点 历史命令,快捷键,tab键,重定向,管道
脚本的格式:
1,声明解释器类型
#!/bin/bash
2,注释,说明该脚本的作用,变量的含义等
3,编写代码
写完后,赋予脚本执行权限 chmod +x test1.sh
执行脚本的方法:
1, ./test1.sh 使用绝对路径或者相对路径执行脚本 ,需要x权限
2, bash test1.sh 调用另外一个bash执行脚本,开启子进程
3, source test1.sh 使用当前解释器执行脚本,不开启子进程
#!/bin/bash
mkdir /opt/abc
cd /opt/abc
#!/bin/bash
echo 123
sleep 1000
#!/bin/bash
#部署yum软件仓库
rm -rf /etc/yum.repos.d/*.repo
echo "[abc]
name=abc
baseurl=http://172.25.254.254/content/rhel7.0/x86_64/dvd/
enabled=1
gpgcheck=0" > /etc/yum.repos.d/abc.repo
#!/bin/bash
#部署vsftpd服务
yum -y install vsftpd &> /dev/null
systemctl restart vsftpd
systemctl enable vsftpd
==============================
常量 固定不变
变量 灵活多变,增加灵活,增加功能
变量的种类
1,自定义变量
变量名称=变量的值 名称必须是字母数字下划线,不能以数字开头,不能使用特殊符号
a=10 定义变量
echo $a 查看变量的值
echo ${a}RMB 输出变量+常量,大括号用来界定容易混淆的名称
unset a 取消变量
echo $a 再次查看
2,环境变量,系统自带
USER当前用户名 UID当前用户的id号 HOME当前用户的家目录 PWD当前位置 SHELL当前用户使用的解释器 HOSTNAME主机名
PS1一级提示符 PS2二级提示符 PATH存放命令的路径
echo $PS1 显示一级提示符
[\u@\h \W]\$
PS1=dachui 修改
PS1='[\u@\h \W]\$' 还原
3,位置变量与预定义变量
$1 $2 $3 .....
$0脚本名 $$进程号 $#位置变量的个数 $*所有的位置变量 $?上一条指令的结果,0是成功, 非0是失败
env 查看所有环境变量
set 查看所有变量
变量的扩展应用
"" 界定范围
'' 界定范围,屏蔽特殊符号
touch "a b" 创建一个带空格文件
touch 'x y' 创建一个带空格文件
a=10
echo "$a" 显示变量a中的值
echo '$a' 显示$a
`` 反撇号, 可以获取命令的执行结果
a=ls 变量a的值是ls
a=`ls` 变量a的值是ls执行的结果
a=$(ls) 变量a的值是ls执行的结果
stty -echo 屏蔽回显
stty echo 恢复回显
a=100 通常创建的变量是局部变量 ,只在某个解释器中生效
export 发布全局变量,使任何解释器(子进程中均可使用)
a=100
export a 将a发布为全局变量
export b=200 创建并发布全局变量
bash 进入新解释器(子进程)
echo $a 可以使用之前发布的变量
echo $b
exit 返回
export -n b 取消变量b的全局状态,恢复为局部变量
===============================
shell中的运算
方法一:
expr 1 + 1 加
expr 2 - 1 减
expr 2 \* 2 乘 \ 转义符号 ,可以屏蔽之后1个字符的特殊含义
expr 4 / 2 除
expr 4 % 2 求模(取余数)
a=10
b=20
expr $a + $b
expr $a + 10
expr $a + $a
方法二:
echo $[1+1]
echo $[2-1]
echo $[2*2]
echo $[2/2]
echo $[2%2]
echo $[a+b]
echo $[a+20]
方法三: let 运算结果不显示, 通常用于变量创建或者变量自增减
let a=5+5 创建变量a
变量自增减
主流写法:
let a-- 相当于 let a=a-1
let a++ 相当于 let a=a+1
let a+=2 相当于 let a=a+2
let a-=2 相当于 let a=a-2
let a/=5 相当于 let a=a/5
let a*=4 相当于 let a=a*4
let a%=4 相当于 let a=a%4
bc 计算器 ,可以小数运算
echo "scale=3;10/3" | bc
sell 02
回顾
shell
/bin/bash 历史记录,快捷键,tab键,重定向,管道
规范的shell脚本:
声明解释器 #!/bin/bash
注释,脚本功能,变量的作用
代码
脚本的执行方式:
1,添加x权限
2,调用解释器直接执行 bash XXX.sh
3,source XXX.sh
变量:
1, 自定义变量 变量名=变量的值
echo ${a}XXX
unset a
2,环境变量 USER UID HOME HOSTNAME SHELL PWD PS1 PS2 PATH
3,位置变量与预定义变量
$1 $2 $3..... $0 $$ $# $* $?
变量扩展:
"" ''
` $()
read -p "XXX" n
stty -echo stty echo
export a 发布全局变量
运算:
expr 1 + 1
echo $[1+1]
let a=10+3 let a++ let a*=10
bc
=================================
条件测试,可以让脚本更智能的工具
1,字符串的测试 == 判断两边的内容是否相等 !=
[ a == a ] a是否等于a
echo $? 结果是0
[ a == b ]
echo $? 结果非0
[ root == $USER ] 我是不是管理员,结果是0
su - abc 切换普通用户之后在测试,结果非0
a=10
b=
[ -n "$a" ] 判断$a是否非空
echo $?
[ -n "$b" ] 判断$b是否非空
echo $?
[ ! -n "$b" ] 上述判断取反,判断$b是否为空
echo $?
[ -z "$a" ] 判断$a是否为空
echo $?
[ -z "$b" ] 判断$b是否为空
4, 逻辑测试
&& 符号之前的任务成功后,才执行之后的任务
|| 符号之前的任务失败后,才执行之后的任务
ls && ls 第一个任务成功了,会继续执行第2个任务, 一共执行两次ls
ls || ls 第一个任务成功了,不会继续执行第2个任务, 一共执行1次ls
[ -z $1 ] && exit 如果$1为空, 就会执行exit退出脚本
两个逻辑符号: 在ls都执行成功的情况下
ls && ls && ls 执行3次ls
ls && ls || ls 第1次执行,第2次执行,第3次不执行
ls || ls || ls 第1次执行,后面都不执行
ls || ls && ls 第1次执行,第2次不执行,第3次执行
[ root == $USER ] && echo "我是管理员" || echo "我不是管理员"
2,数字的测试
-eq等于 -ne不等于 -gt大于 -ge大于等于 -lt小于 -le小于等于
[ 1 -eq 1 ] 1等于1, echo $? 结果是成功
[ 0 -eq $USER ] 我的id号是否为0,管理员运行的话,结果是成功
两种不同写法,可以实现相同目的:
[ -z $n ] && echo "你倒是给个名字啊!" && exit
[ -n "$n" ] || echo "你倒是给个名字啊!"
[ -n "$n" ] || exit
要求,每2分钟检查系统登录账户数量,如果超过3人登录,给管理员发报警邮件
#!/bin/bash
x=`who | wc -l`
[ $x -gt 3 ] && echo "有人***服务器!隔壁老王来了!" | mail -s test root
mail 查邮件
crontab -e
*/2 * * * * /opt/test1.sh
chmod +x test1.sh
3,文件的测试
-e 是否存在 -f 是否存在且为普通文件 -d 是否存在且为目录
-r -w -x 判断当前用户对某文件是否有相关权限
[ -e abc ] abc是否存在,不关心文件类型
[ -f abc ] abc是否存在,必须是文件
[ -d abc ] abc是否存在,必须是目录
[ -r abc ] 当前用户对文件abc是否有读权限,管理员无效
[ -w abc ] 当前用户对文件abc是否有写权限,管理员无效
[ -x abc ] 当前用户对文件abc是否有执行(目录是进入的)权限
================================
== != -z -n
-eq -ne -gt -ge -lt -le
-e -f -d -r -w -x
&& || ;
if判断
种类1:
单分支
if 条件测试 ;then
执行指令
fi
#!/bin/bash
if [ ! -d /opt/xyz ] ;then
mkdir /opt/xyz
echo 123
fi
双分支
if 条件测试 ;then
执行指令1
else
执行指令2 判断当前目录是否有a目录,没有就创建
fi
#!/bin/bash
if [ -f a ] ;then
rm -rf a
mkdir a
else
[ -d a ] || mkdir a
fi
多分支
if 条件测试1 ;then
执行指令1
elif 添加测试2 ;then
执行指令2
else
执行指令3
fi
============================
ping -c 检测次数 -i 间隔时间(秒) -W 网络无法通讯时的反馈时间
ping -c 3 -i 0.2 -W 1 172.25.0.13
#!/bin/bash
read -p "请输入ip地址" ip
ping -c 3 -i 0.2 -W 1 $ip &> /dev/null
if [ $? -eq 0 ] ;then
echo "通了!"
else
echo "不通!"
fi
#!/bin/bash
x=$[RANDOM%10]
read -p "请输入一个数字(0-9)" n
if [ $x -eq $n ] ;then
echo "猜中了!"
elif [ $n -lt $x ] ;then
echo "猜小了"
else
echo "猜大了"
fi
========================
循环
for循环 有次数限制 可以关注循环次数或者变量
for 变量名 in 值1 值2 值3......
do
执行指令
done
!/bin/bash```
for i in {1..10} 循环10次,此方式不支持变量比如{1..$a}
do
echo 123
echo $i
done
#!/bin/bash
a=10
for i in `seq $a` 使用变量循环10次
do
echo 123
echo $i
done
172.25.0.1~172.25.0.15
#!/bin/bash
for i in {1..15}
do
ping -c 3 -i 0.2 -W 1 172.25.0.$i &> /dev/null
if [ $? -eq 0 ] ;then
echo "172.25.0.$i 通了"
else
echo "172.25.0.$i 不通"
fi
done
#!/bin/bash
x=0
y=0
for i in {1..15}
do
ping -c 3 -i 0.2 -W 1 172.25.0.$i &> /dev/null
if [ $? -eq 0 ] ;then
echo "172.25.0.$i 通了"
let x++
else
echo "172.25.0.$i 不通"
let y++
fi
done
echo "$x台通了,$y台不通"
shell 03
回顾
条件测试
test 表达式 [ 表达式 ]
1,字符串 == != -n -z
2,逻辑测试 && || ;
3,数字 -eq -ne -gt -ge -lt -le
4,文件 -e -d -f -r -w -x
if 单分支 双分支 多分支
if 条件测试1 ;then
执行指令1
elif 条件测试2 ;then
执行指令2
else
执行指令n
fi
循环
for 变量名称 in 值
do
执行指令
done
while :
do
执行指令
done
ping -c -i -W
RANDOM
200行
===========================
case分支 ,功能类似if,不如if强大,代码比if精简
case 变量名称 in
模式1)
执行指令1 ;;
模式2)
执行指令2 ;;
*)
执行指令n
esac
#!/bin/bash
case $1 in
t|T)
touch $2;;
m|M|mm)
mkdir $2
echo 123;;
r)
rm -rf $2;;
*)
echo "请输入t|m|r"
esac
部署nginx服务
真实主机中:
scp lnmp_soft.tar.gz root@server0:/opt
虚拟机中:
在虚拟机中释放该目录,并将其中的nginx-1.10.3.tar.gz拷贝到/opt下
#!/bin/bash
yum -y install gcc openssl-devel pcre-devel &> /dev/null
tar -xf nginx-1.10.3.tar.gz
cd nginx-1.10.3
./configure
make
make install
执行完脚本后运行 /usr/local/nginx/sbin/nginx
关闭防火墙 systemctl stop firewalld
使用真机浏览器访问172.25.0.11可以看到欢迎页面
echo -e "\033[92mABCD\033[0m"
函数,能够将公共的语句块存储在一个变量中,达到精简脚本的目的
函数名称 (){
指令
}
cecho (){
echo -e "\033[$1m$2\033[0m"
}
中断和退出
exit 退出脚本
break 退出循环,继续执行循环之后的任务
continue 退出当前循环,继续下一次循环
从键盘循环取整数(0结束)并求和,输出最终结果
#!/bin/bash
x=0
while :
do
read -p "请输入一个数字" n
[ -z $n ] && exit
[ $n -eq 0 ] && break
let x+=n
done
echo $x
找出1~20以内6的倍数,并输出她的平方值
#!/bin/bash
for i in {1..20}
do
x=$[i%6] x是余数
[ $x -eq 0 ] || continue 余数等于0就继续下面的任务
echo $[i*i]
done
===============================
字符串处理
1,字符串的截取,第一个字符系统定义序号是0
${变量名:起始位置:长度}
echo ${a:1:1} 截取变量a,从第2个字符向后符截取1位
echo ${a:4:2} 截取变量a,从第5个字符向后符截取2位
echo ${a:0:2} 截取变量a,从第1个字符向后符截取2位 ,且0可以省略
获取一位随机字符的脚本:
#!/bin/bash
a=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUV
WXYZ0123456789
x=$[RANDOM%62]
echo ${a:x:1}
获取8为随机密码的脚本:
#!/bin/bash
a=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUV
WXYZ0123456789
for i in {1..8}
do
x=$[RANDOM%62]
p=${a:x:1}
pa=$pa$p
done
echo $pa
2 字符串的替换
a=aabbccdd
${变量名/old/new} 替换一个old为new
${变量名/a/6} a换成6
${变量名//old/new} 替换所有old为new
${变量名//a/6} 所有a换成6
${变量名/old/} 删除一个old
${变量名//old/} 删除所有old
3,字符串的删除
${变量名#被删除的内容} 掐头
a=`head -1 /etc/passwd`
echo $a
root:x:0:0:root:/root:/bin/bash
echo ${a#root} 删除第一个root
echo ${a#root:x} 删除root:x
echo ${a##*root} 删除到最后一个root,以及该root左边所有
思考如何删除之后剩余 echo ${a#*:root:}
/root:/bin/bash
${变量名%被删除的内容} 去尾
echo ${a%bash} 从右往左删除,到bash
echo ${a%%/*} 从右往左删除,到最后一个/ ,以及/右边所有