shell脚本积累

编者注:shell脚本的学习只有一个方法,那就是多练,多练,多练。嗯,重要的事情说三遍。



RANDOM和Seq的使用

练习1:编写脚本清空所有arp缓存记录:

#!/bin/bash
for i in $(arp | tail -n +2|tr -s ' ' |cut -d' ' -f1)
do
    arp -d $i
done

练习2:产生3个随机数:
方法1:

#for i in {0..9};do echo $RANDOM;done

这里写图片描述

方法2:

#for i in $(seq 10);do echo $RANDOM;done

这里写图片描述

练习3:倒数五秒:

#!/bin/bash
for i in $(seq 5 -1 1)
do
      echo -en "$i\n";
      sleep 1
done
echo -e "\e[31m开始!\e[0m"

这里写图片描述

练习4:批量添加用户:

#!/bin/bash
ULIST=$(cat /root/users.txt)
for UNAME in $ULIST        --》从列表文件读取文件名
do
    useradd $UNAME
    echo "123456" | passwd --stdin $UNAME --》通过管道指定密码字串
done
awk练习

例子:

# cat passwd|awk -F: 'BEGIN{print "############"}$3<100{print $1,$3,$6}END{print "@@@@@@@@@@@@@@"}'

结果:

############
root 0 /root
dbus 81 /
rpc 32 /var/cache/rpcbind
rpcuser 29 /var/lib/nfs
haldaemon 68 /
postfix 89 /var/spool/postfix
mysql 27 /var/lib/mysql
@@@@@@@@@@@@@@

例1:只有模式时,相当于grep

# cat passwd|awk '/liu/'
liu1:x:508:508::/home/liu1:/bin/bash
liu2:x:509:509::/home/liu2:/bin/bash

例2:只有动作时,就直接执行动作。

# who|awk '{print $2}'
tty1
pts/0
# who
root     tty1         2016-06-24 23:20
root     pts/0        2016-06-24 23:21 (liupeng.lan)

例3:输出以h开头的行的第一列和第七列。

# cat passwd|awk -F: '/^h/{print $1,$7}'
haldaemon /sbin/nologin

例4:显示不是以h开头的行的第一列和第七列

awk -F: '/^[^h]/{print $1,$7}' /etc/passwd

例5:以:或者/作为分隔符显示第1列和第10列

awk -F'[:/]' '{print $1,$10}' /etc/passwd

例6:以【空格:/】作为分隔符–》非常方便!!!
这里写图片描述

例1:在$2里查找匹配/pts/的,有就输出$1。

#who | awk '$2 ~ /pts/{print $1}‘ 

例2:输出uid为两位的用户名和uid。

# cat passwd|awk -F: '$3 ~/\<..\>/{print $1,$3}'

结果:
dbus 81
rpc 32
rpcuser 29
haldaemon 68
postfix 89
mysql 27

例3:输出1~100能被5整除的或者以1开头的数字。

#seq 100 | awk '$1 % 5 == 0 || $1 ~ /^1/{print $1}'

例4:显示uid大于等于500并且家目录在/home下同时shell为bash结尾的用户名,uid,家目录,shell。

# cat passwd|awk -F: '$3>=500&&$6 ~/^\/home/&&$7 ~/bash/{print $1,$3,$6,$7}'
aaa 500 /home/aaa /bin/bash
stua6 501 /home/stua6 /bin/bash
stuv1 502 /home/stuv1 /bin/bash
stuv2 503 /home/stuv2 /bin/bash

练习1:查找出用户名里包含liu的用户,输出用户名和uid及shell。

# cat passwd|awk -F':'   '$1  ~/liu/{print $1,$3,$6}'
liu1 508 /home/liu1
liu2 509 /home/liu2
liu3 510 /home/liu3
liu4 511 /home/liu4
liu5 512 /home/liu5
liu 539 /home/liu

练习2:查找出/etc/passwd文件里用户名包含liu并且使用bash的用户。

# cat passwd|awk -F':'  '$1 ~/liu/&&$7 ~/bash/{print $1,$7}'
liu1 /bin/bash
liu2 /bin/bash
liu3 /bin/bash
liu4 /bin/bash
liu5 /bin/bash
liu /bin/bash

例题:

# awk 'BEGIN{print "line one\nline two\nline three"}'
line one
line two
line three

# awk 'END{print "line one\nline two\nline three"}'line one
按Ctrl+D才显示最后三行。
line one
line two
line three

例:显示文件的行数.

# cat -n passwd|awk 'BEGIN{i=0}{i++}END{print i}'

这里写图片描述
分析:每取一行,i++。最后i的值就正好是passwd文件的行数。

例1:显示每行的字段数目

#awk '{print NF}' /etc/passwd(默认分隔符是空白,所以字段数大都是1咯)

这里写图片描述

# awk -F: '{print NF}' /etc/passwd(指定了分隔符了,就是7咯)

这里写图片描述

例2:显示每行的第一字段和最后一个字段

#awk -F:   '{print $1,$NF}' /etc/passwd

例3:显示每行的行号和内容

#awk -F:   '{print NR,$0}' /etc/passwd

例4:显示第一列和第七列,中间用—隔开

#awk -F: 'BEGIN{OFS="---"}{print $1,$7}' /etc/passwd

简单写法:

#awk -F: 'OFS="---"{print $1,$7}'/etc/passwd

这里写图片描述

例5:显示符合模式的用户名和所在的行号最后显示总行号

#awk 'BEGIN{FS=":"}/bash$/{print NR,$1}END{print NR}' /etc/passwd

例6:显示文件的3到5行(带行号,带内容)

#awkNR==3,NR==5{print NR,$0}’ /etc/passwd

这里写图片描述
显示4或7行(带行号,带内容)

#awk 'NR==4||NR==7{print NR,$0}'   /etc/passwd

这里写图片描述

例7:显示文件的前10行(带行号,带内容)

#awk   'NR<=10{print NR,$0}' /etc/passwd

这里写图片描述

例8:显示文件的前10行和30到40行

# awk 'NR<=10||NR>30&&NR<=40{print NR,$0}' /etc/passwd

这里写图片描述

练习:
1.分析下面三条命令的区别,为什么
①#awk ‘BEGIN{print NR}’ /etc/passwd (执行一次)
这里写图片描述

②#awk ‘{print NR}’ /etc/passwd (执行N次,N为行数)
这里写图片描述
(一直到48(最后一行))

③#awk ‘END{print NR}’ /etc/passwd (执行一次,最后是总行数)
这里写图片描述

2.分析下面命令的执行结果
①#awk -F: ‘{print $NR}’/etc/passwd
(解析:第1行去第1个字段,第2行取第2个字段,第n行去第n个字段……)这里写图片描述

②#awk -F: ‘{print NR, NF, 1, NF, $(NF-1)}’ /etc/passwd
(输出每行的行号,字段数,用户名,最后一个字段,倒数第二个字段)
这里写图片描述

3.只显示df -h结果的第一列文件系统

# df -h|awk -F' '  '{print $1}'  (注意指定分隔符为空白,默认就是空白)

4.显示passwd文件的第5行和第10行的行号和用户名

# cat passwd|awk -F: 'NR==5||NR==10{print NR,$1}'

练习:
1.使用NF变量显示passwd文件倒数第二列的内容

# cat passwd|awk -F: '{print $(NF-1)}'

2.显示passwd文件中第5到第10行的用户名

# cat passwd|awk -F: 'NR>=5&&NR<=10{print $1}'

3.显示passwd文件中第7列不是bash的用户名

# cat passwd|awk -F: '$7 ~/[^bash]$/{print $1}' 
--》[^bash]中括号里的^表示取反。
或者:
# cat passwd|awk -F: '$7 !~/bash/{print $1}'

4.显示passwd文件中行号是5结尾的行号和行

# cat passwd|awk -F: 'NR%10==5{print NR,$0}'
# cat passwd|awk -F: 'NR ~/5$/{print NR,$0}' 

5.用ifconfig只显示ip(不能使用tr或者cut命令)

# ifconfig|awk -F: '/inet addr/{print $2}'|awk '{print $1}'
192.168.1.147
127.0.0.1
# ifconfig |sed -n '/inet addr/p'|awk -F[:" "] '{print $13}'

6.使用awk显示eth0的入站流量和出站流量(字节)

# ifconfig eth0|awk -F'[: ]' '/RX bytes/{print $13,$19}'
# ifconfig eth0|tr -s ' '|awk -F'[: ]' '/RX bytes/{print $4,$9 }'
1025085 370703

7.使用awk命令统计以r开头的用户数目,显示如下效果
这里写图片描述

# cat passwd|awk -F: 'BEGIN{print "查找结果";i=0}/^r/{print $1;i++}END{print i}'

awk命令的引用shell变量
一、awk命令的引用shell变量
-v 引入shell变量
例1:

# name=haha
# echo|awk -v abc=$name '{print abc,$name}'  --》引用awk变量无需加$
haha 
# echo|awk -v abc=$name '{print $name}'

# echo|awk -v abc=$name '{print abc}'
haha  

例2:

# name=haha;soft=xixi
# echo|awk -v abc=$name -v efg=$soft '{print abc,123}'    --》123不用加引号就能输出
haha 123

