欢迎来到李洋的博客

回首境界: 众里寻他千百度,蓦然回首,那人却在灯火阑珊处。

shell编程

1.什么情况下使用Shell

1)安装CentOS系统 自动化安装操作系统(kickstart cobbler) 底层shell

2)网络IP地址

3)初始化操作系统(ntp时间同步,更改默认YUM源,SSH端口,SSH远程连接禁止DNS解析,禁止root登录,关闭seilnux,防火墙优化(c6 iptables c7 firewald) 80 443 22 8080 10050 ,
安装常用的软件命令 lrzsz wget net-tools... 加大文件描述符 中文字符集 内核参数优化 别名 重要的文件加上i a....等)
当前centos7的系统 如何更换为iptables
    1.关闭firewalld 永久禁止启动
            systemctl stop firewalld
            systemctl disable firewalld
    2.安装iptables-services
        需要放行的端口?
        以上都是shell脚本实现

4)安装服务 Nginx PHP MySQL Redis MHA Rsync NFS mongo KVM Docker Zabbix ELK.....
shell脚本自动安装不同版本的服务

5)配置文件 shell

6)启动服务(系统默认的就是shell脚本) python产品
python3.5 conut.py --redis 10.0.0.10 --port 3306 --传参 --- 写入shell脚本
conut_start.sh conut_stop.sh 
ps axu|grep php|grep -v grep|awk '{print $2}'|xargs kill -9

7)监控 zabbix 常用 服务器的各种状态 进程 cacti 监控流量 nagios 交换机 路由器 
shell脚本统计需要的数据进行监控

8)日志统计 日志切割 日志收集 +800M vim 或者命令 (排除大数据公司) ELK
三剑客等命令+shell脚本+定时任务

9)命令+shell脚本+定时任务 数据备份

2.学习shell脚本需要用到的知识

1)远程连接工具 Xshll CRT(作业)
2)lINUX的常用命令 熟练掌握
3)三剑客命令熟练
4)vim编辑器熟练

3.如何学好shell编程

环境变量 条件表达式 if判断 for循环 while循环 case语句 数组 函数
先学好shell基础
读懂shell 修改shell脚本 自己编写shell脚本
不可拿来主义
有一本教材 shell编程

4.shell入门

1)什么是shell 壳
命令解释器 用户输入命令 解释器负责解释给内核 处理后的结果 反馈用户 称为解释
交互式shell 用户输入命令 解释器解释把处理后的结果反馈给用户的过程称为 交互式
非交互shell shell执行文本中的命令 当执行到文件的末尾 bash退出
父shell 不能继承子shell变量 子shell可继承父shell变量

2)什么是shell脚本
把可执行命令堆积到一个文本中则称为shell脚本(条件表达式 for循环 if判断等等语句)

5.shell脚本的书写规范

  1. 目录统一
  2. shell脚本的结尾要以.sh结尾
  3. 脚本的开头需要有解释器 /bin/bash /bin/sh
  4. 脚本中需要有作者信息 #Author lzy date version 做什么的
  5. 脚本每行 或者 一个语句 给一个注释
  6. shell中的文字尽量使用英文 py都是中文
  7. 成对的符号一次性书写完毕 语句

6.第一个shell脚本

hello world!
执行脚本的三种方式	
1)bash test.sh
[root@web01 scripts]# bash test.sh
Hello World!

2)全路径执行
[root@web01 scripts]# chmod +x test.sh 
[root@web01 scripts]# /server/scripts/test.sh
Hello World!

3). 或者source执行
[root@web01 scripts]# . test.sh
Hello World!
[root@web01 scripts]# source test.sh
Hello World!

什么区别?
1 2 在子shell中执行
. source 父进程下执行

7. 环境变量

1)什么是环境变量?

右边一堆内容,用一个名字来代替称为环境变量
name="I am lizhenya"
如何查看环境变量? 名称的前面加上$
echo $name
如何查看系统定义好的环境变量
env set
如何取消环境变量?
unset name
环境变量(全局变量) 普通变量(局部变量)
按照生存周期划分
永久性 修改配置文件 /etc/profile
临时性 使用export 变量名称 声明即可
不加export 只对当前的shell生效
加export 对当前登录窗口所有的shell生效

环境的相关文件

  1. /etc/profile 开机或者新连接的窗口执行一次
  2. .bashrc
  3. .bash_profile
  4. /etc/bashrc

2)如何定义环境变量

变量名=变量值
环境变量名称的定义 字符 下划线 数字的组合 尽量以字母开头(禁止使用数字开头) 等号两端不允许有空格 见名知其意
书写方式

  1. OLDBOY_AGE=18 系统中变量的定义格式
  2. oldboy_age=18
  3. oldboy_Age=18 小驼峰语法
  4. Oldboy_Age=18 大驼峰语法

变量值的定义方式

数字的定义
oldboy_age=18 连续的数字

字符串的定义
name="oldboy" 使用双引号 不知道加什么符号 就加双引号 解析变量
name='oldboy' 所见即所得 吃什么吐什么

命令的定义
time=`date` 反引号 里面必须跟可执行命令
time=$(date) $()
[root@web01 scripts]# name=oldboy
[root@web01 scripts]# echo "$oldboyisok"

[root@web01 scripts]# echo "${oldboy}isok"
isok
[root@web01 scripts]# echo "${name}isok"
oldboyisok
[root@web01 scripts]# echo '${name}isok'
${name}isok

8. 重要的特殊位置变量

