77.shell 1:
10,20s/^/#/g 10到20行加上#
d^ 删除光标前面的
d$ 删除光标后面的
dw 删除两个分隔符之间的文字
3yy p
0.Shell简介
1.为什么要学习Shell (工作职责 )
1)安装操作系统(1.手动安装2.工具自动化安装(kickstart cobbler) 3. 网络安装)
2)系统优化(面试)关闭SElinux
Firewalld (防火墙工作中必须开启的对外的场景)内部的测试服务器无所谓,SsH优化
加大文件描述符内核参 数优化yum源安装常用的软件ntp时间同步字符集调整....
在工作中系统优化全部是以脚本的方式运行
3 )安装服务Nginx apache (yum install httpd) PHP MySQL keepalived Zabbix SErsync NES
Redis Mongo Memcache KVM Docker K8S
ELK
使用脚本安装工
4)修改配置文件,启动服务( systemct start stop reload restart status )
公司自主研发(使用py开发的程序)
5)日志监控日志切割脚本+定时任务( rsync+sersyne) 脚本+定时任务ELK
6)日志统计使用三剑客+命令做日志分析
7)数据备份数据库备份存三份
8) zabbix(常用) Nagios (交换路由大型公司宽带运营商使用)Cacti (重要 监控流量)
脚本把数据统计出来使用zabbix进行监控
2.学习Shell所需的知识
1) xshell CRT
2)Linux常用的基础命令
1. Shell入门
1)什么是Shell
[root@web01 /etc/zabbix/zabbix_agentd.d]# cat /etc/shells
/bin/sh
/bin/bash
/usr/bin/sh
/usr/bin/bash
/bin/tcsh
/bin/csh
命令解释器,负责翻译我们输入的命令,执行成功返回给用户
面试题: linux 默认的Shell是(bash )
交互式:用户输入命令,bash负责把我们的命令翻译成内核可识别的语言,返回结果到屏幕
非交互式:不与用户进行交互,执行文本里的内容,执行到文件的末尾,结束
2)什么Shel1脚本
命令的集合命令大礼包很多可执行命令放在文本中称为shell脚本(包含条件表达式
判断语句数组等等)
语言种类: C C++ python JAVA perl go PHP
会python还需要会shell么? 需要
2.shell脚本规范?(规范为了自动化)
1.必须放在同一的目录
2.脚本必须以.sh结束
3.脚本开头有注释#!/bin/bash必须是第一行 以外都是注释
4.脚本的注释信息代码块的注释
5.建议注释使用中文
6.成对的符号一次性写完
7.脚本名称最好建明知意
3.shell特殊位置变量
$0 代表了脚本的名称 如果全路径执行 则脚本名称待全路径
grep ‘$0‘ /etc/init.d/network
basename test.sh # 获取脚本名称
$n sh test.sh oldboy # 就是脚本后面的第n个参数 ${9}之后需要将{},表示一个整体
$# 获取脚本传参的总个数 对参数总个数做控制
[ $# -ne2 ] $$ echo "请输入两个参数" $$ exit # &&前面成功才执行后面的
$* 获取脚本所有的参数 不加引号和$@相同 加上引号 真把参数视为一个参数$1$2$3
$@ 获取脚本所有的参数 不加引号和$*相同 加上引号 真把参数视为独立参数 $1 $2 $3
$@和$*在脚本中相同 再循环体中不同
[root@web01 scripts]# for i in "$*";do echo $i;done
I am lizhenya teacher
[root@web01scripts]# for i in"$@";do echo $i;done
I am
lizhenya
teacher
$? 获取上一天命令的返回结果 0未成功 非0失败 ****
$$ 获取脚本的PID
kill `cat nginx.pid`
$! 获取上一个脚本后台运行的pid
$_ 获取命令左后一个参数 类似esc .
4. 字串的删除和替换
# 从前向后匹配删除 ## 贪婪匹配
[root@oldboy scripts]# echo Surl
www.sina.com.cn
[root@oldboy scripts]# echo ${ur1#*.} # 使用#匹配从*开始到.结束
sina. com. cn
[root@oldboy scripts]# echo ${ur1#*.*.
com. cn
[root@oldboy scripts] #echo ${ur1#*.*.*.}
cn
[roottoldboy scripts]# echo $ {url ##*.}
cn
# 从后向前匹配删除 ## 贪婪匹配
[root@oldboy scripts]# echo $url
www. sina. com. cn
[rootdoldboy scripts] # echo ${ur1%.★}
www. sina.com
[root@oldboy scripts]井echo ${ur1%.*.*}
www. s1na
[root@oldboy scripts]# echo$ {ur1%%.*}
WWwW
# 替换
[root@oldboy scripts]#echo $ur1
www. sina.com.cn
[root@oldboy scripts]# echo $ {ur1/w/a}
aww. sina.com.c cn
[ root@oldboy
scripts] # echo${ur1/ /w/a}
aaa. s1na.com.c cn
5.数值计算
1:expr支持整数运行 # 判断数字是否是整数
expr 1 + 1
expr 1 \* 1
expr 1 + $num >/dev/null 2>&1
[ $? -ne 0 ] $$ echo "请输入整数" $$ exit 1
2:$(()) 整数运算
$((10+10))
3.$[] 整数运算
echo $[10+10]
4:bc 整数小数运算
echo 10+10.5|bc
5.awk 整数小数运算
awk ‘BEGIN{print 1+ 1.5}‘
echo 10 12|awk ‘{print $1*$2}‘
6. shell三种参数方式
# 第一种传参方式 赋值
name=$1
age=$2
echo name age
# 第二种方式 read
read -p "please input name: " name
echo $name
# 第三种方式 $age
echo $1 $2
7. 环境变量字串
字串切片和长度统计
[root@oldboy scripts]# echo $test
i am lizhenya teacher
[root@oldboy scripts]# echo ${test:0:2}
i
[root@oldboy scripts]# echo ${test:0:3}
i a
[root@oldboy scripts]# echo ${test:2:2}
am
[root@oldboy scripts]# echo ${test:1:3}
am
[root@oldboy scripts]# echo ${test:6:10) # 6后面10个字符
izhenya te
[root@oldboy scripts]# echo ${test:5:10}
lizhenya t
试题:
统计以下字符串输出小于3的字符
如何统计字符串长度
[root@oldboy scripts]# echo ${#test}
6
[root@oldboy scripts]# echo $test|wc -L
6
[root@oldboy scripts]# expr length $test
6
[root@oldboy scripts]# echo $test| awk ‘{print length}‘
6
第一种答案
[root@oldboy scripts]# cat for. sh
#! /bin/sh
for i in I am lizhenya teacher I am 18
do
[ ${#i} -lt 3 ]&&echo $i
done
第二种答案awk列方式
echo "I am lizhenya teacher I am 18|xargs n1|awk ‘{if (length<3) print}‘
第三种答案横向判断
echo "I am lizhenya teacher I am 18"| awk‘{for(i=1;i<=NF;i++)if(length($i)<3)print $i}‘、
8.条件表达式
文件测试
test=[] / []
常用
-e file存在则为真
-f file是否为文件
-d file是否为目录是否存在
-x file是否可执行
-r file是否可读
-w file是否可写
-s file是否为socker文件
[root@oldboy scripts]# [-e /etc/hosts ] == test -e /etc/hosts
[root@oldboy scripts]# echo $?
0
[root@oldboy scripts]# [ -e /etc/hostssss ]
[root@oldboy scripts]# echo $?
0
[root@oldboy scripts]# [ -f /etc/hostssss ]
[root@oldboy scripts]# echo $?
1
[root@oldboy scripts]#[ -f /etc/hostssss ] && echo ok || echo error 返回0执行&&后命令,否则执行||后命令
error
[root@oldboy scripts]# [ -f /ete/hosts ] && echo ok || echo error
ok
[root@oldboy scripts]# [ -d /ete/hosts ] && echo ok || echo error
error
# 加载函数库
./etc/init.d/functions
[ -d /backup] $$ action "Nginx start is" /bin/true || actions "Nginx start is" /bin/false
数值比较
语法格式[数值1比较符数值2 ]
比较符
-eq 等于
-ne 不等于
-gt 大于
-ge 大于等于
-lt 小于
-le 小于等于
[[]] 建议使用== != > < >= <=比较符
[rooteoldboy scripts]#↓10 -eq10 ] && echo $?|| echo $?==[10 -eq 101:echo $?
案例1:磁盘使用率
#!/bin/bash
disk=`df -h|grep /$|awk ‘{print $(NF-1)}‘`
[ ${disk%\%} -gt 80 ] && echo "磁盘使用超过百分之八十,当前使用率$disk" || echo "操盘正常,当前使用率$disk"
案例2:内存使用率
[root@web01 ~]# [ `free|awk ‘NR==2{print ($3/$2)*100}‘|awk -F. {print $1}` -gt 5] $$ echo mail|| error
27.693
案例3:统计负载情况 一种负载大于3 报警发邮件
[root@web01 ~]# ab -n 200000 -c 20000 http://127.0.0.1/index.html # -n总次数 -c并发次数
[root@web01 ~]# uptime|awk -F ‘[ ,.]+‘ ‘{print $12}‘
21
9.多整数比较
[root@web01 ~]# [ 10 -ge 10 -a 10 -gt 5 ] && echo "成立" || echo "不成立"
成立
[root@web01 ~]# [ 10 -ge 10 -o 10 -gt 5 ] && echo "成立" || echo "不成立"
成立
[root@web01 ~]# [ 10 -ge 10 -o 10 -gt 5 -a 100 -ge 101 ] && echo "成立" || echo "不成立"
成立
[root@web01 ~]# [[ 10 -ge 100 && 199 -lt 200 ]] && echo "成立" || echo "不成立"
不成立
[root@web01 ~]# [[ 10 -ge 100 || 199 -lt 200 ]] && echo "成立" || echo "不成立"
不成立
78.shell2:
10.环境变量
1)什么是环境变量
x=1 y=x+1 xy===变量名称等号右边=- =变量值 =赋值
右边一堆内容,使用一个名字来代替称为环境变量
2)环境变量分类
1.环境变量(全局变量)
2.普通变量(局部变量)
按照生命周期划分两类
永久的需要在环境变量文件中配置/etc/porfile永久生效
临时的使用export声明即可临时生效重启失效
test=lizhenya中只对当前的bash生效
export test= lizhenya对(当前)所有的bash生效
写入/etc/profile针对所有用户和bash生效
补充:
如何查看变量
env
Set
变量生效顺序 # 按顺序
/etc/profile开机所有用户加载此文件
. ~/.bashrc
. bash_ profile
.bashrc
/etc/bashrc
3)设置在如下文件中
/etc/profile开机所有用户加载此文件
. ~/.bashrc
. bash_ profile
.bashrc
/etc/bashrc
11.字符创比较
[root@web01 ~]# [ "$USER" == ‘root‘ ] && echo 1 ||echo 0
1
-n STRING the length of STRING is nonzero 字符串长度不为0,返回真
-z STRING the length of STRING is zero 字符串长度为0,返回真
[root@web01 ~]# [ -z "fdsf" ]
[root@web01 ~]# echo $?
1
[root@web01 ~]# [ -n "fdsf" ]
[root@web01 ~]# echo $?
0
-z案例:判断是否为空,必须得输入字符,不输入则退出
#! /bin/sh
read -P 请输入要更改的主机名:”name
[ -z $name ] && echo "请输入主机名称" && exit
案例:判断是否为整数
expr 1 + 变量
xBF -ne01e echo "请输入整数"“exit
12.正则比对
需要使用[[] ]
[rootroldboy scripts]# [[ $USER =~ ^r ]] # ~后面必须有空格
[roottoldboy scripts]# echo $?
[rooteoldboy scripts]# [[ $USER =~ ^1 ]]
[roottoldboy scripts]# echo $?
1
[roottoldboy scripts] # [[ ! $USER=~ ^1]] # !后面必须有空格
[root@oldboy scripts]# echo $?
0
[roottoldboy scripts]#test=123
[root@oldboy scripts]# [[ $test =~^[0-9]+$ ]]
[root@oldboy scripts] #
[root@oldboy scripts]# echo $?NH
[root@oldboy scripts]# test=123qqq
[rooteoldboy scripts] # [[ $test =~ ^[0-9]+$ ]] # 判断是否为整数
[rooteoldboy scripts]# echo
案例1:
使用三种传参方式 比较两个数值的大小打了提示大了 小提示小了
[root@web01 /server/scripts]# cat bijiao.sh
#!/bin/bash
read -p "请输入一个整数" num1 num2
[ -z $num1 -o -z $num2 ] && echo "不能输入空" && exit
[[ ! $num1 =~ [0-9]+$ && ! $num2 =~ [0-9]+$ ]] && echo "请输入整数" && exit
[ $num1 -gt $num2 ] && echo "$num1大于$num2" || echo "$num1小于等于$num2"
案例2:使用脚本统计出 系统的名称 服本号 内核版本 虚拟平台 lo IP地址 eth0 IP地址 外网ip地址 当前磁盘使用率当 前内存使用率
当前负载
shtestah
oldboy
ethOIP地址为: 10.0.0.7
外网Ip地址:cur1 cip.cc
案例3:linux添加默认路由 添加多个IP地址
route add default gw 192.168.31.44 # 添加默认路由
route del default gw 192.168.31.44
ip route add 0/0 via 192.168.31.44 # 添加默认路由
ip route del 0/0 via 192.168.31.44
ip add add 192168.31.33/24 dev eth0 # 添加ip地址
ip add del 192168.31.33/24 dev eth0 # 删除ip地址
ip ro list # 查看策略路由
cat /etc/iproute2/rt_tables # 策略路由表
[root@web01 /server/scripts]# cat /etc/iproute2/rt_tables|grep -v "^#"
255 local
254 main
253 default
0 unspec
200 test # 比前面的小,优先级就高
# 添加一个表 给这个表设置一个路由
ip route add 0/0 via 10.0.0.254 table test # 只要是table中的都走的是10.0.0.254这个网关
ip rule add from 10.0.0.1 table test # 只要从10.0.0.1进来的路由,使用test表中定义的网关出去
13.循环
for i in [取值列表] 数字 字符串 命令的结果`` 序列
do
要执行的命令
done
ping -c2 -W1 10.0.0.2 -c次数 -W等一秒
1.批量pingip
for i in {1..200}
do
{
ping -c1 -W1 192.168.31.$i >/dev/null 2>&1
[ $? -eq 0 ] && echo $IP
} &
done
wait
echo "ping完成"
2.批量创建用户
read -p ‘please input prefix‘ pre num
[ -z $pre ] && echo "请输入pre" && exit
[[ ! $num =~ [0-9]+$ ]] && echo "请输入整数" && exit
for i in `seq num`
do
user add $per$i
[ $? -eq 0 ] && echo "创建成功" || ehco "创建失败"
echo 123456|passwd --stdin >/dev/null 2>&!
done
14.if判断
if [ niyouqina ]
then
echo 1
if
#
if [ 你是啥不 ]
then
echo 2
elif [ 你有房 ]
echo 3
fi
#
if [ niyouqina ];then
echo 1
elif [ nishis ];then
echo 2
elif [ afdsf ];then
echo 3
elif [ fadsffas ]; then
echo 4
else
echo XXXX
if
总结:
单分支 一个条件 一个结果
多分支 多个条件 多个结果
案例1:判断输入的两个数字的大小输出结果
[ $num -eq $num2 ] && echo $num =$num2
read -P请输入两个整数” num1 num2
if [ $num1 -gt $num2 ];then
echo $nurml > $num2
elif [ $num1 -lt $nlum2 ];then
echo S num1< S num2
else
echo $num1 = $ num2
fi
[root@web01 /server/scripts]# echo $((RANDOM%100+1)) # 生成随机数100表示100以内,最多只有五位
81
案例2:先输出一一个随机数,read猜随机数
如果你输入的小了则提示小了脚大了就提示大了如果成功则提示猜对了
echo "$RANDOM*100+1 ”
[root@oldboy scripts]# cat ran. sh
#!/bin/sh
ran= echo $ ( (RANDOMA100+1) )
while true
do
let i++
read -P "请输入你要猜的数字:”num
if[ $num -gt $ran];then
echo "比随机数大了”
elif [ $num -lt $ran ] ; then
echo比随机数小了”
else
echo"恭喜你猜对了总共猜了$i次"
exit
fi
done
案例3:按照不同的centos版本安装不同的yum源
1.当前什么版本如何取出来
2. if判断如果是6则安装6的yum源7安装7yum源5的安装5的yum源
[root@oldboy scripts]# cat osversion. sh
#!/bin/sh
os=`cat /etc/redhat-releasel awk ‘{print $ (NF-1)}‘`
[ "$os"== "xxx"] && os=取centos6版本的命令
if[ ${os%%.*} -eq 7] ;then
which wget >/dev/nu11 2> &1
[ $? -ne 0] && yum-Y install wget
#mv letc/yum. repos. d/Centos-Base. repo /etc/yum. repos. d/Centos-Base. repo.backup
#wget -。/etc/yum. repos.d/Centos-Base. repo http; , /mirrors. aliyun, com/repo/centos-7.repe
echo "yum install is done.
elif [ ${os%%.*} -eq 6] ;then
which wget > /dev/nu11 2>&1
[ $? -ne 0 ]&& yum -y install wget
wget -0 /etc/yum. repos.d/Centos-Base.repo http://mirrors. aliyun.com/repe/centes-6.r.p2
else
which wget > /dev/nu11 2>&1
[ $? -ne 0 ] && yum -y install wget
wget -。/etc/yum. repos.d/Centos-Base.repo http://mirrors.aliyun.com/repe/centos-5.repe
fi
案例4:菜单
菜单的使用方法:
[root@oldboy scripts]# sh menu.sh
##############1.PHP install5.5 #######
##############2.PHP install5.7 #######
##############3.PHP instal17.1 #######
##############4.PHP install7.2 #######
cat<< E OF
1.INSTALL PHP5.5
2.INSTALL PHP5.6
3.INSTALL PHP7.1
4.INSTALL PHP7.2
EOF
79.shell3:
15.case
结构
变量 == 名字 自己起的 脚本名称 $1 $2
case $1 in if [ $1 == oldboy ];then echo
模式1)
命令大礼包
;;
模式2)
命令大礼包
;;
模式3)
命令大礼包
;;
*)
echo 没有匹配
esac
案例1:批量删除用户(if也可以)
1.删除用户的前缀read -p "prefix" pre
2.删除用户的数量 read -p "num" num
[root@web01 /server/scripts]# cat userdel_.sh
#!/bin/bash
read -p "prefix" pre num
for i in `seq $num`
do
echo $per$i
done
read -p "确定删除以上用户?y/n" te
for i in `seq $num`
do
user=$pre$i
case $te in
y|Y|yes)
id $user >/dev/null 2>&1
if [ $? -eq 0 ];then
userdel -r $user &>/dev/null
else
echo "id:$user:no such user"
fi
;;
n|N|nO)
exit
esac
done
案例2:case 使用菜单显示
1.help帮助 答应菜单
2.显示内存使用
3.显示磁盘使用
4.显示系统负载
5.显示登录用户
6.查看ip地址
7.查看Linux-version
[root@web01 /server/scripts]# cat xitong.sh
cat << EOF
1.help帮助 答应菜单
2.显示内存使用
3.显示磁盘使用
4.显示系统负载
5.显示登录用户
6.查看ip地址
7.查看Linux-version
EOF
read -p "请输入要查看的选项:" num
case $num in
1)
echo "欢迎使用"
;;
2)
echo "内存使用了`free|awk ‘NR==2{print $3/$2*100}‘|awk -F. ‘{print $1"%"}‘`"
;;
3)
echo "`df -h|grep ‘/$‘|awk ‘{print $(NF-1)}‘`"
;;
5)
echo "$USER"
;;
6)
echo "`hostname -I|awk ‘{print $1}‘`"
;;
7)
echo "系统版本`cat /etc/redhat-release|awk -F ‘[ .]+‘ ‘{print $4}‘`"
;;
4)
echo "`uptime|awk -F ‘[ ,]‘ ‘{print "1m负载:"$(NF-4), "5m负载:"$(NF-2),"15m负载:"$NF}‘`"
;;
*)
echo "滚"
esac
案例3: Nginx 启动脚本
命令行方式启动Nginx
/usr/sbin/nginx 启动命令
/usr/sbin/nginx stop停止命令
/usr/sbin/nginx -s reload重新加载
# 重启
/usr/sbin/nginx -S stopa
sleep 2
/usr/sbin/nginx
查看状态
手动过滤出监听的端口和Nginx的PID打印输出
[root@web01 /server/scripts]# cat start_ngin.sh
#!/bin/sh
name=$1
[ -f /etc/init.d/functions ] && . /etc/init.d/functions
start(){
/opt/nginx1-12/sbin/nginx &>/dev/null
}
stop(){
/opt/nginx1-12/sbin/nginx -s stop &>/dev/null
}
restart(){
stop
sleep 2
start
}
status(){
echo "`netstat -tunlp|grep nginx|awk ‘{print $4}‘`"
}
reload(){
/opt/nginx1-12/sbin/nginx -s reload &>/dev/null
}
test(){
if [ $? -eq 0 ];then
action "Nginx $name is" /bin/true
else
action "Nginx $name is" /bin/false
fi
}
case $1 in
start)
start
test;;
stop)
stop
test;;
restart)
restart
test;;
reload)
reload
test;;
status)
status;;
*)
echo "USEAG $0 [start|stop|reload|restart|status]"
esac
案例4:跳板机
[root@web01 /server/scripts]# cat jumpersuper.sh
#!/bin/sh
WEB1=172.16.1.7
WEB2=172.16.1.8
WEB3=172.16.1.9
MYAQL=172.16.1.51
NFS=172.16.1.31
menu(){
cat << EOF
1. WEB1=172.16.1.7
2. WEB2=172.16.1.8
3. WEB3=172.16.1.9
4. MYAQL=172.16.1.51
5. NFS=172.16.1.31
6. menu
EOF
}
menu
trap "请不要乱按,小心机器炸了" INT TSTP HUP # 限制ctrl+c或者ctrl+d之类的退命令
while true
do
read -p "请输入需要连接的主机名编号:" num
case $num in
1)
ssh root@$WEB1
;;
2)
ssh root@$WEB2
;;
3)
ssh root@$WEB3
;;
4)
ssh root@$MYSQL
;;
5)
ssh root@$NFS
;;
6)
menu
;;
woshiyunwei)
exit
;;
*)
read -p "请输入需要连接的主机名编号:" num
esac
done
16.while 回顾for
for i in `cat user.txt`;do useradd $i;done
while [ 条件表达式 ]
do
命令
done
案例1:创建用户名密码
while read line # 读一行
do
user=`echo $line|wak ‘{print $1}‘`
pass=`echo $linx|awk ‘{print $2}‘`
useradd $user
echo $pass|passwd --stdin $user
done < user.txt
17.shell的内置命令
exit(直接退出) continue(跳出本次循环,执行下次循环) break(直接退出)
while true
do
echo 123
exit/continue/break
done
案例1:猜随机数
[root@web01 /server/scripts]# cat ran.sh
#!/bin/sh
ran=`echo $((RANDOM%100+1))`
while true
do
let i++
read -p "请输入要猜的数字:" num
if [ $num -gt $ran ];then
echo "比随机数大了"
elif [ $num -lt $ran ];then
echo "比随机数小了"
else
echo "恭喜猜对了 总共才了$i次"
exit
fi
done
18.函数
书写方式:
[root@web01 /server/scripts]# cat fun.sh
#!/bin/sh
test(){
echo "1"
}
function test2(){
echo "2"
}
function test3 {
echo "3"
}
test
test2
test3
传参方式:
[root@web01 /server/scripts]# cat fun.sh
#!/bin/sh
test(){
echo "$1"
}
function test2(){
echo "$1"
}
function test3 {
echo "$1"
}
test $1
test2 $2
test3 $3
[root@web01 /server/scripts]# sh fun.sh 12 23 34
12
23
34
案例1:
[root@web01 /server/scripts]# cat fun_c.sh
#!/bin/sh
count01(){
num=10
for i in `seq 10`
do
total=$[$i + $num]
echo "$total"
done
}
count01
案例2:
[root@web01 /server/scripts]# cat fun_c.sh
#!/bin/sh
count01(){
for i in `seq 10`
do
total=$[$i + $num]
echo "$total"
done
}
num=10
count01
[root@web01 /server/scripts]# sh fun_c.sh 10
结果:20
案例3:
[root@web01 /server/scripts]# cat fun_c.sh
#!/bin/sh
count01(){
for i in `seq 10`
do
total=$[$i + $1]
echo "$total"
done
}
count01 $1
count01 $2
count01 $3
[root@web01 /server/scripts]# sh fun_c.sh 10 20 30
结果:20 40 60
案例4:
[root@web01 /server/scripts]# sh fun_c.sh
函数的状态码是: 1
函数的执行结果是: 100
[root@web01 /server/scripts]# cat fun_c.sh
#!/bin/sh
fun3(){
echo 100
return 1
}
result=`fun3`
echo "函数的状态码是: $?"
echo "函数的执行结果是: $result"
案例5:
[root@web01 /server/scripts]# sh fun2.sh /etc/host
[root@web01 /server/scripts]# echo $?
1
[root@web01 /server/scripts]# cat fun2.sh
file=$1
t_file(){
if [ -f $file ];then
return 0
else
return 1
fi
}
t_file
[ $? -eq 0 ] && echo "$file is ok" || echo "$file is error"
案例6:统计文件行
[root@web01 /server/scripts]# sh fun3.sh /etc/hosts
16
[root@web01 /server/scripts]# cat fun3.sh
#!/bin/bash
file=$1
count(){
local i=0
while read line
do
let i++
done <$file
echo $i
}
count
# 统计文件行数
awk ‘{print NR,$0}‘ /etc/hosts
[root@web01 /server/scripts]# wc -l /etc/hosts
[root@web01 /server/scripts]# cat -n /etc/hosts
[root@web01 /server/scripts]# grep -n . /etc/hosts
[root@web01 /server/scripts]# less -N /etc/hosts
[root@web01 /server/scripts]# sed ‘=‘ /etc/hosts
案例7:中午吃啥?随机生成中午要吃哪一家?
1.黄焖鸡
2.包子
3.炒菜
4.豆浆
5.拉面
6.水饺
7.盖饭
8.撸串
9.沙县
10.不吃了
[root@web01 /server/scripts]# cat etc.sh
#!/bin/bash
num=$((RANDOM%10+1))
case $num in
1)
echo "黄焖鸡"
;;
2)
echo "包子"
;;
*)
echo "随便"
esac
案例8:引入脚本和变量
[rooteoldboy scripts]# cat fun2. sh
count01 () {
for i in `seq 10`
do
total=$[$i+ $ num]
done
echo计算结果是: $total"
}
num=10
count01
我在另外脚本调用你的结果计算结果是:20
10
[root@ol dboy scripts]# cat funtest.sh
#! /bin/sh
. /server/ scripts/fun2.sh > dev/null 2>&1
echo "我在另外脚本调用你的结果清`count01`"
echo $num
80.shell数组:
1.
[root@oldboy ~]# echo $ {array}
linux
[ root@oldboy ~]# array[1]=MySQL
[root@oldboy ~] # array[2]=NES
[root@oldboy ~]# array[3]=She11
[root@oldboy ~]# echo ${array}
1 inux
[rooteoldboy ~]# echo $ {array[3]}
Shell
[root@oldboy ~]# echo ${array[1]}
MySQL
[root@oldboy ~]# echo $ {array[2]}
NFS
[coot@oldboy ~]# echo ${array[*]}
linux MySQL NeS Shell
[root@oldboy ~]# echo ${array[@]} # 获取所有制
inux MySQL NeS shel1
[coot@oldboy ~]# echo ${!array[@]} # 获取索引
0 1 2 3
[root@oldboy ~]# echo ${!array[*]}
0 1 2 3
unset array # 取消数组
[root@web01 /server/scripts]# array=([0]=linux [1]=mysql [2]=shell [5]=nosql)
[root@web01 /server/scripts]# declare -a # 查看所有的变量
2.
[root@web01 /server/scripts]# array=(linux shell mysql)
[root@web01 /server/scripts]# echo ${!array[@]}
0 1 2
案例1:
[root@web01 /server/scripts]# sh arrays.sh
1
2
3
[root@web01 /server/scripts]# cat arrays.sh
#!bin/bash
ip=(
1
2
3
)
for i in ${ip[*]}
do
echo $i
done
3.关联数组
关联数组
字符串作为索引
declare -A 数组名 声明是一个关联数组 (awk中不需要定义关联数组)
declare -A 查看关联数组
declare -A array
array= ([index] =Linux [ index1]=She1l [ index2]=KVM [ suiyiqi]=MySQL)
案例1:命令行统计一行数据出现的次数
[root@oldboy scripts]# let array[f]++
[root@oldboy scripts]# let array[f]++
[root@oldboy scripts] #
[root@oldboy scripts]# echo ${array[m]}
[rooteoldboy scripts]# echo ${array[f]}
2
[root@oldboy ~]# let array[f]++
[root@oldboy ~]# let array[f]++
[root@oldboy ~]# let array[m]++
[root@oldboy ~]# let array[m]++
[root@oldboy ~]# echo ${!array[*]}
f m
[root@oldboy ~]# for i inτ${!array[*]} ;do echo $i ;done
f
m
[root@oldboy ~]# for i in ${!array[*]} ;do echo $ {array[$i]} ;done
2
3
[root@oldboy ~]# for i in ${!array[*]} ;do echo $i,${array[$i]};done
f,2
m, 3
[rooteoldboy ~]# for i in ${!array[*]} ;do echo $i $ {array[$1]》;done
f 2
m 3
案例2:统计文件中某行数据出现的次数
[root@web01 /server/scripts]# sh while.sh
f 3
g 1
m 4
[root@web01 /server/scripts]# cat while.sh
#!/bin/bash
declare -A array
while read line
do
let array[$line]++
done<sex.txt
for i in ${!array[@]}
do
echo "$i ${array[$i]}"
done
4.wak数组
# 统计重复行
[root@web01 /server/scripts]# awk -F: ‘{array[$NF]++}END{for (i in array) print i,array[i]}‘ /etc/passwd
/bin/sync 1
/bin/bash 3
/sbin/nologin 43
/sbin/halt 1
/sbin/shutdown 1
# 统计服务
[root@web01 /server/scripts]# ss -an|awk ‘/:80/{tcp[$2]++}END{for(i in tcp) print i,tcp[i]}‘
LISTEN 1
# 修改分隔符
awk ‘BEGIN{FS=":"}{print $1}‘
# OFS指定输出分隔符
awk ‘BEGIN{FS=":";OFS="---"}{print $1,$2}‘ /etc/passwd
awk ‘BEGIN{print 1/2}{print ok}END{print "game over"}‘
awk -F ":" ‘/66/{print $1}‘ /passwd
awk ‘BEGIN{FS=":"} /66/{print $1}‘ /passwd
awk ‘/\/$/{if ($3>5000) print $4}‘
# Awk工作原理
# awk F: ‘{print $1,$3}‘/etc/passwd
1. awk将文件中的每一行作为输入,并将每一行赋给内部变量$0", 以换行符结束
2. awk开始进行字段分解,每个字段存储在已编号的变量中,从$l开始[默认空格分割]
3. awk默认字段分隔符是由内部FS变量来确定,可以使用-F修改
4. ark行处理时使用了print函數打印分割后的字段
5. awk在打印后的字段加上空格,因为$1,$3 之间有一个逗号.逗号被映射至OFS内部变量中,称为输字段分隔符,售OFS默认为空格.
6. awk输出之后,将从文件中获取另一行,并将其存储在$o中,覆盖原来的内容,然后将新的字符串分隔成字段并进行处理。该过程将持续到所有行处理完毕,
[root@web01 /server/scripts]# awk ‘{print NR, $0}‘ /etc/passwd /etc/hosts
[root@web01 /server/scripts]# awk ‘{print FNR, $0}‘ /etc/passwd /etc/hosts
awk -F":" ‘{print NF,$NF}‘ /passwd
# 输出分隔符
[root@web01 /server/scripts]# awk ‘BEGIN{FS=":";OFS="+++"}/root/{print $1,$3}‘ /etc/passwd
root+++0
operator+++11
# 换行符替换
[root@web01 /server/scripts]# awk -F ":" ‘BEGIN{RS=" "}{print $0}‘ /etc/passwd
[rooteSbell ~]# date| awk ‘{print $2, "5月份-"\n",$NF,"今年"}‘
[rooteshell ~]#axk -F: ‘{print "用户是:"$1"\t "用户uid:"$3 "\t用户gid:"$4)‘ /etc/passed
printf 函数
[rooteSbell ~]# awk -F: ‘{printf "%6-15s %-10s %-15s\n", $1, $2, $3}‘ /etc/passwd
%s字符类型
%d数值类型
占15字符类型
表示左对齐,默认是右对齐
printf默认不会在行尾自动换行,加\n
1.cpu:
https://blog.51cto.com/12758568/2122677 三剑客博客
81:练习
x?1.写出以下Shell特殊位置参数变量的含义(5分)
$0 获取脚本的名字,包含路径
$n $n(n=任意数字)代表脚 本在命令行的第几个参数
$# 获取脚本参数的个数$* 获取当前shell脚本所有传参的参数,如果不加引号作用同$@相同,如果 加上双引号"$*则表示将所有的参数视为单个字符串相当于"$1$2$3" I
$@ 获取当前shell脚本所有传参的参数,不加引号同$*相同,加上双引号则 表示把所有的参数视为不同的独立的字符串
$? 获取执行上一个指令执行状态返回值0为成功非零失败
$$ 获取当前shell脚本的进程号PID
$! 获取上一个在后台工作脚本进程的进程号PID
2.如何定义环境变量
临时: export declare -x ? ?
永久: /etc/profile /etc/bashrc ? ? ? ?
3.定义变量内容,不加引号、单引号、双引号、反引号结果有什么不同?应该怎么用? (5分) ? ?
不加引号:一般纯数字,简单连续的字符串也可以。 ? ?
单引号:所见即所得,看见什么就输出什么。 ? ?
双引号:默认是双引号,连续的字符串数字混合在一起,解析变量。 ? ?
反引号:解析命令
4.写出下面特殊变量扩展的意义(5分)
${oldboy} 输出变量的内容,对变量 有保护作用
${#oldboy} 输出变量的长度。
${url#*.} 从前往后删除匹配最短的任意开头的字符到.的内容 ? ?
${url##*.} 从前往后删除匹配最长的任意开头的字符到.的内容 ? ?
${ur1%.*} 从后往前删除匹配最短的结尾是.开头的内容 ? ?
${url%%.*} 从后往前删除匹配最长的结尾是.开头的内容 ? ? ?
5.数字的整数和小数有哪几种运算方式? ? ? ?
小数:awk bc ? ? ?
整数:expr $(()) $[] ?let 1 + 1
6.写出下面条件测试的含义(5分) ?
[ -e dir|file ] 存在则为真 ?
[-d dir] 目录是否存在 ?
[-f file] 文件是否存在 ?
[-r file ] 文件是否有读权限 ?
[-X file] 文件是否有执行权限 ?
[-W file] 文件是否有写权限
7.写一条判断语句,如果/tmp/oldboy.txt文件不存在则进行创建(5分) ? ?
[ -f /tmp/oldboy.txt] $$ echo "文件存在" || touch /tmp/oldboy.txt ? ? ?
8.查看当前磁盘/使用状态,如果使用率超过80%则把结果输出到/var/log/disk.err? ? ? ?
disk_info=`df -h |grep ‘/$‘|awk {print $5}|wak -F % {print $1}` ? ? ?
if [ $disk_info -ge 80 ] ? ? ?
then ? ?
echo "磁盘是用了$disk_info%" >> /var/log/disk.err ? ? ?
fi ? ? ?
9.批量创建10个用户,密码统一为123,需要对用户输入是否为数字和输入的名称是否为空进行判断? ?
-n STRING the length of STRING is nonzero 字符串长度不为0,返回真
-z STRING the length of STRING is zero 字符串长度为0,返回真
[rootroldboy scripts]# [[ $USER =~ ^r ]]
#!/bin/bash
read -p "请输入用户名前缀和个数:" prefix num
[ -n $prefix and -n $num ]
[ $? ne 0] && echo "请输入前缀和个数" ;exit 1
if [[ !$num =~^[0-9]+$]]
then
echo "确保个数为数字";exit 2
fi
for i in `seq $num`
do
username="$prefix$i"
useradd -M -s $username
passwd 123 $username
if [ $? eq 0 ]
then
echo "$username create ok"
fi
done
10.猜数字随机一个100的数字要求用户数字(判断是否位数字),如果比随机数小则提示比随机数小了,大了则提示比随机数大了,最后统计猜了多少次?
#!/bin/bash
num=`echo $((RANDOM%100+1))`
echo $num
i=0
while true
do
let i++
read -p "请输入数字:" num2
if [[ ! $num2 =~ ^[0-9]+$ ]]
then
echo "请输入数字";exit
fi
if [ $num2 -gt $num ]
then
echo "比随机数大了"
elif [ $num2 -lt $num ]
then
echo "比随机数小了"
else
echo "恭喜猜对了 $num2"
echo "猜了$i次"
exit
fi
done
11.编写菜单
[root@web01 /server/scripts]# cat caidan.sh
#!/bin/bash
caidan(){
cat << EOF
h 显示帮助命令
f 显示登录信息
d 显示磁盘挂载
m 查看内存使用
u 查看系统负载
q 退出程序
EOF
}
caidan
while true
do
read -p "请输入选项:" select
case $select in
h)
clear
caidan
;;
f)
clear
w
;;
d)
clear
df -h
;;
m)
clear
free
;;
u)
clear
uptime
;;
*)
clear
exit 1
esac
done
12:用case语句写出nginx启动脚本
[root@web01 /server/scripts]# cat start_ngin.sh
#!/bin/sh
name=$1
[ -f /etc/init.d/functions ] && . /etc/init.d/functions
start(){
/opt/nginx1-12/sbin/nginx &>/dev/null
}
stop(){
/opt/nginx1-12/sbin/nginx -s stop &>/dev/null
}
restart(){
stop
sleep 2
start
}
status(){
echo "`netstat -tunlp|grep nginx|awk ‘{print $4}‘`"
}
reload(){
/opt/nginx1-12/sbin/nginx -s reload &>/dev/null
}
test(){
if [ $? -eq 0 ];then
action "Nginx $name is" /bin/true
else
action "Nginx $name is" /bin/false
fi
}
case $1 in
start)
start
test;;
stop)
stop
test;;
restart)
restart
test;;
reload)
reload
test;;
status)
status;;
*)
echo "USEAG $0 [start|stop|reload|restart|status]"
esac
13.写一个脚本探测1-254之前存活的主机,输出到ip.txt.
for i in {1..254}
do
ip="192.168.31.$i"
ping $ip -c 1
if [ $? eq 0 ]
then
echo "$ip is exit" >> ip.txt
fi
done
14.shell内置命令的含义
exit 退出整个程序
break 跳出循环
continue 跳出本次循环执行下一次循环
15.普通数组和关联数组的定义方式
普通数组:只能使用整数 作为数索引
关联数组:可以使用字符串作用数组索引
array=(linux shell mysql)
declare -A array
array= ([index] =Linux [ index1]=She1l [ index2]=KVM [ suiyiqi]=MySQL)
16.如何查看数组array元素的和索引的总个数?
echo ${!arrsy[*]} 索引
echo ${#array[*]} 元素
[root@web01 /server/scripts]# array=(1 2 3)
[root@web01 /server/scripts]# echo ${#array[*]}
3
[root@web01 /server/scripts]# echo ${!array[*]}|wc -w
0 1 2
17.统计/var/log/nginx.log里ip访问次数
[root@web01 /server/scripts]# awk ‘NR<=10{print $1}‘ /opt/nginx1-12/logs/access.log|sort -n|uniq -c
6 127.0.0.1
4 192.168.31.68
18.统计下面的话中字母不大于6的单词?
[root@web01 /server/scripts]# tail -1 backup.sh
rsync -az $backup_dir/ rsync_backup@172.16.1.41::backup --password-file=/etc/rsync.password
[root@web01 /server/scripts]# tail -1 backup.sh |awk ‘{for(i=1;i<=NF;i++) if(length($i)>6) k++ ;print k}‘3
[root@web01 /server/scripts]#
方式一:
[root@web01 /server/scripts]# tail -1 backup.sh |awk ‘{for(i=1;i<=NF;i++) {if(length($i)>6) print $i} }‘
$backup_dir/
rsync_backup@172.16.1.41::backup
--password-file=/etc/rsync.password
方式二;
array=(rsync -az $backup_dir/ rsync_backup@172.16.1.41::backup --password-file=/etc/rsync.password)
for n in ${array[*]}
do
if [ ${#n} -lt 7 ]
then
echo $n
else
continue
fi
done
19. 计算从1加到100之和.
[root@web01 /server/scripts]# seq 100|awk ‘{count+=$1}END{print count}‘
5050
20.创建以随机十位字母+oldboy的.html文件,同时将oldboy替换为oldgirl
[root@web01 /server/scripts/oldboy]# ls
adfaffddga_oldgirl.html boy.sh ehcceccbie_oldgirl.html ffeecbhaef_oldgirl.html
bcjfiafida_oldgirl.html cjbdeafcaj_oldgirl.html fbgbeafihe_oldgirl.html gdffaccfgi_oldgirl.html
bhcjfdbbae_oldgirl.html dfbfibdajc_oldgirl.html fdfiejbfad_oldgirl.html
[root@web01 /server/scripts/oldboy]# cat boy.sh
#!/bin/bash
i=1
while [ $i -le 10 ]
do
A=`echo $RANDOM|md5sum|tr ‘[0-9]‘ ‘[a-z]‘|cut -c1-10`
touch `echo ${A}_oldboy.html`
let i++
done
for i in `ls *.html`
do
mv $i `echo ${i/_oldboy/_oldgirl}` &>/dev/null
done
20.抓阄,根据输入随机选择三位同学出来.
[root@web01 /server/scripts/oldboy]# cat zhua.sh
#!/bin/bash
>/tmp/pass
suess(){
echo "下面三位同学去"
cat /tmp/pass|sort -rk2|head -n 3
exit 0
}
while true
do
num=`mkpasswd -s 0 -d 2|sed ‘s/[a-zA-Z]//g‘`
while [ `grep $num /tmp/pass|wc -l` -ne 1 ]
do
read -p "输入你的名字全拼:" name
if [[ ! $name =~ [a-Z] ]]
then
echo "别瞎说了"
break
fi
if [ $name = ‘exit‘ ]
then
suess
fi
if [ `grep $name /tmp/pass|wc -l` -eq 1 ]
then
echo "重名了,请在后面加上数字"
break
fi
echo "你的数字是:$num"
echo -e "$name\t$num" >> /tmp/pass
done
done
52.运维9-shell