==============
分析:

#!/bin/bash
awk -v var=$1 -F:    '$1==var{print NR,$0}'  /etc/passwd
[第1$1是位置变量,是执行此脚本时后面接的参数;第2$1指的是用户名。]

这里写图片描述

awk命令的函数
awk编程语言内置了很多函数。
length函数
例1:利用length计算字符数目的函数来检查有无空口令用户。

#awk -F: 'length($2)==0{print $1}' /etc/passwd /etc/shadow

例2:显示文件中超过50个字符的行。

# awk 'length($0)>50{print NR,$0}' /etc/passwd
3 rpc:x:32:32:Rpcbind Daemon:/var/cache/rpcbind:/sbin/nologin
4 rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin
7 mysql:x:27:27:MySQL Server:/var/lib/mysql:/bin/bash

system函数

# cat list
xixi 123
haha 456
hehe 789
# awk '{system("useradd   "$1)}' list 
# ls /home
haha  hehe  hello  xixi
# awk '{system("userdel -r   "$1)}' list  【命令用双括号括起,后面有空格】
# ls /home
hello

练习:利用system函数给上述用户配置密码。

#awk '{system("useradd $1");print $1 "is add"}'  list
#awk '{system("userdel -r  "$1);print $1 "is deleted"}' list
#awk '{system("echo  "$2"|passwd --stdin  "$1)}'  list
【命令用双括号括起,后面有空格】

awk命令的结构化语句
if语句
1.单分支

#awk -F: '{if($1 ~ /\<...\>/)print $0}' /etc/passwd
#awk -F: '{if($3 >= 500)print $1,$7}' /etc/passwd

2.双分支

#awk -F: '{if($3 != 0) print $1 ; else print $3}' /etc/passwd

3.多分支

#awk -F: '{if($1=="root") print $1;else if($1=="ftp") print $2;else if($1=="mail") print $3;else print NR}' /etc/passwd

例2:利用awk的if多重分支判断用户的类型,root显示为管理员 。

#awk -F: '{if($3==0) print $1,"管理员";else if($3>0 && $3<500) print $1,"系统用户";else if($3>=500 && $3 <= 60000) print $1,"普通用户";else print $1,"其它用户"}' /etc/passwd

例:利用awk的system命令在/tmp下建立/etc/passwd中与用户名同名的目录 。

#awk -F: '{system("mkdir /tmp/ "$1)}' /etc/passwd

练习1:用1条命令实现将指定目录下大于10K的对象复制到/tmp下(禁止使用find 和for) 。

#cp $(du -a  /boot | awk '$1>10240{print $2}') /tmp

练习2:监控多台主机的磁盘分区一旦某台被监控主机的任一分区使用率大于80%, 就给root发邮件报警。

#!/bin/bash
warn=10
ip=(10.10.10.2 10.10.10.3)
for i in "${ip[@]}"
do
   ssh root@$i df -Ph | tr -s " "|awk -v w=10 -F "[ %]" '/^\/dev/{if($5>w) print  $1,$5"% useage is over 10%"}'>
alert
   if [ -s alert ]
   then
       sed -i "1i $i" alert &&  mail -s "$i hd usage" root < alert
   fi
done

练习3:检查/var/log/secure日志文件,如果有主机用root用户连接服务器的ssh服务失败次数超过10次(10次必须使用变量),就将这个IP地址加入/etc/hosts.deny文件拒绝其访问,如果这个IP已经存在就无需重复添加到/etc/hosts.deny文件(要求使用awk语句进行字符过滤、大小判断和变量赋值,禁止使用echo、sed、grep、cut、tr命令)

#/bin/bash
awk '/Failed password for root/{print $(NF-3)}' /var/log/secure|sort -nr| uniq -c > test        --》sort 按降序排序,uniq -c统计次数
NUM=10
IP=$(awk '$1>num {print $2}' num=$NUM test)    --》$1就是统计好的次数
for i in $IP
 do
   DENY=$(awk '$2==var {print $2}' var=$i /etc/hosts.deny)
   if [[ -z $DENY ]]
     then
      awk '$2==var {print "sshd: "$2}' var=$i test >> /etc/hosts.deny
      awk '$2==var {print "错误次数"$1,"拒绝"$2"访问"}' var=$i test
   else
      awk '$2==var {print "已经拒绝"$2"访问"}' var=$i test
   fi
done

awk对行和列的累加
1.awk进行列求和
①统计/etc目录下以.conf结尾的文件的总大小

#find /etc/ -type f -name "*.conf" |xargs ls -l | awk '{sum+=$5} END{print sum}‘

这里写图片描述

②如果要匹配第一列的才累加,需要用到awk的数组和for循环(难点)

cat xferlog | awk '{print $7,$8}' | sort -n >/lianxi/123.txt
awk '{a[$1]+=$2}END{for(i in a) print i,a[i]}'/lianxi/123.txt | sort -rn -k2   
--》a[$1]=a[$1]+$2--》a[172.16.1.3]=老的a[172.16.1.3]+对应次数
  • xferlog是ftp服务器上的一个日志文件!
  • awk里的数组支持shell里讲的关联数组!!
  • sort -rn -k2是统计出下载量最大的ip并排序

③awk进行行求和
例1:
#echo 1 2 3 4 5 | awk '{for(i=1;i<=NF;i++) sum+=$i; print sum}'
这里写图片描述

例2:

#seq -s ' ' 100 | awk '{for(i=1;i<=NF;i++) sum+=$i; print sum}'

这里写图片描述

awk里面的数组是关联数组怎么理解:
练习:awk里如何使用数组来存放数据?
1.将所有的/etc/passwd所有的用户存放在user数组里。

# cat /etc/passwd|awk -F: '{user[$1]}'

解析:此时user[root]里面没有值,只是下标或者说索引变成了user[用户名]

# cat /etc/passwd|awk -F: '{user[$1]=$3}'

解析:此时,将$3的值(也就是uid)赋给user[$1]数组。
这样,就把用户和用户对应的uid关联起来了,用户名做下标关键字,uid做数组元素对应的值。

练习:awk里如何从数组里取出数据?
2.将user数组里的所有值取出来。

# cat /etc/passwd|awk -F: '{user[$1]=$3}END{for (i in user)print user[i],i}'

这里写图片描述

小结:
awk里关联数组难点的理解:
{a[$1]+=$2}
将$1对应的ip地址作为下标,将$2对应的大小赋值给下标为ip的元素。awk每读取一行就执行一次,重新又将$1对应的ip地址作为下标,执行a[$1]=a[$1]+$2,将上一行的a[$1]的值加上第2行$2值,实现累加的效果。但是ip地址还是那个ip地址,但是值已经累加了。
适用于:某一列不变,而对应的另一列的内容不同的场景。

练习:
username money
feng 100
feng 200
feng 360
li 100
li 150
zhang 90
zhang 88
统计每个人总共花了多少钱。并按总金额降序排序。

#cat money.txt|awk '{username[$1]+=$2}END{for(i in username)print i,username[i]}'|sort -nr -k2

这里写图片描述
这里写图片描述

awk里的关联数组之if判断
练习2:/etc/passwd里的所有的用户的uid存放到一个数组,如果用户输入的用户名在数组里,就输出这个用户对应的uid。
用户名做下标;uid做元素值。
答案:

#!/bin/bash
read -p "Please input the username:" u_name
cat /etc/passwd|awk -v U_name=$u_name -F: '{user[$1]=$3}END{if (U_name in user)print user[U_name]}'

这里写图片描述

补充:
三种获得uid大于500小于10000的方法:

# cat /etc/passwd|awk -F: '$3>500&&$3<10000{print $1,$3}'
# cat /etc/passwd|awk -F: '($3>500&&$3<10000){print $1,$3}'
# cat /etc/passwd|awk -F: '{if($3>500&&$3<10000)print $1,$3}'

sed 练习

1.sed取出/etc/passwd文件的第一列
2.sed将PATH环境变量中的冒号换成换行
3.sed将PATH环境变量斜杠/换成斜杠\
4.sed修改SELINUX配置文件从开启变成禁用(/etc/sysconfig/selinux)
5.去掉/etc/passwd文件中第二个地段的x
6.修改/etc/inittab文件里的3或者5修改为6
7.编写一个脚本实现修改ip地址:
7.1.提醒用户输入ip地址和子网掩码、dns、网关
7.2.需要判断新输入的ip地址是否有人使用,如果有人使用这个ip地址,就不能去修改ip,并且提示。
7.3.刷新网络服务,让新的ip地址生效。
答案:
1.# cat passwd|sed -r ‘s/(^[0-Z]+)(.*)/\1/’ –》\1表示第一个标签
2.# echo $PATH|sed ‘s/:/\n/g’
3.# echo $PATH|sed -r ‘s/\//\/g’
或者# echo $PATH|sed -r ‘s#/#\\#g’(以#作分界符)
4.# cat selinux|sed ‘/^SELINUX=/s/enforcing/disabled/g’
5.# awk -F: ‘{print $1”:”$3”:”$4”:”$6”:”$7}’ passwd
或者:# awk -F: ’ OFS=”:”{print $1,$3,$4,$5,$6,$7}’ passwd –》OFS指定输出分隔符
或者:# cat passwd|sed ‘s/:x:/::/g’
6.# cat inittab |sed -r ‘/^id/s/:[35]:/:6:/g’
7.

