shell—100实例(10)

 

实例一:

要求:安照这样的日期格式(xxxx-xx-xx)每日生成一个文件,如生成的文件为2017-12-20.log,并且把磁盘的使用情况写到这个文件中,提示:date、df

date=`date +%F`   #重音符``的作用是先运行重音符里面的命令,并将结果赋予变量date
df >$date.log     #将命令df生成的内容覆盖文档$date.log,若$date.log不存在,则先创建;若存在,则直接覆盖  

优化脚本【这是转载其他博主的】

#!/bin/bash
d=`date +%F`   #获取当前日期
dir=/data/logs/disklog  #指定日志文件生成的目录
if [ ! -d $dir ]  #判断如果没有目录创建
then
    mkdir -p $dir
fi
df -h > $dir/$d.log  #将硬盘信息写到日志
find $dir/ -mtime +365 |xargs rm  #删除一年之前的文件

此实例的脚本亮点为:

1、find $dir/ -mtime +365 | xargs rm  #删除一年之前的文件

2、xargs  #xargs能将管道|传来的参数被"不接受管道参数的命令"接收,如上实例:rm删除文档,正常情况下是不接受管道传参的,但加上xargs命令后,rm命令就能接收管道传来的参数。

find / *.log | rm  #此命令不会执行成功

实例二:

统计文档access.log中IP的访问量

# cat access.log
http1 apache1 192.168.14.32
http2 apache2 192.168.14.171
http3 apache3 192.168.14.46
http4 apache4 192.168.14.48
http5 apache5 192.168.14.108
http1 apache1 192.168.14.10
http2 apache2 192.168.14.24
http3 apache3 192.168.14.1
http4 apache4 192.168.14.11
http5 apache5 192.168.14.12
http6 apache6 192.168.14.17
http7 apache7 192.168.14.7
http8 apache8 192.168.14.21
http9 apache9 192.168.14.13
#!bin/bash
#
cat access.log |awk '{print $3}'|sort -t. -k4|uniq -c|sort -k1

命令解析:

1、cat access.log  >为获取文档access.log的内容

2、awk '{print $3}' >为获取从管道中传过来的每一行字符串中的第三个字段;比如http9 apache9 192.168.14.13从管道中传过来,只获取第三个字段,即192.168.14.13

3、sort -t. -k4 >将管道中传来的内容,每一行使用"."进行分隔,分隔完成后,取每一行的第四个字段进行排序

4、uniq -c >将相同的行进行统计,但uniq只能识别和统计相邻的行,所以一般先排序后再统计

实例三:

需求:统计各程序占用的内存之和

#!/bin/bash
declare -i sum=0    #声明一个整数sum,且其值为0
for n in `ps aux |grep -v 'TIME COMMAND'| awk '{print $6}'`  #for循环获取命令"ps aux | awk '{print $6}'"生成每一行字符串
do
    sum=$[ $sum + $n ]
done
echo "$sum"  #使用echo 输出总和sum的值

脚本亮点:

1、使用for循环对目标内容进行遍历

2、ps aux >为获取程序的运行情况;ps的另一种选项搭配为:ps -ef

3、sum=$[$sum+$n] >求和的方式之一,也是笔者习惯的用法,过几天,笔者将在其他文章中详细介绍分享shell运算的知识

4、grep -v 'TIME COMMAND' >此命令是将管道中传过来的每一行【管道每次只传一行】,若包含有字符'TIME COMMAND'则忽略此行,-v是忽略或者丢弃的作用;

实例四:

需求:检测机器存活

#!/bin/bash
ping -c 2 192.168.14.2
if [ $? -eq 0 ];then
    echo "服务器192.168.14.2能ping通"
else
    echo "服务器192.168.14.2不能ping通"
fi

脚本亮点

1、ping -c 2 ...>对ip只ping两次,限制了默认的一直ping操作

2、$? 是上一条命令的退出码,若上一条命令成功运行则返回0值;否则会返回其他非0值;ping ip不通,则命令返回值为非0

 

实例五:

需求:找到/123目录下所有后缀名为.txt的文件;

要求:1、批量修改.txt为.txt.bak  2、把所有.bak文件打包压缩为123.tar.gz  3、批量还原文件的名字,即把增加的.bak再删除