$0	脚本的名称,如果全路径执行脚本,则脚本名称也带全路径 basename 获取脚本的名称 重要
案例: 给用户提示如何使用此脚本
echo $"Usage: $0 {start|stop|status|restart|force-reload}"
$n 脚本的第n个参数 $0被脚本名称占用 从$1开始 $9以后 需要加{}
$# 代表了脚本的传参的总个数 重要
案例:
[ $# -ne 2 ] && echo "你请输入两个参数" && exit
$* 脚本的所有的传参的参数 如果不加双引号则和$@相同 加上双引号则把所有参数视为一个整体
$@ 脚本的所有的传参的参数 如果不加双引号则和$*相同加上双引号则把所有参数视为独立的参数
$* 和$@ 正常情况下一样 循环体内不同
$? 获取上一条命令的结果 0为成功 非0 失败 重要 
$$ 获取脚本的PID
案例
服务器运行大量的名称相同的脚本
echo $$ > /tmp/count.pid
$! 上一个在后台运行脚本的PID 调试使用
$_ 获取脚本的最后一个参数 相当于ESC .

9. 传参的三种方式

1)直接传参
2)赋值传参
3)read传参

#第一种传参方式
echo $1 $2
#第二种传参方式
name=$1
age=$2
echo $name $age
read -p "请输入名字和年龄" name1 age1
echo $name1 $age1

案例:
使用read 传参的方式 更改系统的主机名称和IP地址的最后一位 192.168.12.X

#!/bin/sh
sdir="/etc/sysconfig/network-scripts/ifcfg-eth0"
sip=`cat /etc/sysconfig/network-scripts/ifcfg-eth0|awk -F. '/IPADDR/{print $NF}'|cut -c1`
read -p "请输入主机名称: " name
        hostnamectl set-hostname $name
read -p "请输入IP地址的最后一位: " ip
        sed -i "s#$sip#$ip#g" $sdir

案例:

[root@web01 scripts]# sh ping.sh www.baidu.com
ping www.baidu.com is ok
[root@web01 scripts]# sh ping.sh www.xxxxx.com
ping www.xxxxx.com is error

[root@web01 scripts]# cat ping.sh 
#!/bin/sh
read -p "请输入一个网址: " url
        ping -c 1 -W 1 $url >/dev/null 2>&1
        [ $? -eq 0 ] && echo "ping $url is ok" || echo "ping $url is error"

10. 变量的字符串知识

10.1 统计变量的长度 重点

[root@web01 scripts]# name="I am lizhenya"
[root@web01 scripts]# echo $name
I am lizhenya
[root@web01 scripts]# echo "I am lizhenya"
I am lizhenya
[root@web01 scripts]# echo "I am lizhenya"|wc -L
13
[root@web01 scripts]# echo $name|wc -L
13
[root@web01 scripts]# echo ${#name}
13

10.2 变量的切片

[root@web01 scripts]# echo ${name:0:1}
I
[root@web01 scripts]# echo ${name:2:2}
am
[root@web01 scripts]# echo ${name:0:1}
I
[root@web01 scripts]# echo ${name:1}
am lizhenya
[root@web01 scripts]# echo ${name:2:5}
am li

10.3 取字符串长度

I am lizhenya teacher I am 18

