shell 1-3合集

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 "33[92mABCD33[0m"


函数,能够将公共的语句块存储在一个变量中,达到精简脚本的目的

函数名称 (){
指令
}
cecho (){
echo -e "33[$1m$233[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%%/*}     从右往左删除,到最后一个/ ,以及/右边所有