实例四十一:【检查用户是否登录】

需求:写一个shell脚本,执行中每隔5分钟检查指定的用户是否登录系统,用户名从命令行输入,如果指定的用户已经登录,则显示相关信息。

提示:

1、while死循环   2、用户名需要用户指定

#!/bin/bash
while :
do
        if w|sed '1'd|awk '{print $1}'|grep -qw "$1"
        then
                echo "用户$1已经登录系统"
                exit
        fi
        sleep 300
done

脚本解析:

1、if w|sed '1'd|awk '{print $1}'|grep -qw "$1"  >使用"if"语句判断后续的命令执行情况,成功则进入if语句;不成功则进入if语句的else语句

2、w|sed '1'd|awk '{print $1}'|grep -qw "$1"  >命令"w"是获取目登录系统的当前用户,sed ’1d‘ 意思是将w命令产生的内容的第一行删除掉,并把剩余内容传到下面的管道符中;grep -qw "$1" 意思是静默且精确匹配有字符串"$1"的行

 

实例四十二:【检查系统是否被入侵】

需求:先普及一个小常识,我们用ps aux 可以查看到进程的PID,而每个PID都会在/proc内产生。如果查看到的pid在proc内是没有的,则进程被人修改了,这就代表系统由可能已经被入侵过了。

请用上面知识编写一个shell,定期检查下自己的系统是否被人入侵过。

提示:

1、ps aux 遍历所有pid

2、cd /proc/; -d pid 查看是否有该目录

#!/bin/bash
#
pp=$$
ps -elf | sed '1'd > /tmp/pid.txt
for pid in `awk -v ppn=$pp '$5!=ppn {print $4}' /tmp/pid.txt`
do
        if ! [ -d /proc/$pid ]
        then
                echo "系统中并没有pid为$pid的目录,需要检查。"
        fi
done

脚本解析:

1、pp=$$ >表示运行此脚本时,系统生成的进程pid号

2、awk -v ppn=$pp '$5!=ppn {print $4}' /tmp/pid.txt   >命令中 -v 是定义变量并赋值的作用,意思是将脚本变量$pp赋值给awk变量ppn;'$5!=ppn{print $4}'意思是由管道传过来的每一行字符串,只要第五个字段不等于ppn值,那么打印该行的第四个字段。作用是先把由运行此脚本的pid号排除

 

实例四十三:【三行并一行】

需求:想办法把文本里面每三行内容合并到一行,例如:1.txt内容如下:

1

2

3

4

5

6

7

处理后应该是:

1 2 3

4 5 6

7

提示:

1、while read 逐行遍历

2、echo -n 不换行

#!/bin/bash
#三行内容换成一行
#
declare -i sum=1
while read line
do
        yushu=$[$sum%3]
        if [ $yushu -eq 0 ];then
                echo -n "$line "
                echo ""
        else
                echo -n "$line "
        fi
        sum=$[$sum+1]
done <san.txt

脚本解析:

1、使用while read line 遍历san.txt文档内容

2、使用sum=$[$sum+1] 自增变量定位字符位数为三的倍数,然后换行

 

实例四十四:【网卡和ip】

需求:写一个getinterface.sh脚本可以接收选项[i,I],完成下面任务:

1、使用格式:getinterface.sh [-i interface | -I ip]

2、当用户使用"-i"选项时,显示指定网卡的ip地址;当用户使用"-I"选项时,显示其指定ip所属的网卡。

例:sh getinterface.sh -i eth0

sh getinterface.sh -I 192.168.0.1

3、当用户使用除[-i|-I]选项时,显示[-i interface | -I IP]此信息。

4、当用户指定信息不符合时,显示错误。比如指定的eth0没有,而是eth1时

提示:

1、两个参数$1只能是-i或者-I,$2只能是网卡名字或者IP地址

2、把网卡名字和IP地址写到一个临时文件里备用

#!/bin/bash
ip add |awk -F ': ' '$1 ~ "^[1-9]" {print $2}' > /tmp/ifs.txt
get_ip()
{
    ip add show dev $1 |grep inet |awk '{print $2}' |awk -F '/' '{print $1}'
}
 