方法1
echo I am lizhenya teacher I am 18|wc -L
方法2
name="I am lizhenya teacher I am 18"
echo ${#name}
方法3
[root@web01 scripts]# expr length "$name"
29
方法4
[root@web01 scripts]# echo $name|awk '{print length}'
29

面试题:取字符串长度小于3的

方法1 
for循环方式
[root@web01 scripts]# cat for.sh 
#!/bin/sh
for i in I am lizhenya teacher I am 18
do
        [ ${#i} -lt 3 ] && echo $i
done
方法2
[root@web01 scripts]# echo I am lizhenya teacher I am 18|xargs -n1|awk '{if(length<3)print}'
I
am
I
am
18
方法3
[root@web01 scripts]# echo I am lizhenya teacher I am 18|awk '{for(i=1;i<=NF;i++)if(length($i)<3)print $i}'

11.变量的删除和替换

11.1 从前往后删除变量内容

[root@web01 scripts]# echo $url
www.sina.com.cn
[root@web01 scripts]# echo ${url#*.}
sina.com.cn
[root@web01 scripts]# echo ${url#*.*.}
com.cn
[root@web01 scripts]# echo ${url##*.}
cn

11.2 从后往前删除变量内容

[root@web01 scripts]# echo $url
www.sina.com.cn
[root@web01 scripts]# echo ${url%.*}
www.sina.com
[root@web01 scripts]# echo ${url%%.*}
www

11.3 变量的替换

[root@web01 scripts]# echo $url
www.sina.com.cn
[root@web01 scripts]# echo ${url/w/a}
aww.sina.com.cn
[root@web01 scripts]# echo ${url/w/aa}
aaww.sina.com.cn
[root@web01 scripts]# echo ${url/w/a}
aww.sina.com.cn
[root@web01 scripts]# echo ${url//w/a}
aaa.sina.com.cn
[root@web01 scripts]# echo ${url/sina/baidu}
www.baidu.com.cn

12. 数值的运算

12.1 expr 整数运算

[root@web01 scripts]# expr 1+1
1+1
[root@web01 scripts]# expr oldboy
oldboy
[root@web01 scripts]# expr 1 + 1
2
[root@web01 scripts]# expr 1 - 1
0
[root@web01 scripts]# expr 1 * 11
expr: 语法错误
[root@web01 scripts]# expr 1 \* 11
11
[root@web01 scripts]# expr 110 / 11
10
[root@web01 scripts]# expr 1 + 1.5

expr: 非整数参数
案例: 判断传参输入是否为整数
[root@web01 scripts]# num1=10
[root@web01 scripts]# num2=11q
[root@web01 scripts]# expr $num1 + 1 >/dev/null 2>&1
[root@web01 scripts]# [ $? -ne 0 ] && echo "你输入的是非整数" || echo "你输入的是整数"
你输入的是整数
[root@web01 scripts]# expr $num2 + 1 >/dev/null 2>&1
[root@web01 scripts]# [ $? -ne 0 ] && echo "你输入的是非整数" || echo "你输入的是整数"
你输入的是非整数

11.2 $(()) 整数运算 运算效率最高

[root@web01 scripts]# echo $((10+10))
20
[root@web01 scripts]# echo $((10-10))
0
[root@web01 scripts]# echo $((10*10))
100
[root@web01 scripts]# echo $((10/10))
1

11.3 $[] 整数运算

[root@web01 scripts]# echo $[10+10]
20
[root@web01 scripts]# echo $[10-10]
0
[root@web01 scripts]# echo $[10*10]
100
[root@web01 scripts]# echo $[10/10]
1
[root@web01 scripts]# echo $[10-10.5]
-bash: 10-10.5: 语法错误: 无效的算术运算符 (错误符号是 ".5")

11.4 let 重点

[root@web01 scripts]# let sum=10+10
[root@web01 scripts]# echo $sum
20
[root@web01 scripts]# num1=100
[root@web01 scripts]# num2=50
[root@web01 scripts]# let sum=$num1+$num2
[root@web01 scripts]# echo $sum
150
[root@web01 scripts]# let sum=$num1-$num2
[root@web01 scripts]# echo $sum
50
[root@web01 scripts]# let sum=$num1*$num2
[root@web01 scripts]# echo $sum
5000
[root@web01 scripts]# let sum=$num1/$num2
[root@web01 scripts]# echo $sum
2

11.5 i++ 变量自增

[root@web01 scripts]# let i=i+1
[root@web01 scripts]# echo $i
1

[root@web01 scripts]# let i++
[root@web01 scripts]# echo $i
2

[root@web01 scripts]# let i++
[root@web01 scripts]# let i++
[root@web01 scripts]# let i++
[root@web01 scripts]# let i++
[root@web01 scripts]# echo $i
6

[root@web01 scripts]# sh for.sh
7

[root@web01 scripts]# sh -x for.sh 
+ for i in I am lizhenya teacher I am 18
+ let a++
+ for i in I am lizhenya teacher I am 18
+ let a++
+ for i in I am lizhenya teacher I am 18
+ let a++
+ for i in I am lizhenya teacher I am 18
+ let a++
+ for i in I am lizhenya teacher I am 18
+ let a++
+ for i in I am lizhenya teacher I am 18
+ let a++
+ for i in I am lizhenya teacher I am 18
+ let a++
+ echo 7
7

[root@web01 scripts]# let c++
[root@web01 scripts]# let c++
[root@web01 scripts]# let c++
[root@web01 scripts]# let c++
[root@web01 scripts]# let c++
[root@web01 scripts]# let c++
[root@web01 scripts]# let c++
[root@web01 scripts]# echo $c
7

11.6 bc awk python (bc需要安装)

bc
[root@web01 scripts]# echo 10+10|bc
20
[root@web01 scripts]# echo 10-10|bc
0
[root@web01 scripts]# echo 10*10|bc
100
[root@web01 scripts]# echo 10/10|bc
1
[root@web01 scripts]# echo 10+10.5|bc
20.5

awk
[root@web01 scripts]# awk 'BEGIN{print 10+10}'
20
[root@web01 scripts]# awk 'BEGIN{print 10-10}'
0
[root@web01 scripts]# awk 'BEGIN{print 10/10.5}'
0.952381
[root@web01 scripts]# awk 'BEGIN{print 10*10.5}'
105
[root@web01 scripts]# awk 'BEGIN{print 10^10.5}'
3.16228e+10
[root@web01 scripts]# awk 'BEGIN{print 10^10}'
10000000000
[root@web01 scripts]# echo 100 200
100 200
[root@web01 scripts]# echo 100 200|awk '{print $1+$2}'
300

python
[root@web01 scripts]# python
Python 2.7.5 (default, Oct 30 2018, 23:45:53) 
[GCC 4.8.5 20150623 (Red Hat 4.8.5-36)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 10+10
20
>>> 10-10
0
>>> 10*10
100
>>> 10/10
1
>>> 10/10.5
0.9523809523809523
>>> 

小结 expr $(()) $[] let bc awk python
案例1:
ps axu 中的VSZ 列 所有的数相加 得出结果
[root@web01 scripts]# ps axuf|awk '{print $5}'|grep -v VSZ|tr "\n" "+"|sed -r 's#(.*)#\10\n#g'|bc
12778952

案例2:
做一个加减乘除的计算器
例如:
请输入第一个数字 10
请输入第二个数字 20
显示的结果 10+20=30

[root@web01 scripts]# cat count.sh 
#!/bin/sh
read -p "请输入第一个数字: " num1
read -p "请输入第二个数字: " num2
echo "$num1+$num2=$[$num1+$num2]"
echo "$num1-$num2=$[$num1-$num2]"
echo "$num1*$num2=$[$num1*$num2]"
echo "$num1/$num2=$[$num1/$num2]"

13 条件表达式

[]======test []常用
[ -f file ] 文件是否存在 且为普通文件 重点
[ -e file ] 文件存在则为真
[ -d file ] 目录存在则为真 重点
[ -x file ] 文件有执行权限则为真
[ -w file ] 文件可写则为真
[ -r file ] 文件可读则为真

[root@web01 scripts]# [ -f /etc/hosts ] && echo 为真 || echo 为假
为真
[root@web01 scripts]# [ -f /etc/hostsss ] && echo 为真 || echo 为假
为假
[root@web01 scripts]# [ -d /etc/hosts ] && echo 为真 || echo 为假
为假
[root@web01 scripts]# [ ! -d /etc/hosts ] && echo 为真 || echo 为假
为真
[root@web01 scripts]# [ -e /etc/hosts ] && echo 为真 || echo 为假
为真
[root@web01 scripts]# [ -e /etc/ ] && echo 为真 || echo 为假
为真
[root@web01 scripts]# [ -r /etc/ ] && echo 为真 || echo 为假
为真
[root@web01 scripts]# [ -w /etc/ ] && echo 为真 || echo 为假
为真
[root@web01 scripts]# [ -x /etc/ ] && echo 为真 || echo 为假
为真
[root@web01 scripts]# [ -x /etc/hosts ] && echo 为真 || echo 为假
[root@web01 scripts]# [ -x /etc/hosts ] && echo 为真 || echo 为假
为假
[root@web01 scripts]# [ -x /etc/hosts ] && echo 为真 || echo 为假
为假
[root@web01 scripts]# ll
总用量 24
-rw-r--r-- 1 root root 230 8月 1 16:07 count.sh
-rw-r--r-- 1 root root 74 8月 1 15:33 for.sh
-rw-r--r-- 1 root root 297 7月 31 16:59 ip.sh
-rw-r--r-- 1 root root 14 8月 1 15:06 oldboy.sh
-rw-r--r-- 1 root root 152 7月 31 17:12 ping.sh
-rwxr-xr-x 1 root root 225 7月 31 16:34 test.sh
[root@web01 scripts]# [ -x test.sh ] && echo 为真 || echo 为假
为真

-f 判断文件是否存在

案例:
[root@web01 scripts]# [ -f /etc/init.d/functions ] && . /etc/init.d/functions
[root@web01 scripts]# action "hehehe is" /bin/true
hehehe is [ 确定 ]
[root@web01 scripts]# action "hehehe is" /bin/false
hehehe is [失败]

函数库使用
[root@web01 scripts]# cat ping.sh 
#!/bin/sh
[ -f /etc/init.d/functions ] && . /etc/init.d/functions
read -p "请输入一个网址: " url
ping -c 1 -W 1 $url >/dev/null 2>&1
[ $? -eq 0 ] && action "ping $url is" /bin/true || action "ping $url is" /bin/false

-d 判断是否为目录 目录是否存在

[root@web01 scripts]# [ -d /alex ] || mkdir /alex
[root@web01 scripts]# test -f /etc/hosts && echo ok || echo error
ok
[root@web01 scripts]# test -d /etc/hosts && echo ok || echo error
error
[root@web01 scripts]# test -d /etc/ && echo ok || echo error
ok

14. 数值的比较

[ 数值1 比较符 数值2 ] [[]] = != >= < <=
-eq 相等
-ne 不等于
-gt 大于
-ge 大于等于
-lt 小于
-le 小于等于

[root@web01 scripts]# [ 10 -eq 10 ] && echo ok || echo error
ok
[root@web01 scripts]# [ 10 -gt 10 ] && echo ok || echo error
error
[root@web01 scripts]# [ 10 -ge 10 ] && echo ok || echo error
ok
[root@web01 scripts]# [ 10 -ne 10 ] && echo ok || echo error
error
[root@web01 scripts]# [ 10 -lt 10 ] && echo ok || echo error
error
[root@web01 scripts]# [ 10 -le 10 ] && echo ok || echo error
ok

案例1:

统计当前磁盘的使用率 如果大于5% 则把内容写入到以日期为名称的文本中 2019-08-01.txt
如果小了 则把当前的使用率 写入 2019-08-01.txt
1.如何取出当前的使用率
df -h|awk 'NR==2{print $(NF-1)}'
df -h|grep /$|awk '{print $(NF-1)}'

2.条件表达式 整数的比较
3.输出结果到文本
4.调试


[root@shell scripts]# cat usedisk.sh 
#!/bin/sh
time=`date +%F`
usedisk=`df -h|grep /$|awk '{print $(NF-1)}'`
[ ${usedisk%\%} -gt 5 ] && echo "当前使用率不正常 $usedisk" >> ${time}.txt || echo "当前使用率正常 $usedisk" >> ${time}.txt 


[root@web01 scripts]# [ `df -h|grep /$|awk -F "[ %]+" '{print $(NF-1)}'` -gt 5 ] && echo error || echo ok
error
[root@web01 scripts]# [ `df -h|grep /$|awk -F "[ %]+" '{print $(NF-1)}'` -gt 80 ] && echo error || echo ok
ok

案例2:

统计系统内存的使用率 如果大于10则 echo 使用率到 以时间命名的文件中
1.如何取出当前的使用率
百分比=====使用的除总数乘100
2.条件表达式 整数的比较
3.输出结果到文本
4.调试
[root@web01 scripts]# free|awk 'NR==2{print $3/$2*100}'
19.0124
[root@web01 scripts]# free=`free|awk 'NR==2{print $3/$2*100}'`
[root@web01 scripts]# [ ${free%.*} -gt 10 ] && echo error || echo ok
error
[root@web01 scripts]# [ ${free%.*} -gt 80 ] && echo error || echo ok
ok

案例3:

统计系统的负载 负载超过2 则发送到文件中 否则提示正常
1.如何查看统计负载
2.取值做比较
3.输出结果
4.调试

案例4:

使用脚本统计 主机名称 网卡IP地址 虚拟平台 系统版本号 外网IP地址 磁盘使用率
例如
sh os.sh
当前系统的主机名称是 web01
当前系统的IP地址是 10.0.0.7

15.字符串比对

15.1 字符串必须使用双引号

[ "name" = "name" ] 
[ "name" != "name" ] 
[root@web ~]# [ "$USER" = "root" ]
[root@web ~]# echo $USER
root
[root@web ~]# [ "$USER" = "root" ]
[root@web ~]# echo $?
0
[root@web ~]# [ "$USER" = "alex" ]
[root@web ~]# echo $?
1
[root@web ~]# [ "$USER" != "alex" ]
[root@web ~]# echo $?
0

15.2 -z -n

[root@web ~]# name=""
[root@web ~]# [ -z $name ]
[root@web ~]# echo $?
0
[root@web ~]# [ ! -z $name ]
[root@web ~]# echo $?
1
[root@web ~]# name="alex"
[root@web ~]# [ -z $name ]
[root@web ~]# echo $?
1
[root@web ~]# [ -n $name ]
[root@web ~]# echo $?
0

-z 案例:

read -p "请输入名字" name1 
[ -z $name1 ] && echo "请输入姓名否则不继续执行" && exit
read -p "请输入年龄" age1
echo $name1 $age1

15.3 正则比对

[[]]
[root@web01 scripts]# [ "$USER" = "root" ]
[root@web01 scripts]# echo $?
0
[root@web01 scripts]# [[ "$USER" =~ ^r ]]
[root@web01 scripts]# echo $?
0
[root@web01 scripts]# [[ "$USER" =~ t$ ]]
[root@web01 scripts]# echo $?
0
[root@web01 scripts]# [[ ! "$USER" =~ t$ ]]
[root@web01 scripts]# echo $?
1

15.4 判读传参的参数是否为整数

方法1
[root@web01 scripts]# age=188
[root@web01 scripts]# 
[root@web01 scripts]# 
[root@web01 scripts]# [[ "$age" =~ ^[0-9]+$ ]]
[root@web01 scripts]# echo $?
0
[root@web01 scripts]# age=188q
[root@web01 scripts]# [[ "$age" =~ ^[0-9]+$ ]] && echo $?
[root@web01 scripts]# [[ "$age" =~ ^[0-9]+$ ]] || echo $?
1
[root@web01 scripts]# age=18.8
[root@web01 scripts]# [[ "$age" =~ ^[0-9]+$ ]]
[root@web01 scripts]# echo $?
1
方法2
expr $1 + 0 >/dev/null 2>&1
[ $? -ne 0 ] && exit

16.多整数比对

-a and
-o or

[ 10 -eq 10 -a 100 -ne 100 ]
[root@web01 scripts]# [ 10 -eq 10 -a 100 -ne 100 ]
[root@web01 scripts]# echo $?
1
[root@web01 scripts]# [ 10 -eq 10 -a 100 -eq 100 ]
[root@web01 scripts]# echo $?
0
[root@web01 scripts]# [ 10 -eq 10 -o 100 -ne 100 ]
[root@web01 scripts]# echo $?
0

[root@web01 scripts]# [[ 10 -eq 10 && 100 -ne 100 ]]

[root@web01 scripts]# [[ 10 -eq 10 -a 100 -ne 100 ]]
-bash: 条件表达式中有语法错误
-bash: `-a' 附近有语法错误

[root@web01 scripts]# [[ 10 -eq 10 && 100 -ne 100 ]]
[root@web01 scripts]# echo $?
1
[root@web01 scripts]# [[ 10 -eq 10 || 100 -ne 100 ]]
[root@web01 scripts]# echo $?
0

案例:

传入两个数字 比对两个数字的大小 
例如 
sh count.sh 10 10	要求判读是否传入两个参数 要求数字加判读是否为整数(禁止if)
10=10
#!/bin/sh
[ $# -ne 2 ] && echo "please input two number" && exit
[[ ! $1 =~ ^[0-9]+$ ]] && echo "请输入整数" && exit 50
[[ ! $2 =~ ^[0-9]+$ ]] && echo "请输入整数" && exit 100
[ $1 -eq $2 ] && echo "$1=$2"
[ $1 -gt $2 ] && echo "$1>$2"
[ $1 -lt $2 ] && echo "$1<$2"

案例:

批量创建用户 批量创建10个用户 oldboy1 oldboy2 oldboy3...oldboy10
要求密码统一设置为123456
1.输入用户的前缀 oldboy
判断如果为空 则退出
2.输入需要创建用户的个数 10
判断是否为整数
[root@web01 scripts]# cat useradd.sh
#!/bin/sh
#read -p "please input prefix: " name
#read -p "创建的个数: " num
for i in {1..10}
do
        echo oldboy$i
done

[root@web01 scripts]# cat useradd.sh 
#!/bin/sh
read -p "please input prefix: " name
read -p "创建的个数: " num
for i in `seq $num`
do
        useradd $name$i >/dev/null 2>&1
        echo 123456|passwd --stdin $name$i &>/dev/null
        [ $? -eq 0 ] && echo "$name$i create is ok"
done

案例:

判断当前10.0.0.0/24网络中 有哪些IP地址在线 ping通则在线
[root@web01 scripts]# cat ping.sh 
#!/bin/sh
[ -f /etc/init.d/functions ] && . /etc/init.d/functions
for i in `seq 254`
do
        { IP=10.0.0.$i
        ping -c 1 -W 1 $IP >/dev/null 2>&1
        [ $? -eq 0 ] && action "ping $IP is" /bin/true
        } &
done

10.0.0.1-254都通 网卡可配置多个IP

网络相关

ip addr add 10.0.0.3/24 dev eth0 临时生效 重启失效
面试题 配置一条默认网关
route add default gw 10.0.0.254
删除网关
route add default gw 10.0.0.254
其他方法 静态路由方式
ip route add 0/0 via 10.0.0.254
策略路由
服务器使用vpn常用 网关被替换成vpn
pptpstup 拨号命令
查看网关
route -n
开机启动配置文件(/etc/rc.local) +x 权限 rc.d/rc.local (禁止使用alias和变量)

17.if判断

单分支
if [你有房];then	[ -f file ] && echo ok

if [你有房]
then
我就嫁给你
fi

双分支
if [ 你有房 ]	[ -f file ] && echo ok || echo error
then
我就嫁给你
else
拜拜
fi

多分支
if [ 你有房 ]
then
        我就嫁给你
elif [ 你有钱 ]
then
        我也嫁给你
elif [ 你爸是李刚 ]
then
        我也嫁给你
elif [ 活好!运维技术好 ]
then
        我倒贴也嫁给你
elif [ 你在老男孩学运维 ]
then
        我考虑考虑
else
        拜拜
fi

案例: 输入两个数字 是否为整数 使用if方式

#!/bin/bash
read -p "请输入第一个数字:" num1
read -p "请输入第二个数字:" num2
if [ -z $num1 ]
then
        echo "您输入的第一个数字为空"&& exit
elif [ -z $num2 ]
then
        echo "您输入的第二个数字为空"&& exit
elif [[ "$num1" =~ ^[0-9]+$ && "$num2" =~ ^[0-9]+$ ]]
then

        if [ $num1 -lt $num2 ]
        then
                echo "$num1<$num2"
        elif [ $num1 -gt $num2 ]
        then
                echo "$num1>$num2"
        else
                echo "$num1=$num2"
        fi
else
        echo "您输入了错误的值!"&& exit
fi 

案例: 根据操作系统不同的版本安装不同的源

1. 如何取出版本号
2. 如何做版本号的比对
3. 比对完成执行相对应的安装源
[root@web scripts]# cat yum.sh 
#!/bin/sh
ve=`cat /etc/redhat-release |awk '{print $(NF-1)}'`
#centos6.x使用以上命令获取不到版本号
if [ ${ve%%.*} -eq 7 ]
then
        #判断网络是否通畅ping 如果不通 则重启systemctl restart network 通继续执行
        mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
        #测试wget是否已安装 无安装先安装wget
        wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
elif [ ${ve%%.*} -eq 6 ]
then
        mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
        wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-6.repo
fi

案例:猜数字 笔试题

生成一个随机数1-100之间
RANDOM 随机数的范围 0-32767
取余
echo $((RANDOM%100+1))
用户输入一个数字
判断用户输入的数字如果相等则退出提示猜对了 大了 提示比随机数大 小了 提示 比随机数小

[root@web scripts]# cat ran.sh 
#!/bin/sh
ran=`echo $((RANDOM%100+1))`
while true
do
        let i++
        read -p "请输入一个数字[1-100]: " num
if [ $num -gt $ran ];then
        echo "你输入的数字大了"
elif [ $num -lt $ran ];then
        echo "你输入的数字小了"
else
        echo "恭喜你猜对了 总共猜了 $i 次"
        exit
fi
done

案例: 反向破解RANDOM 字符串比较

[root@web scripts]# echo $RANDOM
6500
[root@web scripts]# echo $RANDOM|md5sum|cut -c1-8
98f23d45
[root@web scripts]# echo 1|md5sum 
b026324c6904b2a9cb4b88d6d61c81d1 -
[root@web scripts]# echo 1|md5sum |cut -c1-8
b026324c
[root@web scripts]# echo $RANDOM|md5sum|cut -c1-8
abafad14
[root@web scripts]# echo $RANDOM|md5sum|cut -c1-8
312c404c
[root@web scripts]# echo $RANDOM|md5sum|cut -c1-8
02ab2b9b
[root@web scripts]# echo $RANDOM|md5sum|cut -c1-8
ab1e7ee2
[root@web scripts]# echo 1|md5sum |cut -c1-8
b026324c

18. case 流程控制语句

case 变量名4 in
        模式匹配1)
                命令的集合
                ;;
        模式匹配2)
                命令的集合
                ;;
        模式匹配3)
                命令的集合
                ;;
        *)	*的下一行不需要有;;
                echo USAGE[$0 1|2|3]
esac
[root@web scripts]# cat case.sh 
#!/bin/sh
case $1 in
        Linux)
                echo linux......
                ;;
        Shell)
                echo Shell......
                ;;
        MySQL)
                echo MySQL.....
                ;;
        *)
                echo "USAGE $0 [Linux|Shell|MySQL]"
esac

case 批量删除用户

[root@web scripts]# cat casedel.sh
#!/bin/sh
read -p "请输入用户名前缀: " prefix
read -p "请输入要删除几个用户: " num
for i in `seq $num`
do
        echo $prefix$i
done
read -p "你确定要删除以上用户吗?[y|yes|YES|n|N|no]" ready

for n in `seq $num`
do
        name=$prefix$n
        case $ready in
        y|yes|YES)
                id $name &>/dev/null
                if [ $? -eq 0 ];then
                        userdel -r $name
                        [ $? -eq 0 ] && echo "$name del is ok"
                else
                        echo "id: $name: no such user"
                fi
                ;;
        n|N|no)
                echo "不删除我玩啥呢?" && exit
                ;;
        *)
                echo "USAGE $0 [y|yes|YES|n|N|no]"
        esac
done

菜单

[root@web scripts]# cat menu.sh
#!/bin/sh
echo -e	"\t\t#########################"
echo -e	"\t\t#\t1.系统负载\t#"
echo -e	"\t\t#\t2.磁盘使用率\t#"
echo -e	"\t\t#\t3.内存使用率\t#"
echo -e	"\t\t#\t4.当前登录用户\t#"
echo -e	"\t\t#\t5.当前eth0的IP\t#"
echo -e	"\t\t#\t6.显示菜单\t#"
echo -e	"\t\t#########################"
menu(){
cat<<EOF
        1.u 系统负载
        2.d 磁盘使用率
        3.f 内存使用率
        4.w 当前登录用户
        5.ip 当前eth0的IP
        6.h 显示帮助(菜单)
        7.q 退出
EOF
}
menu
while true
do
        read -p "请输入你想要查看的系统信息的编号: " num
        case $num in
                1|u)
                        uptime
                        ;;
                2|d)
                        df -h
                        ;;
                3|f)
                        free -h
                        ;;
                4|w)
                        w
                        ;;
                5|ip)
                        ip add
                        ;;
                6|h)
                        clear
                        menu
                        ;;
                7|q)
                        exit
                        ;;
                *)
                        menu
        esac
done

案例:

Nginx 启动脚本 jumpserver跳板机
/usr/sbin/nginx	使用命令进行启动后 systemctl 无法管理命令行启动的Nginx

/usr/sbin/nginx 启动
/usr/sbin/nginx -s stop 停止
/usr/sbin/nginx -s reload 重新加载\

/usr/sbin/nginx -s stop	重启
sleep 2
/usr/sbin/nginx

自取状态 PID 端口 状态
[root@web scripts]# sh nginxstart.sh status
当前Nginx的PID:116528

[root@web scripts]# cat nginxstart.sh 
#!/bin/sh
. /etc/init.d/functions
en=$1
fun(){
        [ $? -eq 0 ] && action "Nginx $en is" /bin/true || action "Nginx $en is" /bin/false
}
case $1 in
        start)
                /usr/sbin/nginx
                fun
                ;;
        stop)
                /usr/sbin/nginx -s stop
                fun
                ;;
        reload)
                /usr/sbin/nginx -s reload
                fun
                ;;
        restart)
                /usr/sbin/nginx -s stop
                sleep 2
                /usr/sbin/nginx
                fun
                ;;
        status)
                echo "当前Nginx的PID:`ps axu|grep nginx|grep master|awk '{print $2}'`"
                ;;
        *)
                echo "USAGE $0 [start|stop|reload|restart|status]"
esac

jumpserver 跳板机

WEB01=10.0.0.7
WEB02=10.0.0.8
MySQL=10.0.0.51
NFS=10.0.0.31
菜单
            1. WEB01=10.0.0.7
            2. WEB02=10.0.0.8
            3. MySQL=10.0.0.51
            4. NFS=10.0.0.31
            ...
read -p 请输入连接服务器的编号或者是主机名 : num
case $num in
        1|WEB01)
                ssh root@$WEB01 免秘钥登录
esac


[root@web scripts]# cat jumpserver.sh 
#!/bin/sh
menu(){
cat<<EOF
                1. WEB01=10.0.0.7
                2. WEB02=10.0.0.8
                3. MySQL=10.0.0.51
                4. NFS=10.0.0.31
                5|h. 显示菜单
EOF
}
menu
trap "echo 不要乱输入!小心爆炸!" HUP INT TSTP
while true
do
            read -p "请输入连接服务器的编号或者是主机名 :" num
            case $num in
                        1|WEB01)
                                    ssh root@$WEB01 # 免秘钥登录
                                    ;;
                        2|WEB02)
                                    ssh root@$WEB02 # 免秘钥登录
                                    ;;
                        5|h)
                                    clear
                                    menu
                                    ;;
                        woshiyunwei)
                                    exit
                                    ;;
                        *)
                                    echo "USAGE:[WEB01|1|WEB02|2|h]"
            esac
done

19. for循环

for 变量名 in [取值列表] 苹果 香蕉 梨 桃子 西瓜 字符串 数字{}序列 命令
do
        命令体
        echo 呵呵
done

案例:使用for循环创建用户

cat user.txt
zs
ls
em
oldboy

[root@web scripts]# cat for1.sh 
#!/bin/sh
for i in `cat user.txt`
do
        useradd $i
done

命令行中使用for循环批量删除用户

for i in `cat user.txt`;do userdel -r $i;done

案例2:笔试题

使用for循环 从1加到100 结果5050

seq -s + 100|bc

[root@web scripts]# cat ping.sh 
#!/bin/sh
[ -f /etc/init.d/functions ] && . /etc/init.d/functions
for i in `seq 254`
do
            IP=10.0.0.$i
            ping -c 1 -W 1 $IP >/dev/null 2>&1
            [ $? -eq 0 ] && action "ping $IP is" /bin/true
done

for i in `seq 100`;do sum=$[sum+i];done;echo $sum

20. while循环

while [ 条件表达式 ]
do
            命令
done

案例:

1加到100
#!/bin/sh
i=0
while [ $i -le 100 ]
do
            sum=$[i+sum]
            let i++
done
echo $sum

while 读行

while read line	line 变量名 按行读取文件的内容 for循环是按照空格分隔读取文件内容
do
            命令
done<user.txt

从文件中读取用户和密码,批量创建用户

[root@web scripts]# cat while3.sh 
#!/bin/sh
. /etc/init.d/functions
while read line
do
                user=`echo $line|awk '{print $1}'`
                useradd $user
                pass=`echo $line|awk '{print $2}'`
                echo $pass|passwd --stdin $user &>/dev/null
                [ $? -eq 0 ] && action "$user create is ok" /bin/true
done<user.txt

判断一个文件中总共的行数
统计行号

[root@web scripts]# cat while4.sh
#!/bin/sh
while read line
do
                let i++
done</etc/passwd
echo $i

21. 流程控制语句 exit continue break

exit 退出整个脚本 不会继续执行
break 跳出本次循环 继续往下执行 跳出循环体
continue 结束当前此次的命令,继续下一次循环

[root@web scripts]# cat exit.sh
#!/bin/sh
while true
do
                echo ok
                exit
                echo hehe
done
echo done......

[root@web scripts]# break.sh
#!/bin/sh
while true
do
                echo ok
                break 
                echo hehe
done
echo done......

[root@web scripts]# continue.sh 
#!/bin/sh
while true
do
                echo ok
                continue
                echo hehe
done
echo done......

案例2:

[root@web scripts]#  cat break.sh
#!/bin/sh
for i in `seq 10`
do
                user=oldboy$i
                id $user &>/dev/null
                if [ $? -ne 0 ];then
                        useradd $user
                        [ $? -eq 0 ] && echo "$user create is ok"
                else
                        break
                fi
done
echo hehe.......


[root@web scripts]# cat continue.sh
#!/bin/sh
for i in `seq 10`
do
                user=oldboy$i
                id $user &>/dev/null
                if [ $? -ne 0 ];then
                        useradd $user
                        [ $? -eq 0 ] && echo "$user create is ok"
                else
                        continue
                fi
done
echo hehe.......

22. 函数

命令的集合 完成特定功能的代码块
模块化 复用
函数和变量类似 只有先定义才可以调用,如果只定义不调用 则不会执行

函数的定义和调用
三种方法

[root@web scripts]# cat fun.sh 
#!/bin/sh
test1(){
            echo "第一种函数定义方式"
}
function test2(){
            echo "第二种函数定义方式"
}
function test3 {
            echo "第三种函数定义方式"
}
test1
test2
test3

函数的传参 不能直接传参

  1. 在函数名的后面跟参数
  2. 全局配置 在函数的最上面 设置变量
  3. local 只在函数体内部生效
fun(){
            if [ -f $1 ];then
                    echo "$1 is exsis"
            else
                    echo "$1 is no ex"
            fi
}
fun $1

[root@web scripts]# cat fun.sh 
#!/bin/sh
fun(){
            if [ -f $1 ];then
                        echo "$1 exists"
            else
                        echo "$1 no exists"
            fi
}
fun $2 $3


#!/bin/sh
fun(){
            num=20
            for i in `seq 10`
            do
                    sum=$[num+i]
            done
            echo $sum
}
fun

[root@web scripts]# cat fun1.sh
#!/bin/sh
fun(){
            num=20
            for i in `seq $1`
            do
                    sum=$[num+i]
            done
            echo $sum
}
fun $3 $1 $2

[root@web scripts]# cat fun1.sh 
#!/bin/sh
fun(){
                num=20
                for i in `seq $1`
                do
                        sum=$[num+i]
                done
                echo $sum
}
fun $1
echo $num

以下错误 先定义 在调用
[root@web scripts]# cat fun1.sh
#!/bin/sh
fun $1
fun(){
                num=20
                for i in `seq $1`
                do
                        sum=$[num+i]
                done
                echo $sum
}
函数的返回值 return

#!/bin/sh
[ -f /etc/hosts ] && exit 50 || exit 100

#!/bin/sh
fun(){
                if [ -f $1 ];then
                        return 50
                else
                        return 100
                fi
}
fun $1
re=$?
[ $re -eq 50 ] && echo "$1 该文件存在"
[ $re -eq 100 ] && echo "$1 该文件不存在"

[root@web scripts]# cat fun3.sh 
#!/bin/sh
fun(){
            if [ -f $1 ];then
                    return 50
            else
                    return 100
            fi	
}
fun $1
if [ $? -eq 50 ];then
        echo "ok"
else
        echo "error"
fi

函数内如果执行的上一条是函数名 则不会返回函数本身执行的返回值

[root@web scripts]# cat fun4.sh
#!/bin/sh
fun(){
            echo 50
            return 1
}
re=`fun`
echo "函数的返回值是?: $?"
echo "函数执行的结果是?: $re"

[root@web scripts]# sh fun4.sh
函数的返回值是?: 1
函数执行的结果是?: 50

[root@web scripts]# cat fun4.sh
#!/bin/sh
fun(){
            echo 50
            return 1
}
re=`fun`
name=oldboy
echo "函数的返回值是?: $?"
echo "函数执行的结果是?: $re"

[root@web scripts]# sh fun4.sh
函数的返回值是?: 0
函数执行的结果是?: 50

posted on 2019-08-06 19:25  miss_xxy  阅读(205)  评论(0编辑  收藏  举报

导航

levels of contents