提示:1、find用来查找所有.txt文件  2、tar用来打包文件   3、用for循环还原文件名

# ll
总用量 0
-rw-r--r--. 1 root root 0 10月  3 20:36 1.txt
-rw-r--r--. 1 root root 0 10月  3 20:36 2.txt
-rw-r--r--. 1 root root 0 10月  3 20:36 3.txt
-rw-r--r--. 1 root root 0 10月  3 20:36 4.txt
-rw-r--r--. 1 root root 0 10月  3 20:36 sdf.txt
#!/bin/bash 
find /123/ -type f -name "*.txt" >txt.list
find /123/ -type f -name "*.txt" | xargs -n1 -i mv {} {}.bak  #改名
#find /123/ -type f -name "*.txt" -exec mv {} {}.bak \;       #改名,这是另一种实现方式

tar -cfvz 123.tar.gz `find -type f -name "*.bak"|xargs `     #打包压缩

for f in `cat txt.list`            #还原名字
do
         mv $f.bak $f
done

#!/bin/bash
find /123/ -type f -name "*.txt" > /tmp/txt.list
for f in `cat /tmp/txt.list`
do
        mv $f $f.bak
done
#find /123/ -type f -name *.txt |xargs -i mv {} {}.bak
#find /123/ -type f -name *.txt -exec mv {} {}.bak \;
for f in `cat /tmp/txt.list`
do
        echo $f.bak
done > /tmp/txt.bak.list
tar -czvf 123.tar.gz `cat /tmp/txt.bak.list |xargs`
for f in `cat /tmp/txt.list`
do
        mv $f.bak $f
done

脚本亮点:

1、xargs -n1 -i mv {} {}.bak >命令xargs默认是将管道传过来的参数"一并"传给后续命令;-n1 则是一次只传一个参数;-i 则是结合{}使用,也就是说要使用{}就要搭配 -i; {}则是指xargs传过来的一个参数,需搭配 -i 使用

2、find命令中其实就有[-exec|-ok COMMAND \;]搭配使用

3、find -type f -name "*.bak" | xargs 等价于 将"find -type f -name "*.bak”"命令获取的所有文件一并传给命令tar 进行打包

4、由于无法使用{}来将文件名修改成比原来更短,所以只能用for循环遍历,且事先需要将原文件名保留在一个文档中

实例六

需求:检测80端口

 #!/bin/bash
 stat=`netstat -lntp | grep ':80'|awk '{print $6}'`
 if [ -z $stat ];then
        echo "80端口没有使用"
 else
        echo "$stat"
 fi

脚本亮点:

1、if [ -z $stat ] >此处使用if语句进行判断,-z 则是判断遍历$stat 是否为空,为空则返回真;不为空则返回假

实例七:

需求:删除字母:把一个文本文档的前5行中包含字母的行删除掉,同时把6到10行中的全部字母删除掉

提示:sed命令

[root@localhost shell_xiti]# vim test
  1 sdffg
  2 123332
  3 sdfsdg34r
  4 sdf232
  5 23425432
  6 f34t
  7 34rt43
  8 324r2f
  9 23r2
 10 334
 11 t34r
 12 334r
#!/bin/bash 
declare -i first=1
while read line
do
        str=`echo "$line"|sed 's/[^a-zA-Z]//g'`
        if [ -z $str ]&&[ $first -le 5 ]
        then
                echo "$line"
        fi
        sttr=`echo "$line"|sed 's/[a-zA-Z]//g'`
        if [ $first -gt 5 ]&&[ $first -le 10 ]
        then
                echo "$sttr"
        fi
        if [ $first -gt 10 ];then
                echo "$line"
        fi
        first=$[$first + 1 ]
done <test

 

 

 

1、使用自增变量$first来定位处理文档的特定行

2、if [ -z $str ]&&[ $first -le 5 ] >if语句的双条件判断

3、sed 's/[^a-zA-Z]//g' >此命令是将传入的每一行中非字母的字符去掉

4、sed 's/[a-zA-Z]//g' >此命令是将传入的每一行中的字母去掉

【脚本二】

#!/bin/bash
sed -n '1,5'p 1.txt|sed '/[a-zA-Z]/d'
sed '1,5d' 1.txt |sed '1,5s/[a-zA-Z]//g'

脚本亮点:

1、sed -n '1,5'p 1.txt >此命令是将文档1.txt中的第1行到第5行内容打印出来,即输出到后面的管道符

2、sed '1,5d' 1.txt >此命令是将文档1.txt中的前五行删除【不影响文档1.txt实际内容】,然后将剩余内容输出到后面的管道

 

实例八:【找单词】

需求:用shell打印下面的这句话中字母数小于6的单词;Bash also interprets a number of multi-character options.

提示:1、for循环遍历所有单词  2、wc -L 获取字符串长度

【脚本一】

#!/bin/bash 
str="Bash also interprets a number of multi-character options."
for n in $str
do
        num=`echo "$n"|wc -L`
        if [ $num -lt 6 ];then
                echo "$n"
        fi
done

脚本亮点:

1、wc -L >此命令能获取字符串的字节数量,也就是字符串长度

【脚本二】

#!/bin/bash
c="Bash also interprets a number of multi-character options."
n=`echo $c|awk -F '[ +-.]' '{print NF}'`
for ((i=1;i<$n;i++))
do
        l=`echo $c|awk -F '[ +-.]' -v j=$i '{print $j}'|wc -L`
        if [ $l -lt 6 ]
        then
                echo $c|awk -F '[ +-.]' -v j=$i '{print $j}'
        fi
done

脚本亮点:

1、此脚本multi视为单个字符串

2、awk -F '[+-,]' -v j=$i '{print $j}' >此命令的作用是将传入的每一行字符串,只有有"+-,"就需要分隔;-v 此选项是在awk中赋值,不能直接使用{print $i},因为awk不能识别外面的变量

 

实例九:【输入数字执行命令】

需求:写一个脚本实现如下功能:输入亦歌数字,然后运行对应的一个命令。

显示命令如下:

*cmd meau**   1-date  2-ls  3-who  4-pwd

当输入1时,会运行date,输入2时运行ls,以此类推

提示:case判断

【脚本一】

#!/bin/bash
menu (){
cat <<EOF
        1-date
        2-ls
        3-who
        4-pwd
EOF
}
menu
read -t 10 -p "please choose a num:" num
case $num in
1)
        date +%F;;
2)
        ls;;
3)
        who;;
4)
        pwd;;
*)
        echo "Usage:[1|2|3|4]";;
esac

脚本亮点:

1、使用函数menu () {COMMAND} 显示选择菜单

2、read -t 10 -p "..."  num >此命令是将用户键入的数字保存在变量num中,且-t 表示只等待10s;-p 为提示用户输入的信息

3、case语句的使用,最后的"*)"为异常输入的处理

【脚本二】相同功能

#!/bin/bash
echo "*cmd meau** 1 - date 2 - ls 3 - who 4 - pwd"
read -p "Please input a number:" n
if [ -z "$n" ]
then
        echo "请输入一纯数字,范围1-4。"<br>     exit
fi
n1=`echo $n|sed 's/[0-9]//g'`
if [ -n "$n1" ]
then
        echo "请输入一个纯数字,范围1-4。"
        exit
fi
case $n in
        1)
        date
        ;;
        2)
        ls
        ;;
        3)
        who
        ;;
        4)
        pwd
        ;;
        *)
        echo "请输入1-4的数字"
        ;;
esac

 

实例十:【批量创建用户】

需求:添加user_00-user_09 10个用户,并且给他们设置一个随机密码,密码要求10位包含大小写字母以及数字,注意需要把每个用户的密码记录到一个日志文件里。

提示:1、随机密码使用命令mkpasswd  2、在脚本中给用户设置密码,可以使用echo然后管道passwd命令

3、seq 实现数字递增 

#!/bin/bash
string=user_0
for i in `seq 0 9`
do
    user=$string$i
    useradd $user
    if [ $? -eq 0 ];then
        pass=`mkpasswd -l 10 -s 0`
        echo "$pass" | passwd --stdin $user
        echo "$user $pass" >>pass.txt
    else
        echo "此用户$user已存在"
    fi
done

脚本亮点:

1、`seq 0 9` >此命令生成0到9的数列

2、user=$string$i >字符串变量叠加

3、mkpasswd -l 1- -s 0 >使用mkpasswd 生成长度为10且包含0个特殊字符的字符串

4、echo "$pass" |passwd --stdin $user >--stdin 重定向标准输入

  • 2
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值