for eth in `cat /tmp/ifs.txt`
do
    myip=`get_ip $eth`
    if [ -z "$myip" ]
    then
        echo $eth
    else
        echo $eth $myip
    fi
done > /tmp/if_ip.txt
 
if [ $# -ne 2 ]
then
    echo "请输入正确的格式: bash $0 -i 网卡 或者 bash $0 -I ip"
    exit
fi
 
if [ $1 == "-i" ]
then
    if awk '{print $1}' /tmp/if_ip.txt |grep -qw $2
    then
        eth=$2
        ip1=`awk -v aeth=$eth '$1==aeth' /tmp/if_ip.txt|sed "s/$eth //"`
        echo "网卡$2的ip是 $ip1"
    else
        echo "你指定的网卡不对,系统中的网卡有:`cat /tmp/ifs.txt|xargs`"
        exit
    fi
elif [ $1 == "-I" ]
then
    if grep -qw " $2 "  /tmp/if_ip.txt
    then
        eth=`grep -w " $2 " /tmp/if_ip.txt|awk '{print $1}'`
        echo "IP $2对应的网卡是$eth"
    else
        echo "你指定的ip不对,系统中的IP有:`ip add |grep inet |awk '{print $2}'|awk -F '/' '{print $1}'|xargs`"
        exit
    fi
else
    echo "请输入正确的格式: bash $0 -i 网卡 或者 bash $0 -I ip"
fi

脚本解析:

1、awk -F ': ' '$1 ~ "^[1-9]" {print $2}'  >awk将管道传过来的每一行使用":"进行分隔,"~"是匹配的意思;$1~^[1-9] 意思是每行字符串的第一个字段是1-9开头的行;{print $2}意思是把前面符合匹配规则的行的第二个字段输出

2、echo "请输入正确的格式: bash $0 -i 网卡 或者 bash $0 -I ip"  >$0表示此脚本的名字

 

实例四十五:【随机3位数】

需求:写一个脚本产生随机3位的数字,并且可以根据用户的输入参数来判断输出几组。比如,脚本名字为number3.sh.

执行方法:

1、bash number3.sh 会产生一组3位数字

2、bash number3.sh 10 会产生10组3位数字

提示:

1、$RANDOM除以10取余

#!/bin/bash
get_number()
{
        for i in `seq 0 2`
        do
                a[$i]=$[$RANDOM%10]
        done
        echo ${a[@]}|sed s'/ //g'
}
 
if [ $# -eq 0 ]
then
        get_number
elif [ $# -eq 1 ]
then
        n=`echo $1|sed 's/[0-9]//g'`
        if [ -n "$n" ]
        then
                echo "给定的参数必须是一个数字"
                exit
        fi
        for i in `seq 1 $1`
        do
                get_number
        done |xargs
else
        echo "格式不对,正确的格式是sh $0 [n],这里的n是一个数字。"
fi

脚本解析:

1、a[$i]=$[$RANDOM%10]  >a为数组名,$i为数组a的元素下标,数组的第一个元素下标默认是从0开始

2、echo ${a[@]}  >此命令为作用是显示数组a内的元素

 

 

实例四十六:【检查是否安装相应的rpm包】

需求:写一个shell,先判断是否安装http和mysql,没有安装进行安装,安装了检查是否启动服务,若没有启动则需要启动服务。

说明:操作系统为centos6,httpd和mysql全部为rpm包安装。

提示:

1、rpm -q 包名判断是否安装

2、service xxx start启动

#!/bin/bash
if_install()
{
        rpm -q $1 >/dev/null 2>/dev/null
        if [ $? -eq 0 ]
        then
                echo "$1已经安装"
                return 0
        else
                echo "$1没有安装"
                return 1
        fi
}
 
if_install httpd
if [ $? -eq 0 ]
then
        if ! pgrep httpd >/dev/null
        then
                service httpd start
        fi
else
        yum install -y httpd
fi
 
if_install mysql-server
if [ $? -eq 0 ]
then
        if ! pgrep mysqld >/dev/null
        then
                service mysqld start
        fi
else
        yum install -y mysql-server
fi

脚本解析:

1、此处使用函数模块来检查程序是否已经安装,若安装脚本返回值是0;若不安装脚本返回值是1;这返回值是给后续检查判断以便做出下一步操作

2、if_install httpd ...if [ $? -eq 0 ]  ##此处就是调用脚本返回值来做进一步的处理操作

3、rpm -q 包名  >此命令是检查系统中是否已安装rpm包

4、pgrep httpd  >此命令是获取与httpd服务有关的进程pid

 

实例四十七:【日期是否合法】

需求:用shell脚本判断输入的日期是否合法;比如20170110就是合法日期,20171332就不合法。

提示:

1、4位年两位月两位日

2、月的范围是00-12

3、日的范围是00-31

4、借助cal命令判断年月日是否合法

#!/bin/bash
if [ $# -ne 1 ] || [ ${#1} -ne 8 ]
then
        echo 'please input sh $0 yyyymmdd'
        exit 1
fi
 
y=`echo ${1:0:4}`
m=`echo ${1:4:2}`
d=`echo ${1:6:2}`
 
if echo $d|grep -q "^0"
then
        d=`echo ${1:6:2}|sed 's/^0//'`
fi
 
if cal $m $y > /dev/null 2>/dev/null
then
        if ! cal $m $y |grep -qw "$d"
        then
                echo "你给的日期是不合法的"
        else
                echo "日期合法"
        fi
else
        echo "你给的日期不合法"
fi

脚本解析:

1、if [ $# -ne 1 ] || [ ${#1} -ne 8 ]  >$#是指脚本的位置参数个数;${#1}是指脚本的第一个位置参数的字符长度

2、y=`echo ${1:0:4}` >此命令是获取脚本的第一个位置参数,也就是$1,然后取该参数的第0位数到第4位数,比如如果$1为abcdef,那么${1:0:4}就是abcd

3、cal month year >此命令是显示第year年第month月的日历信息,若不搭配参数,直接使用cal则是显示当前年及当前月的日历信息

 

实例四十八:【监控网卡】

需求:写一个监控网卡的脚本,需要满足以下要求:

1、每10分钟检测一次指定网卡的流量   2、如果流量为0,则重启网卡

提示:

1、sar -n DEV

2、ifdown xxx ; ifup xxx

#!/bin/bash
LANG=en
sar -n DEV 1 10|grep -w "$1" > /tmp/sar.tmp
in=`grep "Average:" /tmp/sar.tmp|awk '{print $5}'|sed 's/\.//'`
out=`grep "Average:" /tmp/sar.tmp|awk '{print $6}'|sed 's/\.//'`
 
if [ $in == "000" ] && [ $out == '000']
then
        ifdown $1
        ifup $1
fi

脚本解析:

1、sar -n DEV 1 10  >此命令是收集所有网卡在10秒内的流量情况

2、ifdown $1  >此命令是将网卡$1关闭

3、ifup $1  >此命令是将网卡$2开启

 

实例四十九:【判断网站是否正常】

需求:写一个shell脚本,通过curl -l返回的状态码来判定所访问的网站是否正常。比如,当状态吗为200时,才算正常。

提示:

1、curl -l url

#!/bin/bash
#这个脚本用来判断一个网址是否正常
url='http://www.baidu.com'
mail_user=sun.yujun@zol.com.cn
code=`curl -I $url 2>/tmp/curl.err|head -1|awk '{print $2}'`
 
if [ -z $code ]
then
        python mail.py $mail_user "$url访问异常" "`cat /tmp/curl.err`"
        exit
elif [ $code != "200" ]
then
        curl -I $url &>/tmp/curl.log
        python mail.py $mail_user "$url访问异常 状态码$code" "`/tmp/curl.log`"
fi

脚本解析:

1、curl -I $url 2>/tmp/curl.err|head -1|awk '{print $2}'  >此脚本的关键之处是如何获取访问网站的状态码

 

实例五十:【小于5k的文件打包】

需求:将用户家目录(考虑到执行脚本的用户可能是普通用户也可能是root)下面小于5KB的文件打包成tar.gz的压缩包,并以当前日期为文件名前缀,例如2019-10-05.tar.gz。

提示:

1、find ./ -type f -size -5k

2、date +%F

#!/bin/bash
t=`date +%F`
 
cd $HOME
tar czf $t.tar.gz `find ./ -type f -size -5k|xargs`

脚本解析:

1、$HOME  >此命令是获取当前用户的家目录