Shell 编程总结 第1章 基础知识 1.linux下默认的shell是?
2.shell脚本书写规范?
1.shell脚本存放统一的目录 /server/scripts
2.脚本名字的结尾使用.sh
3.脚本的开头 必须有解释器 #!/bin/bash
4.脚本内有作者信息 脚本信息
5.每段代码块有注释(尽量使用英文)
6.标点符号 (语法尽量一次性书写完毕
7.成对的符号 一次性书写完毕
3.执行脚本的三种方法?
1 2 3 4 5 6 7 8 9 10 [root@backup /server/scripts] hello world! [root@backup ~] hello world! [root@backup /server/scripts] hello world!
4.变量可分为两类?
变量可分为两类:环境变量(全局变量)和普通变量(局部变量)
全局变量(环境变量) 针对系统所有用户生效
局部变量(普通变量) 针对当前登录用户生效
5.如何显示默认的环境变量**
1.使用echo命令查看单个环境变量。例如: echo $PATH
2.使用env查看所有环境变量。例如: env
3.使用set查看所有本地定义的环境变量。
6.如何设置环境变量与局部变量
1.在/etc/profile文件中添加变量【对所有用户生效(永久的)】,注意:修改文件后要想马上生效还要运行# source /etc/profile不然只能在下次重进此用户时生效。
2.在用户目录下的.bash_profile文件中增加变量【对单一用户生效(永久的)】
3.直接运行export命令定义变量【只对当前shell(BASH)有效(临时的)】
7.定义变量内容,不加引号、单引号、双引号、反引号结果有什么不同?应该怎么用?
不加引号:直接定义变量的内容,一般用于连续的数字、字符串、路径名等
单引号:所见即所得,引号内是什么就输出什么
双引号:输出变量内容时引号的变量及命令会经过解析后再输出内容
反引号:一般用于引用命令,执行的时候命令会被执行,相当于S0,赋值和输出都要用引号将命令引起来
8.以下参数含义
参数
含义
$0
获取当前执行的shell脚本的文件名,如果包含路径,则包括脚本路径
$n
获取当前执行脚本的第n个参数值,参数从$1开始 $9 以后需要加{}
$#
获取当前执行的脚本后面接的参数的总个数
$*
脚本所有传参的参数,加双引号将所有参数视为一个整体
$@
脚本所有传参的参数,加双引号将所有参数视为不通的独立字符串
$?
上一个指令的状态返回值(0为成功,非0失败)
$$
当前执行脚本的PID进程号
$!
上一个在后台工作的进程的PID
$_
获取在此之前的命令或脚本的最后一个参数
9.echo参数含义
参数
含义
-n
不换行输出内容
-e
解析转义字符
转义字符
\n
换行
\r
回车
\t
制表符(tab)
\b
退格
\v
纵向制表符
10.变量传参的三种方式?
1.直接传参
2.赋值传参
3.read传参
11.统计字符串长度?
1 2 3 4 5 6 7 8 9 10 I am oldboy 11 11 11 11
12.输出字符串长度小于3的单词
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 [root@backup /server/scripts] #!/bin/bash for i in I am lizhenya teacher I am 18do [ ${#i} -lt 3 ] && echo $i done [root@backup /server/scripts] I am I am 18 [root@backup /server/scripts] I am I am 18 [root@backup /server/scripts] I am I am 18
13.变量子串的删除和替换
1 2 3 4 5 6 7 8 9 [root@backup /server/scripts] I am oldboy [root@backup /server/scripts] [root@backup /server/scripts] am oldboy [root@backup /server/scripts] am
14.写出下面特殊变量扩展的意义
1 2 3 4 5 6 ${oldboy} ${#oldboy} ${url#*.} ${url##*.} ${url%.*} ${url%%.*}
15.常见的Shell算术运算符
算术运算符
意义(*表示常用)
+ 、-
加(或正号)、减(或负号)*
*、/、%
乘法、除法、取余 *
**
冥运算 *
++ 、–
增加、减少,可前置也可放在变量的结尾 *
!、&&、||
非(取反)、相当于and 、相当于or *
< 、<= 、> 、>=
比较符号(小于、小于等于、大于、大于等于)
== 、!= 、=
比较符号 (相等、不相等、对于字符串=也可表示相当于)*
<< 、>>
向左移位、向右移位
~ 、| 、& 、^
按位取反、按位异或、按位于、按位或
= 、+=、-= 、*= 、%=
赋值运算符,例如 a+=1 相当于 a=a+1 , a-=1 相当于 a=a-1 *
16.常见的运算命令
运算操作符号与运算命令
意义
(())
用于整数的运算、效率很高
let
用于证书运算,类似于(())
expr
可用于整数运算,还有其他功能
bc
Linux下的计算程序、可用于整数及小数运算
$[]
用于整数运算
awk
awk既可用于整数运算,也可用于小数运算
declare
定义变量值和属性,-i参数可用于定义整形变量,做运算
17.常用的条件表达式
语法
意义
test -f file
表示如果file文件存在,则为真(0),否则为假(非0)
test -z
表示如果字符串长度是为0,则表达式成立
[ -e file ]
文件存在则为真
[ -f file ]
是否存在并且为普通文件
[ -d file ]
是否为目录
[ -r file ]
是否可读
[ -w file ]
是否可写
[ -x file ]
是否可执行
18.数值表达式
[ 整数1 比较符 整数2 ]
在[]以及test 中使用的比较符号
在(())和[[]] 中使用的比较符号
说明
-eq
== 或 =
等于
-ne
!=
不等于
-gt
>
大于
-ge
>=
大于等于
-lt
<
小于
-le
<=
小于等于
19.循环控制及状态返回值参数
参数
含义
exit
退出脚本
return
退出函数
local
局部变量
breadk
跳出循环体
continue
跳过本次循环,进行下一次循环
第2章 脚本案例 1.查看磁盘/当前使用状态,如果使用率超过80%则把结果输出
1 2 3 4 #!/bin/sh usedisk=`df -h|awk 'NR==2{print $(NF-1)}'` [ ${usedisk%\%} -gt 80 ] && echo "send mail 当前使用为$usedisk" || echo "磁盘使用正常,当前使用率为$usedisk" [ `df -h|awk -F "[ %]+" 'NR==2{print $(NF-1)}'` -gt 5 ] && echo "send mail" || echo "磁盘使用正常"
统计磁盘使用率 如果磁盘使用率大于 5% 则发邮件报警 当前使用率为? 小于5% 则提示磁盘使用正常 当前使用率为?
1 2 3 4 5 6 7 8 [root@backup /server/scripts] #!/bin/sh usedisk=`df -h|awk 'NR==2{print $(NF-1)}' ` [ ${usedisk%\%} -gt 80 ] && echo "send mail 当前使用为$usedisk " || echo "磁盘使用正常,当前使用率为$usedisk " [ `df -h|awk -F "[ %]+" 'NR==2{print $(NF-1)}' ` -gt 5 ] && echo "send mail" || echo "磁盘使用正常" [root@backup /server/scripts] 磁盘使用正常,当前使用率为4% 磁盘使用正常
2.加大文件描述符
1 echo '* - nofile 65535' >>/etc/security/limits.conf
3.使用脚本 统计系统的 主机名 IP地址 虚拟平台 版本号 磁盘使用率 内存使用率 外网IP地址
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 [root@backup /server/scripts] #!/bin/bash eth0=$(ip a|awk 'BEGIN{FS="[ /]+"}/eth0$/{print $3}' ) eth1=$(ip a|awk 'BEGIN{FS="[ /]+"}/eth1$/{print $3}' ) net_IP=$(curl -s ifconfig.me) VMW=$(hostnamectl | awk '/Virtuali/{print $NF}' ) version=$(awk '{print $1,$(NF-1)}' /etc/redhat-release) disk=$(df|awk 'NR==2{print $(NF-1)}' ) mem="$(free|awk 'NR==2{print $3/$2*100}') %" echo "内网IP为:${eth0} " echo "外网IP为:${eth1} " echo "公网IP为:${net_IP} " echo "虚拟平台为:${VMW} " echo "操作系统为:${version} " echo "磁盘使用率为:${disk} " echo "内存使用率为:${mem} " [root@backup /server/scripts] 内网IP为:10.0.1.41 外网IP为:172.16.1.41 公网IP为:113.88.12.225 虚拟平台为:vmware 操作系统为:CentOS 7.4.1708 磁盘使用率为:4% 内存使用率为:10.2867%
4.反向破解 RANDOM 0-32767
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 案例:反向破解 RANDOM 0-32767 d2c74151 a9982990 4462a9fd b195fe48 5e77d38 [root@backup /server/scripts] #!/bin/bash for i in {0..32767}do num1=`echo $i |md5sum|cut -c1-8` [ $num1 = "d2c74151" -o $num1 = "a9982990" -o $num1 = "4462a9fd" -o $num1 = "b195fe48" ]; [ $? = 0 ] && echo "$num1 is $i " num2=`echo $i |md5sum|cut -c1-7` [ $num2 = "5e77d38" ];[ $? = 0 ] && echo "$num2 is $i " done [root@backup /server/scripts] 4462a9fd is 2458 5e77d38 is 2945 d2c74151 is 6420 a9982990 is 13008 b195fe48 is 29193
5.使用if分支 来比较两个数字的大小
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 [root@backup /server/scripts] #!/bin/sh read -p "please input two number: " num1 num2if [[ ! "$num1 " =~ ^[0-9]+$ || ! "$num2 " =~ ^[0-9]+$ ]] then echo "请输入正确的整数" exit fi if [ $num1 -gt $num2 ];then echo "$num1 >$num2 " elif [ $num1 -lt $num2 ];then echo "$num1 <$num2 " else echo "$num1 =$num2 " fi [root@backup /server/scripts] please input two number: 10 20 10<20
6.随机生成一个随机数1-100 判断生成的随机数和输入的随机数是否相等,如果相等则退出,大了提示大了,小则提示小了,总共猜了多少次
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 [root@backup /server/scripts] #!/bin/sh ran=`echo $((RANDOM%100+1))` > ran.txt read -p "请回车开始系统自动猜: " rei=1 case $re in y) while true do ra=`echo $((RANDOM%100+1))` if [ `grep -w $ra ran.txt|wc -l` -eq 1 ];then continue fi if [ $ra -gt $ran ];then echo "系统猜的数字为 $ra 猜大了" echo $ra >> ran.txt elif [ $ra -lt $ran ];then echo "系统猜的数字为 $ra 猜小了" echo $ra >> ran.txt else echo "系统猜对了数字为$ra " echo "总共猜了 $i 次" exit fi let i++ done ;; *) echo hehe esac
7.按照系统版本号的不同 更改默认YUM源
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 [root@backup /server/scripts] #!/bin/sh . /etc/init.d/functions os=`cat /etc/redhat-release |awk '{print $4}' ` if [ "$os " = "(Final)" ] then os=`cat /etc/redhat-release|awk '{print $3}' ` fi ping -c 1 -W1 www.baidu.com &>/dev/null if [ $? -ne 0 ];then systemctl restart network action "请检查网络" /bin/false else if [ ${os%%.*} -eq 7 ];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-7.repo &>/dev/null if [ $? -eq 0 ];then action "yum源已更新完成......." /bin/true else action "yum源更新失败,请检查.." /bin/false exit fi elif [ ${os%%.*} -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 &>/dev/null if [ $? -eq 0 ];then action "yum源已更新完成......." /bin/true else action "yum源更新失败,请检查.." /bin/false exit fi else echo "请检查你的版本号" fi fi [root@backup /server/scripts] yum源已更新完成....... [ OK ]
8.nginx启动脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 [root@backup /server/scripts] #!/bin/sh [ -f /etc/init.d/functions ] && . /etc/init.d/functions te=$1 test (){ if [ $? -eq 0 ];then action "Nginx $te is" /bin/true else action "Nginx $te is" /bin/false fi } case $1 in start) /usr/sbin/nginx test ;; stop) /usr/sbin/nginx -s stop test ;; restart) /usr/sbin/nginx -s stop sleep 1 /usr/sbin/nginx test ;; reload) /usr/sbin/nginx -s reload test ;; status) echo "WEB端口号: `netstat -tnulp|grep master|grep '\<tcp\>'|awk '{print $4 }'`" echo "WEB-PID: `ps axu|grep [n]ginx|grep master|awk '{print $2 }'`" ;; *) echo "Usage: $0 {start|stop|status|restart|reload}" esac
9.生活案例: 吃饭
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 [root@backup /server/scripts] #!/bin/bash cat<<EOF 1.皇萌鸡 2.酸笋鱼 3.瓦香鸡 4.炒菜 5.酸辣粉 6.炒粉 7.面 8.饺子 9.不吃 EOF read -p "想吃什么,请按回车键 :" ran=`echo $((RANDOM%9+1))` case $ran in 1) echo "皇萌鸡" ;; 2) echo "酸笋鱼" ;; 3) echo "瓦香鸡" ;; 4) echo "炒菜" ;; 5) echo "酸辣粉" ;; 6) echo "炒粉" ;; 7) echo "面" ;; 8) echo "饺子" ;; 9) echo "不吃" ;; esac
10.脚本批量创建10个用户,密码统一为123,需要对用户输入是否为数字和输入的名字是否为空做判断
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 [root@backup /server/scripts] #!/bin/sh read -p "请输入用户名的前缀: " prefix[ -z $prefix ] && echo "请输入前缀" && exit read -p "请输入要创建多少个用户: " numexpr 1 + $num &>/dev/null [ $? -ne 0 ] && echo "请输入整数" && exit for i in `seq $num `do echo $prefix $i done read -p "你确定要创建以上用户吗?[y|yse|Y|YES|n|N|NO]" refor n in `seq $num `do user=$prefix $n case $re in y|yes|Y|YES) id $user &>/dev/null if [ $? -ne 0 ];then mm=`mkpasswd -l 8` useradd $user && echo $mm |passwd --stdin $user &>/dev/null [ $? -eq 0 ] echo -e "用户: $user \t创建成功\t密码是:$mm " else echo "用户已存在" continue fi ;; n|N|no|NO) echo "不创建则退出" exit ;; *) read -p "你确定要创建以上用户吗?[y|yse|Y|YES|n|N|NO]" re esac done
11.简单jumpserver脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 [root@backup /server/scripts] menu (){cat<<EOF 1)WEB01=10.0.1.7 2)WEB02=10.0.1.8 3)MySQL=10.0.1.51 4)NFS=10.0.1.31 5)BACKUP=10.0.1.41 6)help EOF } menu trap "echo 不要乱输入,小心爆炸" INT HUP TSTPwhile true do read -p "请输入需要连接的服务器: " numcase $num in 1) ssh 10.0.1.7 ;; 2) ssh 10.0.1.8 ;; 3) ssh 10.0.1.51 ;; 4) ssh 10.0.1.31 ;; 5) ssh 10.0.1.41 ;; 6|h) clear menu ;; woshiyunwei) exit ;; *) echo "请输入正确信息!" esac done
12.取10位随机小写字母
1 2 3 4 5 6 7 8 9 10 [root@backup /server/scripts] #!/bin/bash randstr () { index=0 str="" for i in {a..z}; do arr[index]=$i ; index=`expr ${index} + 1`; done for i in {1..10}; do str="$str ${arr[$RANDOM%$index]} " ; done echo $str } echo `randstr`
13.Ping10.0.1.0/24网段那些能通
1 2 3 4 5 6 7 8 9 10 11 12 13 14 [root@backup /server/scripts] #!/bin/bash for i in `seq 254`do { IP=10.0.1.$i ping -c 1 -W 1 $IP &>/dev/null if [ $? -eq 0 ];then echo "10.0.1.$i is OK" fi } & done wait echo "在线取IP完成..."
14.输入两个整数计算这两个整数的相加,相减,相乘,相除,求余的结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 #!/bin/bash read -p "please input num1: " num1read -p "please input num2: " num2expr $num1 + 1 &>/dev/null RERVAL_A=$? expr $num2 + 1 &>/dev/null RERVAL_B=$? if [ $RERVAL_A -ne 0 -o $RERVAL_B -ne 0 ];then echo "请输入整数" exit fi echo "mun1+num2 =$(( num1 + num2 ) )" echo "mun1-num2 =$(( num1 - num2 ) )" echo "mun1*num2 =$(( num1 * num2 ) )" echo "mun1/num2 =$(( num1 / num2 ) )"
15.打印下面这句话中字母数小于5的单词 I am lizhenya teacher I am 18
1 2 3 4 5 6 7 #!/bin/bash for i in I am lizhenya teacher I am 18do if [ ${#i} -lt 5 ];then echo $i fi done
16.写个shell,看看你的linux系统中是否有自定义用户(普通用户),若是有,一共有几个?
1 2 3 #!/bin/bash user=`awk 'NR!=1' /etc/passwd|awk -F: '/\/bin\/bash$/{print $1}' ` echo $user
17.写一个shell脚本来看看你使用最多的命令是哪些,列出你最常用的命令top10
1 2 3 4 5 #!/bin/bash HISTFILE=~/.bash_history set -o history re=`history |awk '{print $2}' |sort|uniq -c|sort -nr|head` echo -e "最近使用最多的前个命令10是:\n$re "
18.编写一个脚本,计算100以内所有能被3整除数字的和
1 2 3 4 5 6 7 8 9 #!/bin/bash sum=0 for i in {1..100}do if [ $((i % 3)) -eq 0 ];then sum=$[$sum +$i ] fi done echo $sum
19.写一个脚本计算一下Linux系统所有进程占用内存大小的和
1 2 3 4 5 6 7 #!/bin/bash sum=0 for mem in `ps aux |awk '{print $6}' |grep -v 'RSS' `do sum=$[$sum +$mem ] done echo "The total memory is $sum ."
20.打印一个菜单如下,然后用循环加case语句输出用户输入菜单选项的结果 h 显示命令帮助 f 显示登陆信息 d 显示磁盘挂载 m 查看内存使用 u 查看系统负载 q 退出程序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 #!/bin/bash nume (){cat<<EOF h 显示命令帮助 f 显示登陆信息 d 显示磁盘挂载 m 查看内存使用 u 查看系统负载 q 退出程序 EOF } nume while true do read -p “please input num”numcase $num in h) man ;; f) who ;; d) df -h ;; m) free -h ;; u) w ;; q) exit ;; *) echo “请输入正确编号 ” esac done
21.写一个数组脚本统计/var/log/nginx.log里IP访问次数
1 2 3 4 5 6 7 8 9 10 11 awk ‘{print $1 } /var/log /nginx.log >ip.txt #!/bin/bash declare -A arraywhile read linedo let array[$line ]++ done <ip.txtfor i in ${!array[*]} do echo “nginx 的$i 访问次数为 $i |sort -nr|wc -l” done
22.统计下面这句话中字母数不大于6的单词(至少两种方式)
1 2 3 4 5 6 7 8 1.echo “I am oldboy teacher welcome to oldboy training class”|xargs -n1|awk ‘if (length<7){print }’ 2. for i in I am oldboy teacher welcome to oldboy training classdo if [ ${#i} -le 6 ];then echo $i fi done
23.使用for循环在/oldboy目录下通过随机小写10个字母加固定字符串oldboy批量创建10个html文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 [root@backup /server/scripts] #!/bin/bash dir=/oldboy [ ! -d $dir ] && mkdir $dir for n in `seq 10`do randstr () { index=0 str="" for i in {a..z}; do arr[index]=$i ; index=`expr ${index} + 1`; done for i in {1..10}; do str="$str ${arr[$RANDOM%$index]} " ; done echo $str } touch $dir /`randstr`_oldboy.html if [ $? -eq 0 ];then echo `randstr`_oldboy.html create successful fi done