#!/bin/bash

read -p "Please input the ip:" IP
read -p "Please input the netmask:" MASK
read -p "Please input the dns server:" DNS
read -p "Please input the gateway:" GATEWAY

a=$(cat ifcfg-eth0|grep "IPADDR"|cut -d '=' -f2)
if [[ $IP == $a ]]
then
    echo "The IP:$IP is exist!!!"
else
    sed -i "{
    /IPADDR/c IPADDR=$IP
    /NETMASK/c NETMASK=$MASK
    /DNS1/c DNS1=$DNS
    /GATEWAY/c GATEWAY=$GATEWAY
    }" /lianxi/ifcfg-eth0
    echo "The IP is alter:$IP"
fi
shell考试题

1简答:
在bash中,在一条命令后面加入”&>/dev/null” 意味着什么?$?、$$、$0、$1、$@、$#分别表示什么意思。
答:&>/dev/null就是放入垃圾桶(黑洞文件),消除多余的输出信息。
$?:上一条命令的返回值。正确执行为0;
$$:当前shell的进程号
$0:当前行的全部字段信息
$1:第一个字段值
$@:数组里的全部元素
$#:数组的总元素数

这里写图片描述
答:

#!/bin/bash
cat access.log |sort|uniq -c|sort -nr|awk '{sum+=$1}END{print "总访问次数:"sum}'
cat access.log |sort|uniq -c|sort -nr|awk 'NR<=5{print $0}'

执行结果:
这里写图片描述

3(功能2、3未实现)
这里写图片描述

答:

#!/bin/bash
menu(){
    echo "**********************"
    echo -e "\t1.备份/var/log目录"
    echo -e "\t2.指定备份文件路径备份"
    echo -e "\t3.根据条件查找文件备份"
    echo -e "\t4.退出"
    echo "**********************"
}
main(){
while :
do
    clear
    menu
    read -p "Please input the choise:" cho
    case $cho in
    1) #备份/var/log目录
        a=$(date +%F-%H:%M:%S)
        [ -d /kaoshi/bak/log ]||mkdir /kaoshi/bak/log
        tar -czvf /kaoshi/bak/log/$a-log.tar.gz /var/log/* &>/dev/null
        echo "备份完毕!"&& ls /kaoshi/bak/log                
        find /kaoshi/bak/log -mtime +7 -type f -exec rm -rf {} \; &>/dev/null
        ;;  
    2) #指定备份文件路径备份
        today=$(date +%F)
        a=$(date +F-%H:%M:%S)
        [ -d /kaoshi/bak/$today ]||mkdir /kaoshi/bak/$today   --》双引号
        tar -czvf /kaoshi/bak/2016-07-14/pass_$a-log.tar.gz /var/log &>/dev/null
        echo "备份完毕!"&& ls /kaoshi/bak/$today
        ;;  
    3) #根据条件查找文件备份(case)
        read -p "请输入最近几天进行查找:" day 
        [ -d /kaoshi/bak/find ]||mkdir /kaoshi/bak/find
        find /kaoshi/bak/log -type f -mtime -$day >>/kaoshi/bak/find.txt 
        if (( $?==0 ))        --》find命令的返回值一直是0!!
            then
                find /kaoshi/bak/log -type f -mtime -$day -exec cp {} /kaoshi/bak/find \;
            else
                echo "对不起,没有找到对应文件."
        fi
        ;;
    4) #退出
        exit
        ;;
    *)
        echo "Please input 1-4!!!"
        ;;
    esac
    read -p "Please input anykey to continue..."
done
}
main

4
这里写图片描述
答:

#!/bin/bash
read -p "Please input the sorce:" so
if (( $so>=90&&$so<=100 ))
then
    echo "good job,may be you can try join alibaba"
elif (( $so>=80&&$so<=89 ))
then
    echo "nice,may be you can try join tencent"
elif (( $so>=60&&$so<=79 ))
then
    echo "come on,baby!may be you can try join facebook"
elif (( $so>=0&&$so<=59 ))
then
    echo "keep on fighting,may be you can try join google"
else
    echo "Please input 0-100!!!"
fi

5
这里写图片描述
D.最后显示所有新建的用户的名字和uid、gid、家目录、shell。
答:

#!/bin/bash
read -p "Please input the name:" name
read -p "Please input the number:" num
read -p "Please input the password:" pass
for i in `seq $num`
do
    id $name$i &>/dev/null|useradd $name$i
    echo "$pass"|passwd $name$i --stdin &>/dev/null         
done

6
这里写图片描述
答:

#!/bin/bash
cat /etc/passwd|awk -F: '$3>500&&$3<5000{print "username:"$1,"uid is "$3,"gid is "$4}'

7
这里写图片描述
答:

#!/bin/bash
cat web.log|awk -F '/' '{print $3}'|sort -nr|uniq -c

8
这里写图片描述
答:

#!/bin/bash
names=($(cat singers.txt))
songs=($(cat songs.txt))
nnames=${#names[@]}
nsongs=${#songs[@]}
echo "共有$nnames位歌手:${names[@]}"
echo "共有$nsongs首歌:${songs[@]}"
name1=$((RANDOM%$nnames))
song1=$((RANDOM%$nsongs))
for i in $(seq 3 -1 1)
do
        echo -e "\t\t$i"
        sleep 1
done
echo -e "\n\t\t有请${names[$name1]}演唱《${songs[$song1]}》"
#将已经选中的歌和人追加到pass文件里,并且删除用过的数组元素
echo "${names[name1]}" >>pass_singers.txt
echo "${songs[song1]}" >>pass_songs.txt
unset names[name1]
unset songs[song1]
#重新定义原来的两个数组,并且当数组元素为0时,更新数组;每次选完后更新文件
echo "${names[@]}" >singers.txt
if ((${#names[@]}==0))
then
        mv pass_singers.txt singers.txt
        echo "Update singers OK!"
fi
echo "${songs[@]}" >songs.txt
if ((${#songs[@]}==0))
then
        mv pass_songs.txt songs.txt
        echo "Update songs OK!"
fi

9
这里写图片描述
答:

#!/bin/bash
menu(){
        echo "***********************"
        echo -e "\t1.配置主机名"
        echo -e "\t2.配置ip"
        echo -e "\t3.查看ip和主机名"
        echo -e "\t4.退出"
        echo "***********************"
}
main(){
while : 
do
        clear
        menu
        read -p "请输入你的选择:" choice
        case $choice in
        1)
                #临时修改主机名
                read -p "请输入你想要的主机名:" name
                hostname $name
                #永久修改主机名
                #read -p "请输入你想要的主机名:" name2
                #vim /etc/sysconfig/network|sed 's/HOSTNAME=liupeng/HOSTNAME=$name2/g'
                ;;
        2)
                read -p "请输入你想要的IP" IP
                ifconfig eth0 $IP       
                service network restart &>/dev/null
                ;;
        3)
                ifconfig|tr -s ' '|awk -F "[: ]" '/Bcast/{print $4}'
                hostname
                ;;
        4)
                exit
                ;;
         *)
                echo "请输入1-4的数!!"
        esac
        read -p "请按任意键继续..."
done
}
main

10(功能5未全实现)
这里写图片描述
答:

#!/bin/bash
menu(){
        echo "***********************"
        echo -e "\t1.add user"
        echo -e "\t2.delete user"
        echo -e "\t3.query user information"
        echo -e "\t4.reset user's password"
        echo -e "\t5.modify user's information"
        echo -e "\t6.exit"
        echo "***********************"
}
menu2(){    
        echo "***********************"
        echo -e "\t1.update uid"
        echo -e "\t2.update gid"
        echo -e "\t3.update shell"
        echo -e "\t4.update home"
        echo -e "\t5.exit"
        echo "***********************"
}
modify(){
while :
do
        clear
        menu2
        read -p "请输入你的选择:" xuanze
        case $xuanze in
        1)  
                read -p "Please input the name:" na
                if (id $na &>/dev/null)
                then
                        read -p "Please input the uid:" uid    
                        usermod -u $uid  -o 用户名$na 
                        echo "update uid success!"
                else
                        echo "no exits!"
                fi
                ;;
        2)
                #groupmod -g 
                ;;
        3)
                #??? usermod    -d 目录路径 -u uid
                ;;
        4)
                #??? usermod
                ;;
        5)
                exit
                ;;
        *)
                echo "Please input 1-5!!!"
                ;;
        esac
        read -p "Please input anykey to continue ..."
done
}
main(){
while :
do
        clear
        menu
        read -p "请输入你的选择:" choice
        case $choice in
        1)
                read -p "Please input the name:" name
                if (id $name &>/dev/null)
                then
                        echo "exit!"
                else
                        useradd $name &>/dev/null
                        echo "create success!"
                fi
                ;;
        2)
                read -p "Please input the name:" b
                if (id $b &>/dev/null)
                then
                        userdel -r $b
                        echo "delete success!"
                else
                        echo "no exits!"
                fi
                ;;
        3)
                read -p "Please input the name:" c
                if (id $c &>/dev/null)
                then
                        id $c
                else
                        echo "no exists!"
                fi
                ;;
        4)
                read -p "Please input the name:" d
                if (id $d &>/dev/null)
                then
                        read -p "Please input the password:" e
                        echo $e|passwd $d --stdin &>/dev/null
                        echo "uptate password success!"
                else
                        echo "no exits!"
                fi
                ;;
        5)
                modify
                ;;
        6)
                exit
                ;;
        *)
                echo "请输入1-6的数!!"
                ;;
        esac
        read -p "请按任意键继续..."
done
}
main

11
这里写图片描述
答:

#!/bin/bash
[ -d /yum ]||mkdir /yum
mount /dev/cdrom /yum &>/dev/null
cd /etc/yum.repos.d
cat >local.repo<<EOF
[local_yum]
name=local yum
baseurl=file:///yum
enabled=1
gpgcheck=0
EOF
yum clean &>/dev/null
echo "yum created successful!!!"
#安装mysql服务和启动mysql
yum install mysqld -y
service mysqld start
#追加命令到样板文件即可
echo "service mysqld start" >>/etc/skel/.bashrc

12
这里写图片描述
答:

#!/bin/bash
ps aux >aux.txt
echo "CPU使用率前十:"
cat aux.txt |sort -nr -k3|awk 'NR>=2&&NR<=10{print $1,$2,$3"%"}'
echo  "内存使用率前十:"
cat aux.txt |sort -nr -k4|awk 'NR<=10{print $1,$2,$4"%"}'

13
这里写图片描述
答:

#/bin/bash
a=$(netstat -anplt|tr -s ' '|awk -F "[ :]" '/3306/{print $4}')
if ( lsof -i:3306 )
then
        echo "监听地址:$a"
else
        service mysqld start
fi

system tools(菜单 main)
***************system tools*************
1.build local yum
2.build ftp server
3.user management
4.memory statistic
5.cpu statistic
6.disk statistic
7.ftp server monitor
8.exit
******************************************

答案:

#!/bin/bash
menu(){
        echo "************System Tools**********"
        echo -e "\t1.build local yum"
        echo -e "\t2.build ftp server"
        echo -e "\t3.user management"
        echo -e "\t4.memory statistic"
        echo -e "\t5.cpu statistic"
        echo -e "\t6.disk statistic"
        echo -e "\t7.ftp server monitor"
        echo -e "\t8.exit"
        echo "**********************************"
}
main(){
while :
do
        clear
        menu
        source monitor_system.sh
        read -p "Please input your choise:" choise
        case $choise in
        1)
                bash yum.sh
                ;;
        2)
                bash ftpbuild.sh
                ;;
        3)
                bash useradd.sh
                ;;
        4)
                monitor_mem
                ;;
       5)
                monitor_cpu
                ;;
        6)
                monitor_disk
                ;;
        7)
                w
                ;;
        8)
                exit
                ;;
        *)
                echo "Please input the number of 1-8..."
                ;;
        esac
        read -p "Please input anykey to continue..."
done
}
main

猜商品价格游戏RANDOM,while.note
练习:猜商品价格游戏
猜唐僧的紫金钵价值多少~
①通过变量RANDOM获得价格
②提示用户猜测并记录次数,猜中后退出循环

分析:随机产生价格(1-100),给与提醒,价格高了/低了,记录猜的次数,如果猜的次数大于10次,输出you are bajie;5次,you are wukong;1次,you are rulai。并且猜中后退出循环,没有猜中就一直猜。。
答案:

#!/bin/bash
time=0
a=$((RANDOM%100))    --》产生099的自然数。
while :
do
        read -p "Please input the price between 1 and 100:" price
        ((time++))
        if ((price==a))
        then
                echo "Bingo!!You guess it!"    
                echo "The time that you guess is :$time"
                break
        elif ((price>a))
        then
                echo "The $price is 高了!!"
        else
                echo "The $price is 低了!!"
        fi
done
if ((time==1))
then
        echo "You are rulai!"
elif ((time<5 && time>1))
then
        echo "You are wukong!!"
elif ((i<=10))
then
        echo "You are bajie!!"
else
        echo "You are loser..."
fi

查找出uid大于X的用户(for循环)
查找出uid大于500的用户。使用for循环。

#!/bin/bash
uid=(`cat /etc/passwd|awk -F: '{print $3}'`)
name=(`cat /etc/passwd|awk -F: '{print $1}'`)
for i in `seq ${#uid[@]}`
do
        if (( ${uid[i-1]}>500 ))
        then
                echo "${uid[i-1]},${name[i-1]}"
        fi
done

方法2:用正则找出大于500的用户:

cat /etc/passwd|egrep "5[0-9]{2}|[6-9]{3}"

搭建本地yum源
#!/bin/bash
[ -d /yum ]||mkdir /yum    --》/yum不存在的时候才创建。
mount /dev/cdrom /yum &>/dev/null
cd /etc/yum.repos.d
cat >local.repo <<EOF
[local_yum]
name=local yum
baseurl=file:///yum
enabled=1
gpgcheck=0
EOF
yum clean &>/dev/null
echo "yum created successful!!"

PS:
搭建本地yum源:
1.放入系统光盘
2.新建一个目录/yum
3.挂载镜像光盘到/yum
mount /dev/cdrom /yum
补充:这里写图片描述
4.修改yum的配置文件
#cd /etc/yum.repos.d
#vim local.repo
[local_yum]
name=local yum
baseurl=file:///yum –》镜像的挂载出处!!
enabled=1
gpgcheck=0
5.清除yum缓存
yum clean all
#6.将selinux关闭
getenforce –》查看selinux状态
setenforce 0 –》临时关闭
7.安装软件
#yum install python-ipython


当前eth接口的有效ip和有效网关

编写脚本实现显示当前主机eth接口的有效IP和有效网关,要求显示结果如下图所示(多使用正则表达式,少用cut和tr)
分析:route -n–》看网关,ifconfig–》看ip,
答案:

[cat /lianxi/eth01.sh]
#!/bin/bash
ifconfig|egrep "([1-9]|[1-9][0-9]|1[0-9][0-9]|2[01][0-9]|22[0-3])(\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}"|head -n +2|tr -s " " ":"|cut -d":" -f4,6,8|tr -s ":" " " >eth01.txt
n=0
for i in $(<eth01.txt)
do
((n++))
        if (( n==1 ))
        then
                (echo $i|egrep "([1-9]|[1-9][0-9]|1[0-9][0-9]|2[01][0-9]|22[0-3])(\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}"&>/dev/null)&&echo "eth0:$i"||echo "no IP"

        elif (( n==4 ))
        then
                (echo $i|egrep "([1-9]|[1-9][0-9]|1[0-9][0-9]|2[01][0-9]|22[0-3])(\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}"&>/dev/null)&&echo "eth1:$i"||echo "no IP"
        fi
done
route -n|tail -n 1  >GATEWAY.txt
cat GATEWAY.txt|while read a IP c d e f g ETH
do
        if ( echo $IP|egrep "([1-9]|[1-9][0-9]|1[0-9][0-9]|2[01][0-9]|22[0-3])(\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}"&>/dev/null )
        then
                echo "gateway: $IP ($ETH)"
        else
                echo "gateway:  NULL"
        fi

done

当前主机中哪些是普通用户,哪些是系统用户.note
分析当前主机中所有用户,哪些是普通用户,哪些是系统用户。
分析:
看 passwd文件的UID,uid>500则为普通用户,uid<500则为系统用户,
uid怎么从passwd文件里弄出来,uid>500的用户怎么弄出来,怎么嵌套进循环里。
答案:

#!/bin/bash
cat /etc/passwd|tr ":" " "|while read username x uid gid --》用户名给username变量,x给x变量,uid给uid变量,其他的给gid这个变量,while取出来是一行一行的取出。
do
        if ((uid>500))
        then
                echo "$username is general user."
        elif ((uid==0))
        then
                echo "$username is super user."
        else
                echo "$username is system user."        
        fi
done
(闪烁功能:#echo -e"\e[5;33mHello,Word\e[0m"
而且是显示黄色,并且闪烁)

点歌程序脚本

点歌程序:v2
1.准备歌手名单,曲库;
2.随机抽歌手,随机抽歌,输出谁要唱什么歌;
3.抽过的歌手,已经唱过的歌手和歌曲都不能再出现。
答案:

#!/bin/bash
songs=($(cat songs.txt))
names=($(cat singer.txt))
nsong=${#songs[@]}        --》统计数组元素的个数
nname=${#names[@]}
echo "共有$nsong首歌:${songs[@]}"    --》显示全部数组元素
echo "共有$nname位歌手:${names[@]}"
name1=$((RANDOM%$nname))    --》随机选取
song1=$((RANDOM%$nsong))
for i in $(seq 3 -1 1)    --》倒计时三秒效果
do
        echo -e "\t\t$i"
        sleep 1
done
echo -e "\n\t\t有请 ${names[$name1]} 演唱 <<${songs[$song1]}>>"
#将已经选中的追加到pass文件里,并且删除用过的数组元素
echo "${names[name1]}" >>pass_singer.txt
echo "${songs[song1]}" >>pass_songs.txt
unset names[name1]
unset songs[song1]
#重新定义原来的两个数组,并且当数组元素为0时,更新数组
echo "${names[@]}" >singer.txt
if ((${#names[@]}==0))
then
        mv pass_singer.txt singer.txt
        echo "Update singer is OK!"
fi
echo "${songs[@]}" >songs.txt
if ((${#songs[@]}==0))
then
        mv pass_songs.txt songs.txt
        echo "Update songs is OK!"
fi

效果:
这里写图片描述


给登录到当前主机的所有非root用户终端发送一句话

给登录到当前主机的所有非root用户终端发送一句话:“用户名:Hi,I’m Root!”
答案:

#!/bin/bash
w|tail -n +3|while read user TTY other  --》w命令显示连接到本机的所有用户
do
        if [[ "$user" != "root" ]]
        then
                echo "Hello $user,I am Root!" >/dev/$TTY
        fi
done

执行结果:
另起一个终端,
这里写图片描述


函数 菜单 main

监控脚本:
1.显示内存的使用 monitor_mem()
2.显示cpu的使用 monitor_cpu
3.显示磁盘分区的使用情况 monitor_disk()
主要是/和/boot分区
4.显示内存使用率最大的5个进程 monitor_mem5()
5.显示cpu使用率最大的5个进程 monitor_process5()
分析:
free -m:看内存的使用
top -n 1:top命令仅执行一次(显示的少,不是所有的进程!、
df -Th:看磁盘空间
ps aux(所有进程一瞬间的快照)
答案:

#!/bin/bash
monitor_mem(){
        echo "****************mem********************"
        free -m
        echo "***************************************"
}
monitor_cpu(){
        echo "***************cpu*********************"
        top -n 1|egrep "^Cpu"
        uptime|cut -d, -f4,5,6
        echo "***************************************"
}
monitor_disk(){
        echo "*************disk partition************"
        df -Th|grep "/$"
        df -Th|grep "/boot"
        echo "***************************************"
}
monitor_cpu5(){
        echo "************cpu5***********************"
        ps aux|tail -n +2|sort -k3 -nr|head -5 >cpu5.txt
        #awk 'BEGIN(i=1){print i;print "pid:"$2,"memory use:"$6,"program name:"$11;i++}' cpu5.txt
        program_name=($(cat cpu5.txt|awk '{print $11}'))
        cpu_use=($(cat cpu5.txt|awk '{print $3}'))
        rm -rf cpu5.txt
        for i in {1..5}
        do
                echo "$i program name is ${program_name[i-1]} memory use:${cpu_use[i-1]}"
        done
        echo "***************************************"
}
monitor_mem5(){
        echo "************mem5***********************"
        ps aux|tail -n +2|sort -k6 -nr|head -5 >mem5.txt
        program_name=($(cat mem5.txt|awk '{print $11}'))
        memory_size=($(cat mem5.txt|awk '{print $6}'))
        rm -rf mem5.txt
        for i in {1..5}
        do
                echo "$i program name is ${program_name[i-1]} memory use:${memory_size[i-1]}"
        done
        echo "***************************************"
}
monitor_mem
monitor_cpu
monitor_disk
monitor_cpu5
monitor_mem5
监控脚本的菜单和main函数的实现
#!/bin/bash
menu(){
echo -e "1.\tdisplay memory statistics"
echo -e "2.\tdisplay cpu statistics"
echo -e "3.\tdisplay disk partiton statistics"
echo -e "4.\tdisplay cpu top5 statistics"
echo -e "5.\tdisplay mem top 5 statistics"
}
main(){
while :
do
        clear
        menu
        source monitor_system.sh
        read -p "Please input your choice option:" choice
        case $choice in
                1)
                monitor_mem
                ;;
                2)
                monitor_cpu
                ;;
                3)
                monitor_disk
                ;;
                4)
                monitor_cpu5
                ;;
                5)
                monitor_mem5
                ;;
                6)
                exit
                ;;
                *)
                echo "Please input 1-6 !!!"
                ;;
        esac
        read -p "Please input anykey to continue..."
done
}
main
监控脚本

大练习:
编写一个监控脚本,监控172.16.1.* ftp服务器的ftp服务是否正在运行,而且每秒监控一次,一旦发现ftp服务器没有运行了,马上报警并输出warnning!ftp server is down!!
需求分析:
1.nc
2.死循环–》while
3.判断if
如果考虑一直往一个文件里写,需要考虑磁盘空间的问题,会把磁盘空间耗光。
输出的时候加一个日期。
4.如果down机,需要统计出是什么时候down机的。
使用一个文件记录down机时间,判断这个文件里是否有内容,如果有说明已经记录了,就不记录。
5.down机时间的统计、down机次数的统计
例如:累计down5次,明细:
1 10分钟 从2015-5-15 12:03
2 50分钟 从2015-5-16 18:03
答案:

# vim jiankong.sh 
#!/bin/bash
################主菜单
menu(){
#!/bin/bash
################主菜单
menu(){
clear
echo -e "\t\t\e[31m **** ****\e[0m\e[5;32m  监控系统\e[0m\e[31m **** ****\e[0m"
echo -e "\t\t\e[35m **** **** 3.exit **** ****\e[0m"
}
##################次级菜单
menu2(){
echo -e "\t\t\e[5;31m **** **** 监控系统 **** ****\e[0m"
echo -e "\t\t\e[31m **** **** 1.查询监控日志 **** ****\e[0m"
echo -e "\t\t\e[31m **** **** 2.删除监控日志 **** ****\e[0m"
echo -e "\t\t\e[31m **** **** 3.备份监控日志 **** ****\e[0m"
echo -e "\t\t\e[31m **** **** 4.返回上一级 **** ****\e[0m"
}
###################监控日志查询清空与备份
########监控程序
jiankong(){
######网址判断
read -p "请输入你想监控的网址" ip
while :
do
        echo "$ip">>ip.txt
        pp=`cat ip.txt|tail -1|egrep "\b([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-9])(\.([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}\b" |awk -F. 'NF<=4'|wc -l`
        if (( pp==0 ))
        then
                read -p "请您输入有效的IP地址:" ip
        else
                >ip.txt
                break;
        fi
done
n=0 ######监控
but_q=null
while :
do
        a=`date +%F`
        b=`date "+%F %H:%M:%S"`
        nc -z $ip 21 &>/dev/null
        if (( $? == 0 ))
        then
                t=`cat downtime.txt|head -1`
                count=`cat downtime.txt|wc -l`
                if (( ${count} != 0 ))
                then
                        ((n++))
                        echo " $ip 运行监控程序后第$n次down机,共${count}秒,从$t$b">>/lianxi/jiankong/bak/log${a}.txt
                        >downtime.txt
                else
                        echo -e "\e[31m正在监控中,$ip ftp server is running...,input 'q' to return menu\e[0m"
                        read -s -n1 -t1 but_q
                        if [[ "$but_q" = "q" ]]
                        then
                                read -n1 -t3 -s -p "Do you want to quit to menu [Y/N]?" answer
                                case $answer in
                                Y|y)
                                        break;;
                                N|n)
                                        continue
                                        ;;
                                *)
                                        continue
                                        ;;
                                esac
                        fi

                fi
        else
                echo -e "\e[31mwarnning!!the ${ip} ftp server is down!\e[0m"
                echo -e "\e[031m input 'q' to return the menu!\e[0m"
                echo "$b">>downtime.txt
                read -s -n1 -t1 but_q
                if [[ "$but_q" = "q" ]]
                then
                        echo
                        read -n1 -t3 -s -p "Do you want to quit to menu[Y/N]?" answer
                        case $answer in
                        Y|y)
                                break;;
                        N|n)
                                continue
                                ;;
                        *)
                                continue
                                ;;
                        esac
                fi

        fi
        sleep 1
done
}
###################备份主函数
bakmain(){
clear
while :
do
        menu2
        read -p"please choose the option(1-4):" cho2
        case $cho2 in
        1)
                chk
                ;;
        2)
                del
                ;;
        3)
                tar2
                ;;
        4)
                break;;
        *)
                echo "your input is wrong,please try again!"
                ;;
        esac
        clear
done
}
#############主函数
main(){
clear
while :
do
        menu
        read -p"please choose the option(1-3):" cho
        case $cho in
        1)
                jiankong
                ;;
        2)
                bakmain
                ;;
        3)
                echo -e "\e[31mthank you for use the system!\e[0m"
                break;;
        *)
                echo -e "\e[31myour inupt is wrong,please try again!\e[0m"
                ;;
        esac
done
}
###############chk查看
chk(){
        k=`ls -l /lianxi/jiankong/bak|wc -l`
        while :
        do
                if (( k == 1 ))
                then
                        echo -e "\e[31m系统没有查找到任何监控日志文件!\e[0m"
                        read -p"按回车键返回上一层"
                        break;
                else
                        echo -e "\e[31m这里是所有的日志文件:\e[0m"
                        ls /lianxi/jiankong/bak
                        read -p "查询请输入1,退出请输入2:" an
                        if [[ $an == "1" ]]
                        then
                                while :
                                do
                                read -p "请输入你要具体要查询的日志文件日期(year-month-day:2000-02-01):" day
                                        if [ -f /lianxi/jiankong/bak/log${day}.txt ]
                                        then
                                                echo -e "\e[31mlog${day}的内容如下:\e[0m"
                                                cat /lianxi/jiankong/bak/log${day}.txt
                                                read -p "按回车键返回"
                                                break;
                                        else
                                                echo  "你输入的文件格式有问题或者不存在,请重新输入!"
                                        fi
                                done
                        elif [[ $an == "2" ]]
                        then
                                break;
                        else
                                echo -e  "\e[31m您的输入错误,请重新输入(1或2):\e[0m" 
                        fi
                fi
        done
}
##############del删除
del(){
        k=`ls -l /lianxi/jiankong/bak|wc -l`
        while :
        do
                if (( k == 1 ))
                then
                        echo -e "\e[31m系统没有查找到任何监控日志文件!\e[0m"
                        read -p"按回车键返回上一层"
                        break;
                else
                        echo -e "\e[31m这里是所有的日志文件:\e[0m"
                        ls /lianxi/jiankong/bak
                        read -p"删除文件请输入1,退出请输入2:" an
                        if [[ $an == "1" ]];then
                                k=`ls -l /lianxi/jiankong/bak|wc -l`
                                if ((k ==1))
                                then
                                        read -p "所有文件都已被删除!请按回车键返回"
                                else
                                        read -p"请输入你想删除的文件日期(year-month-day:2000-02-01):" day
                                        while :
                                        do
                                                if [ -f /lianxi/jiankong/bak/log${day}.txt ]
                                                then
                                                        read -p"你确认删除?一旦删除将无法还原(y/n):" an
                                                        if [[ $an == "y" ]]
                                                        then
                                                                rm -rf /lianxi/jiankong/bak/log${day}.txt
                                                                echo "delete is ok!"
                                                                read -p "按回车键返回"
                                                                break;
                                                        else
                                                                break;
                                                        fi
                                                else
                                                        echo "你输入的文件格式不对或者不存在,请重新输入!" 
                                                fi
                                        done
                                fi
                        elif [[ $an == "2" ]];then
                                break;
                        else
                                echo -e "\e[31m您的输入有误,请重新输入\e[0m" 
                        fi
                fi
        done
}
##############备份
        menu
        read -p"please choose the option(1-3):" cho
        case $cho in
        1)
                jiankong
                ;;
        2)
                bakmain
                ;;
echo -e "\t\t\e[5;31m **** **** 监控系统 **** ****\e[0m"
echo -e "\t\t\e[31m **** **** 1.查询监控日志 **** ****\e[0m"
echo -e "\t\t\e[31m **** **** 2.删除监控日志 **** ****\e[0m"
echo -e "\t\t\e[31m **** **** 3.备份监控日志 **** ****\e[0m"
echo -e "\t\t\e[31m **** **** 4.返回上一级 **** ****\e[0m"
}
###################监控日志查询清空与备份
########监控程序
jiankong(){
######网址判断
read -p "请输入你想监控的网址" ip
while :
do
        echo "$ip">>ip.txt
        pp=`cat ip.txt|tail -1|egrep "\b([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-9])(\.([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}\b" |awk -F. 'NF<=4'|wc -l`
        #pp=`cat ip.txt|tail -1|egrep "^([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-9])(\.([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}$"` 
        if (( pp==0 ))
        then
                read -p "请您输入有效的IP地址:" ip
        else
                >ip.txt
                break;
        fi
done
n=0 ######监控
but_q=null
while :
do
        a=`date +%F`
#!/bin/bash


################主菜单
menu(){
clear
echo -e "\t\t\e[31m **** ****\e[0m\e[5;32m  监控系统\e[0m\e[31m **** ****\e[0m"
echo -e "\t\t\e[33m **** **** 1.启动监控程序 **** ****\e[0m"
echo -e "\t\t\e[34m **** **** 2.监控日志管理 **** ****\e[0m"
echo -e "\t\t\e[35m **** **** 3.exit **** ****\e[0m"
}
##################次级菜单
menu2(){
echo -e "\t\t\e[5;31m **** **** 监控系统 **** ****\e[0m"
echo -e "\t\t\e[31m **** **** 1.查询监控日志 **** ****\e[0m"
echo -e "\t\t\e[31m **** **** 2.删除监控日志 **** ****\e[0m"
echo -e "\t\t\e[31m **** **** 3.备份监控日志 **** ****\e[0m"
echo -e "\t\t\e[31m **** **** 4.返回上一级 **** ****\e[0m"
}
###################监控日志查询清空与备份
########监控程序
jiankong(){
######网址判断
read -p "请输入你想监控的网址" ip
while :
do
        echo "$ip">>ip.txt
        pp=`cat ip.txt|tail -1|egrep "\b([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-9])(\.([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}\b" |awk -F. 'NF<=4'|wc -l`
        #pp=`cat ip.txt|tail -1|egrep "^([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-9])(\.([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}$"` 
        if (( pp==0 ))
        then
                read -p "请您输入有效的IP地址:" ip
        else
                >ip.txt
                break;
        fi
done
n=0 ######监控
but_q=null
while :
do
        a=`date +%F`
        else
                >ip.txt
                break;
        fi
done
n=0 ######监控
but_q=null
while :
do
        a=`date +%F`
        b=`date "+%F %H:%M:%S"`
        nc -z $ip 21 &>/dev/null
        if (( $? == 0 ))
        then
                t=`cat downtime.txt|head -1`
                count=`cat downtime.txt|wc -l`
                if (( ${count} != 0 ))
                then
                        ((n++))
                        echo " $ip 运行监控程序后第$n次down机,共${count}秒,从$t$b">>/lianxi/jiankong/bak/log${a}.txt
                        >downtime.txt
                else
                        echo -e "\e[31m正在监控中,$ip ftp server is running...,input 'q' to return menu\e[0m"
                        read -s -n1 -t1 but_q
                        if [[ "$but_q" = "q" ]]
                        then
                                read -n1 -t3 -s -p "Do you want to quit to menu [Y/N]?" answer
                                case $answer in
                                Y|y)
                                        break;;
                                N|n)
                                        continue
                                        ;;
                                *)
                                        continue
                                        ;;
                                esac
                        fi

                fi
        else
                echo -e "\e[31mwarnning!!the ${ip} ftp server is down!\e[0m"
                echo -e "\e[031m input 'q' to return the menu!\e[0m"
                echo "$b">>downtime.txt
                read -s -n1 -t1 but_q
                if [[ "$but_q" = "q" ]]
                then
                        echo
                        read -n1 -t3 -s -p "Do you want to quit to menu[Y/N]?" answer
                        case $answer in
                        Y|y)
                                break;;
                        N|n)
                                continue
                                ;;
                        *)
                                continue
                                ;;
                        esac
                fi

        fi
        sleep 1
done
}
###################备份主函数
bakmain(){
clear
while :
do
        menu2
        read -p"please choose the option(1-4):" cho2
        case $cho2 in
        1)
                chk
                ;;
        2)
                del
                ;;
        3)
                tar2
                ;;
        4)
                break;;
        *)
                echo "your input is wrong,please try again!"
                ;;
        esac
        clear
done
}
#############主函数
main(){
clear
while :
do
        menu
        read -p"please choose the option(1-3):" cho
        case $cho in
        1)
                jiankong
                ;;
        2)
                bakmain
                ;;
        3)
                echo -e "\e[31mthank you for use the system!\e[0m"
                break;;
        *)
                echo -e "\e[31myour inupt is wrong,please try again!\e[0m"
                ;;
        esac
done
}
###############chk查看
chk(){
        k=`ls -l /lianxi/jiankong/bak|wc -l`
        while :
        do
                if (( k == 1 ))
                then
                        echo -e "\e[31m系统没有查找到任何监控日志文件!\e[0m"
                        read -p"按回车键返回上一层"
                        break;
                else
                        echo -e "\e[31m这里是所有的日志文件:\e[0m"
                        ls /lianxi/jiankong/bak
                        read -p "查询请输入1,退出请输入2:" an
                        if [[ $an == "1" ]]
                        then
                                while :
                                do
                                read -p "请输入你要具体要查询的日志文件日期(year-month-day:2000-02-01):" day
                                        if [ -f /lianxi/jiankong/bak/log${day}.txt ]
                                        then
                                                echo -e "\e[31mlog${day}的内容如下:\e[0m"
                                                cat /lianxi/jiankong/bak/log${day}.txt
                                                read -p "按回车键返回"
                                                break;
                                        else
                                                echo  "你输入的文件格式有问题或者不存在,请重新输入!"
                                        fi
                                done
                        elif [[ $an == "2" ]]
                        then
                                break;
                        else
                                echo -e  "\e[31m您的输入错误,请重新输入(1或2):\e[0m" 
                        fi
                fi
        done
}
##############del删除
del(){
        k=`ls -l /lianxi/jiankong/bak|wc -l`
        while :
        do
                if (( k == 1 ))
                then
                        echo -e "\e[31m系统没有查找到任何监控日志文件!\e[0m"
                        read -p"按回车键返回上一层"
                        break;
                else
                        echo -e "\e[31m这里是所有的日志文件:\e[0m"
                        ls /lianxi/jiankong/bak
                        read -p"删除文件请输入1,退出请输入2:" an
                        if [[ $an == "1" ]];then
                                k=`ls -l /lianxi/jiankong/bak|wc -l`
                                if ((k ==1))
                                then
                                        read -p "所有文件都已被删除!请按回车键返回"
                                else
                                        read -p"请输入你想删除的文件日期(year-month-day:2000-02-01):" day
                                        while :
                                        do
                                                if [ -f /lianxi/jiankong/bak/log${day}.txt ]
                                                then
                                                        read -p"你确认删除?一旦删除将无法还原(y/n):" an
                                                        if [[ $an == "y" ]]
                                                        then
                                                                rm -rf /lianxi/jiankong/bak/log${day}.txt
                                                                echo "delete is ok!"
                                                                read -p "按回车键返回"
                                                                break;
                                                        else
                                                                break;
                                                        fi
                                                else
                                                        echo "你输入的文件格式不对或者不存在,请重新输入!" 
                                                fi
                                        done
                                fi
                        elif [[ $an == "2" ]];then
                                break;
                        else
                                echo -e "\e[31m您的输入有误,请重新输入\e[0m" 
                        fi
                fi
        done
}
##############备份
tar2(){
        k=`ls -l /lianxi/jiankong/bak|wc -l`
        while :
        do
                if (( k == 1 ))
                then
                        echo -e "\e[31m系统没有查找到任何监控日志文件!\e[0m"
                        read -p"按回车键返回上一层"
                        break;
                else
                        echo "这里是所有的日志文件:"
                        ls /lianxi/jiankong/bak
                        read -p "备份文件请输入1,退出请输入2:" an
                        if [[ $an == "1" ]];then
                                read -p "请输入你想备份的日志文件(year-month-day:2000-02-01):" day
                                while :
                                        do
                                        if [ -f /lianxi/jiankong/bak/log${day}.txt ]
                                        then
                                                cd /lianxi/jiankong/bakup
                                                tar -czvf ${day2}.tar.gz /lianxi/jiankong/bak/log${day2}.txt &>/dev/null
                                                echo "${day2} 备份成功!"
                                                read -p"按任回车键返回"
                                        else
                                                read -p"你输入的文件格式不对或者不存在,请重新输入:" day
                                        fi
                                done
                        elif [[ $an == "2" ]];then
                                break;
                        else
                                read -p"你的输入有误,请重新输入:" an
                        fi
                fi
        done
}
main

监控内存的使用情况

练习2:
监控内存的使用情况,一旦内存的可用空间低于800M就在屏幕上输出“your system is less than 800M,you need to do something to improve memory size”(用free -m 命令即可)
答案:

# a=$(free -m|grep "Mem"|awk '{print $4}')
# [ $a -lt 800 ]&&echo "your system is less than 800M"

free -m --》以M为单位显示内存的使用情况。

监听mysql服务是否开启

练习:
1.判断内核版本,如果大于2.6,显示“内核版本:版本,否则显示内核版本太低,无法继续”(uname -r)
2.检查mysqld服务是否开启,如果开启显示如下内容:
监听地址:0.0.0.0:3306
如果没有开启,将mysqld服务启动
(netstat -anplut|grep 3306)
(lsof -i:3306)
答案:

1.
#/bin/bash
a=$(uname -r|awk -F'.' '{print $1"."$2}')
if [[ $a>2.6 ]]
then
        echo "内核版本:$a"
else
        echo "内核版本太低,无法继续!"
fi
2.
#/bin/bash
a=$(netstat -anplt|awk '/3306/{print $5}')
if ( lsof -i:3306 )
then
        echo "监听地址:$a"
else
        service mysqld start
fi

netstat命令(-anplut)

netstat命令用于显示与IP、TCP、UDP和ICMP协议相关的统计数据,一般用于检查本机各端口的网络连接情况。
netstat是在内核中访问网络及相关信息的程序,它能提供TCP连接,TCP和UDP监听,进程内存管理的相关报告。
命令参数:
-a 显示所有连线中的socket all
-c 持续列出网络状态 continue
-C 显示路由器配置的快取信息 cache
-e 显示网络其他相关信息 extend
-F 显示FIB fib
-g 显示多重广播功能群组组员名单 groups
-h 显示帮助 help
-i 显示网络界面信息表单 interfaces
-l 显示监控中的服务器的socket listening
-M 显示伪装的网络连线 masquerade
-n 直接使用ip地址,而不通过域名服务器 numeric
-N 显示网络硬件外围设备的符号连接名称 netlink或symbolic
-o 显示计时器 timers
-p 显示正在使用socket的程序识别码和程序名称 programs
-r 显示route table route
-s 显示网络工作信息统计表 statistice
-t 显示TCP传输协议的连线情况 tcp
-u 显示UDP传输协议的连线情况 udp
-v 显示指令执行进程 verbose
-V 显示版本信息 version
-w 显示RAW传输协议的连线状态 raw
-x 此参数的效果和指定”-A unix”参数相同 unix
-ip 此参数的效果和指定”-A inet”参数相同 inet


截取本机上所有网卡的ip地址和子网、网关

练习:
1.截取出本机上所有网卡的ip地址和子网掩码、默认网关
2.格式如下:
eth0 ip adreess is 172.16.1.1/16
eth1 ip adreess is 173.168.1.1/16
default gateway is 173.168.20.20
dns servers are 114.114.114.114 219.146.1.66

#得到eth0和eth1的名字:
# ip add|grep "mtu"|awk '{print $2}'|tr -d :
#得到eth0的ip地址:
#ifconfig eth0|grep "inet addr"|tr -s ':' ' '|cut -d' ' -f4
#得到eth1的ip地址:
#ifconfig eth1|grep "inet addr"|tr -s ':' ' '|cut -d' ' -f4 
#得到默认网关:
# route -n|grep "^192"|awk '{print $2}'
#获得DNS:
# cat /etc/resolv.conf |grep " DNS1"|tr = ' '|awk '{print $3}'# cat /etc/resolv.conf |grep " DNS1"|tr = ' '|cut -d ' ' -f3

练习 :
1.只显示/boot目录下所有对象的实际空间,并按由小到大排序
2.统计/etc/passwd中每种shell的被使用次数
3.用fdisk -l命令只显示出分区和文件系统的类型
4.统计/etc/passwd文件中sbin这个单词出现多少次
5.用find命令查找/根目录下所有包含特殊权限的对象,并只显示出对象的权限和文件名称,不能显示错误提示
6.列出前5位占MEM最多的进程的命令
7.只显示网卡eth0的IP地址
答案:

1)find /boot –exec ls -l {} \; | tr -s ' ' | cut -d' ' -f5 | grep -v ^$ | sort –n
(2)cat /etc/passwd | cut -d: -f7 | sort | tail -n +2 | uniq -c3)fdisk -l | grep ^/dev | tr -s '*' ' ' | cut -d' ' -f1,6-4)cat /etc/passwd | tr -s ':/ ' '\n' | sort | uniq -c | grep sbin
(5)find / -perm +7000 -exec ls -ld {} \; 2>/dev/null |tr -s ' ' | cut -d' ' -f1,9 | cut -c 2-10,12-6)ps aux | tr -s ' ' | tail -n +2 | sort -k4 -rn | head -57)ifconfig eth0 | grep "inet addr" | tr -s ':' ' ' |cut -d' ' -f4

练习:每2秒钟输出一次系统时间。
解析:不停输出–》死循环while–》sleep 2–》时间格式:年月日时分秒
答案:

#!/bin/bash
while :
do
        echo $(date +%F'  '%H:%M:%S) >>/lianxi/timeout.txt
        sleep 2
done
[或者:date +'%Y-%m-%d  %H:%M:%S']

结果:
这里写图片描述


判断IP是否合法

编写判断IP地址是否合法的脚本
①提醒用户输入ip地址②要求判断文件中的ip地址是否是合法的ipv4地址③不合法的ip地址给与提醒④输出用户输入的ip地址
分析:首先有三个点,其次,第一部分为1-223,其他为0-255即可。
答案:

#!/bin/bash
while :
do
        clear
        read -p "Please input the IP:" addr
        echo "$addr" >iphefa.txt
        if ( (cat "iphefa.txt"|egrep "^([1-9]|[1-9][0-9]|1[0-9][0-9]|2[01][0-9]|22[0-3])(\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}$")&>/dev/null )
        then
                echo "The IP that you input is :$addr"
                break
        else
                echo "Please input the right IP!!"
                read -p "Please input anykey to continue......"
        fi
done

判断用户是否存在,存在则设置密码,不存在就新建,然后给用户设置密码
练习1:设置密码
判断用户是否存在,存在则设置密码,不存在就新建,然后给用户设置密码,用户输入的密码长度小于6位时给与提醒,弱密码,如果大于6位,提醒用户设置的密码长度,并且提示安全。

答案:

#!/bin/bash
read -p "Please input the user:" u_name
if id $u_name
then
        read -p "Please input the password:" pass
        len=$(echo $pass|wc -m)
        echo $pass|passwd $u_name --stdin &>/dev/null
else
        echo "The user $u_name is isn't exit!"
        useradd $u_name &>/dev/null&& echo "User u_name create OK!"
        read -p "Please input the password:" pass
        echo $pass|passwd $u_name --stdin &>/dev/null
fi
[[ $pass==?????? ]] && echo "password is ok!And the lens is $(( $len-1 )),it's good!"||echo "password is so short!"
怎么得到密码的长度

(1)
#a=123
#len=echo ${#a} –》非常准确!

echo ${#a} $a中字符串的个数
echo ${a:3} $a中从第三个开始取直到结束
echo ${a:3:2} $a中从第三个开始去两个字符
echo ${a: -1} 取最后一个字符
echo ${a#*.} 从左边开始删除直到遇到.为止
echo ${a##*.} 从左边开始删除直到遇到最后一个.为止
echo ${a%.*} 从右面开始删除直到遇到.为止
echo ${a%%.*} 从右面开始删除直到遇到最后一个.为止
echo ${a/abc/111} 将变量a中的第一个abc替换成111
echo ${a//abc/xyz} 将变量a中的所有的abc替换成xyz

(2)len=echo $a|wc -m –》得到的值比实际大1

批量添加用户while,for.note

for循环批量添加

批量添加用户并且满足以下要求:
这里写图片描述

答案:

#!/bin/bash
read -p "请输入用户名的前缀:" a 
read -p "请输入用户的数目:" num
if (( $num<=10 ))
then
        n=0
        for i in `seq $num`
        do
               if useradd $a$i &>/dev/null
                then
                        echo "用户$a$i创建成功!"
                        (( n++ ))
                        echo "123456"|passwd $a$i --stdin &>/dev/null
                fi
        done
        echo "一共创建的用户数:$n个"
else
        echo "最多只能创建10个用户啦!"
fi
用while循环批量添加20个用户

要求:
①用户名称以stu开头,按数字顺序进行编号
②一共添加20个用户,即stu1、stu2……
③初始密码均设置为123456
答案:

#!/bin/bash
a="stu"
i=1
while (( i<=20 ))
do
         useradd $a$i
         echo "123456"|passwd --stdin $a$i &>/dev/null
         (( i++ ))
done

假如用户名在一个文件里,怎么解决

#!/bin/bash
cat username.txt|while read name pass  --》name pass 叫啥都行
do
        id $name &>/dev/null||useradd $name
        echo "$pass"|passwd $name --stdin &>/dev/null
done
(||:或符号,id命令执行不成功,才执行后面的命令)
使用条件测试

练习:使用条件测试完成下列任务
(1)测试/分区磁盘空间,小于10%,显示“一切正常”,否则显示“当前的磁盘空间是 磁盘空间% 警告”
(2)统计当前系统的登陆用户,登陆用户小于3个,显示“一切正常”,否则显示“登陆用户已经有:个数”
(3)测试当前主机eth0的网卡入站和出站流量,只要两个都大于200MiB,就显示“警告”;
(4)当内存空闲空间小于内存的5%时,显示“内存不足”,否则显示“当前空闲内存是:内存空闲数值”
答案:

1#df -Th
#!/bin/bash
a=$(df -Th|grep sda3|tr -s ' '|awk '{print $6}'|tr -d %)    --》tr -d 删除%
if (( $a<10 ))
then
        echo "Everything is OK!"
else
        echo "Now is:$a % free space!"
fi2#who
#!/bin/bash
a=$(who|wc -l)
(($a<3))&&echo "Everything is OK!"||echo "The user is: $a "3#watch -n 1 "/sbin/ifconfig eth0“
watch -n 1 "/sbin/ifconfig eth0|grep bytes|tr -s ' '|cut -d ' ' -f8|tr -d '(' ")
(4#free
#!/bin/bash
free=$(free|grep "Mem"|tr -s ' '|awk -F ' ' '{print $4}')
tocal=$(free|grep "Mem"|tr -s ' '|awk -F ' ' '{print $2}')
echo "The free space is: $free"
echo "The tocal space is:$tocal"
bai=$(echo -n 0;echo "scale=2;$free/$tocal"|bc)   
 --》echo -n 0,下一条命令不换行
bai_xin=$(echo $bai|tr -d '0.')
echo "$bai_xin"
(($bai_xin<5))&&echo "The mem isn't enough!!"||echo "当前空闲内存是:$free,空闲百分比:$bai_xin%"

执行效果:
这里写图片描述

双色球的选择(数组和seq的应用)

数组和seq命令的应用
选择双色球
这里写图片描述

答案:

#!/bin/bash
echo "欢迎购买福彩双色球,按任意键机选一注"
redball=($(seq 32))
echo -e "\033[31m红球:\n$(echo ${redball[@]})\033[0m" --》显示数组元素
blueball=($(seq 16))
echo -e "\033[34m蓝球:\n$(echo ${blueball[@]})\033[0m"
blen=${#blueball[@]}    --》blen存的是篮球的总数
for i in $(seq 6)        --》随机取6个红球
do
    rlen=${#redball[@]}    --》rlen存的是红球总数
    rnum=$((RANDOM % rlen))
    rb[x++]=${redball[rnum]}    -》rb数组存的是选出来的6个红球
    unset redball[rnum]    -》从原红球数组删除已选的
    redball=(${redball[@]})
done
bnum=$((RANDOM % blen))
bb=${blueball[bnum]}
read -n1 -s    --》暂停功能,实现按任意键选择的功能。
echo -e "你的幸运号码是:******** \033[31m红球:${rb[@]}\033[0m \033[34m蓝球:$bb\033
[0m ********"

统计某个文件夹下有多少个文件夹

这里写图片描述

答案:

find 文件夹 -maxdepth 1 -type d|tail -n +2|wc -l

这里写图片描述

运行结果:
这里写图片描述

目录的深度从0开始算 ,0代表目录本身,1 代表当前目录下的文件夹 2代表当前目录下的文件夹里的子文件夹 ,以此类推。

统计某文件夹下,某种文件后缀名的文件的数目

这里写图片描述

答案:

#!/bin/bash
read -p "please input the dir:" DIR
for i in "$@"        --》$@ 所有的位置变量
do
        num=$(find $DIR -type f -name "*$i"|wc -l)
        echo "yi $i jiewei de wen jian shu mu shi:" $num
done

执行结果:
这里写图片描述

统计日志里访问次数最多的10个ip地址

练习:
将access.log 文件里的web日志访问次数最多的10个ip地址,显示出来要求格式如下:
1 172.16.30.123 tocal:1898
2 172.16.30.34 tocal:1800
3 172.16.20.13 tocal:1456
答案:

#cat access.log | cut -d " " -f1 | sort | uniq -c | sort -k1 -nr | head | tr -s “ “| cat -n | awk -F “ ” ‘{print $1,$3,“tocal:”$2}’

分析:
截取文件里的ip–》相同ip在一起–》去重统计–》按第一列的数值大小降序–》取前十个–》压缩空格–》产生行号–》截取1,3,2列
效果:
这里写图片描述

简单版:
构造的文件内容如下:
这里写图片描述
命令:
#cat access.log|sort|uniq -c|sort -k1 -nr|awk '{print $2"tocal:"$1}'|cat -n
结果:
这里写图片描述

dd

无意义,while dd:每次产生1个1M大小的文件来消耗内存
每次产生1个1M大小的文件来消耗内存的例子:

#cat while4.sh
i=1
while true
do
    echo “$i”
    ((i++))
  (dd   if=/dev/zero    of=dd.dd$i    bs=1M   count=1)&
done

–》每次产生1个1M大小的文件,并且放到后台去运行。
这里写图片描述


选择菜单的应用

编写脚本显示如下图所示效果,要求选择一个菜单后,显示出来选择的是什么。
这里写图片描述

答:

#!/bin/bash
echo -e "\e[31m\t\t***系统管理工具***\e[0m"
echo -e "\n"
echo -e "\t1.\t显示磁盘接口信息"
echo -e "\t2.\t显示网络接口信息"
echo -e "\t3.\t显示内存空间信息"
echo -e "\t4.\t退出菜单"
echo -e "\n"

read -p "请输入选项:" choise
echo "你的选择是:$choise"
芝麻开门 [[字符串比较]]

例:字符串的比较
芝麻开门:直到说出芝麻开门才停,否则一直说“山无棱,天地合,才敢与君绝。”

答案:

#!/bin/bash
until false
do
        read -p "山无棱,天地合,才敢与君绝:" PIN
        if [[ $PIN == "open door" ]]
        then
                echo "your answer is OK!"
                break
        fi
done

执行结果:
这里写图片描述


最经典的ping,检查能用

练习:
检查整个局域网中172.16.30.0/16,172.16.30.1到30.254之间的ip,有哪些ip正在使用,哪些没有使用;显示出正在使用的ip地址和总数

答案:

#!/bin/bash
for a in `seq 1 5`
do
        ip=192.168.227.$a
        echo $ip
        (ping $ip -c 1 -i 0.2 -w 1 &>/dev/null)
        if (( $?==0 ))
        then
                echo "$ip is UP">>IPADDR.txt
        else
                echo "$ip is DOWN">>IPADDR.txt
        fi
done
sleep 3
num_up=`cat IPADDR.txt|grep UP|wc -l`
num_down=`cat IPADDR.txt|grep DOWN|wc -l`
echo "There are $num_up computers UP."
echo "There are $num_down computers DOWN."

执行结果:
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

斯言甚善

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值