Linux shell脚本100道练习题(每日更新)

1. 创作目的

        为了加强和巩固自身对linux shell脚本的熟悉程度,通过100道练习题强化shell能力,同时分享自己的劳动成果给很多需要提升脚本能力的朋友,大家一起共同进步;

2. 练习题100道合集

2.1 练习题001

【题目要求】

请生成日期格式为yyyy-MM-dd的日志文件,每日生成一个文件, 例如生成的文件名为2024-04-28.log, 并且把磁盘的使用情况写到到这个文件中,同时将文件放到指定目录中,并删除一年前的日志记录; 不用考虑cron,仅仅写脚本即可

 2.1.1 知识巩固
Date的用法

#打印当前时间
[root@kdc-server shell]# date
Sun Apr 28 02:51:21 CST 2024
#打印当年年份最后两位
[root@kdc-server shell]# date +%y
24
#打印当前完整年份
[root@kdc-server shell]# date +%Y
2024
#打印当月月份
[root@kdc-server shell]# date +%m
04
#打印当前小时数
[root@kdc-server shell]# date +%H
02
#打印当前秒数
[root@kdc-server shell]# date +%s
1714243745
#打印当前分钟的第几秒
[root@kdc-server shell]# date +%S
11
#打印一个星期的第几天,这里是0,表示星期天[0-6]
[root@kdc-server shell]# date +%w
0
#打印今年第几周
[root@kdc-server shell]# date +%W
17
#打印格式yyy-mm-dd的日期
[root@kdc-server shell]# date +%F
2024-04-28
#打印当前完整月份
[root@kdc-server shell]# date +%B
April
#打印当前月份缩写
[root@kdc-server shell]# date +%b
Apr


df命令的用法

[root@kdc-server ~]# df -h
Filesystem               Size  Used Avail Use% Mounted on
devtmpfs                 898M     0  898M   0% /dev
tmpfs                    910M     0  910M   0% /dev/shm
tmpfs                    910M  9.7M  901M   2% /run
tmpfs                    910M     0  910M   0% /sys/fs/cgroup
/dev/mapper/centos-root   17G  2.0G   16G  12% /
/dev/sda1               1014M  151M  864M  15% /boot
cm_processes             910M     0  910M   0% /run/cloudera-scm-agent/process
tmpfs                    182M     0  182M   0% /run/user/0


find命令的用法 后续补充
xargs命令用法  后续补充
-mtime命令用法 后续补充
2.1.2 脚本内容
#! /bin/bash

##生成yyyy-mm-dd格式的时间字符串
logname=`date +%F`
#指定日志存放的路径
dir=/opt/logs/disklog

#判断路径是否存在,不存在则创建
if [ ! -d $dir ]
then
        mkdir -p $dir
fi

#将磁盘信息写入日志文件
df -h > $dir/$logname.log

#查询指定目录下修改时间在365天以前的文件,并执行删除
find $dir/ -mtime +365 | xargs rm -f

2.2 练习题002

【日志格式】

112.111.12.248 – [25/Sep/2013:16:08:31 +0800]formula-x.haotui.com “/seccode.php?update=0.5593110133088248″ 200″http://formula-x.haotui.com/registerbbs.php” “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1;)”
61.147.76.51 – [25/Sep/2013:16:08:31 +0800]xyzdiy.5d6d.com “/attachment.php?aid=4554&k=9ce51e2c376bc861603c7689d97c04a1&t=1334564048&fid=9&sid=zgohwYoLZq2qPW233ZIRsJiUeu22XqE8f49jY9mouRSoE71″ 301″http://xyzdiy.5d6d.com/thread-1435-1-23.html” “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)”

 2.2.1 知识巩固
awk的用法
可以处理带空格的行数据

awk的使用格式
awk ‘条件1{执行语句1}条件2{执行语句2}条件3{执行语句3}’ filename 条件语句可选(文件名可选)
awk ‘BEGIN{执行语句1}{执行语句2}END{执行语句3}’ filename  BEGIN和END条件语句可选(文件名可选)

#打印磁盘的使用信息
[root@kdc-server ~]# df -h 
Filesystem               Size  Used Avail Use% Mounted on
devtmpfs                 898M     0  898M   0% /dev
tmpfs                    910M     0  910M   0% /dev/shm
tmpfs                    910M  9.6M  901M   2% /run
tmpfs                    910M     0  910M   0% /sys/fs/cgroup
/dev/mapper/centos-root   17G  2.0G   16G  12% /
/dev/sda1               1014M  151M  864M  15% /boot
cm_processes             910M     0  910M   0% /run/cloudera-scm-agent/process
tmpfs                    182M     0  182M   0% /run/user/0

#打印第二列和第五列的信息
[root@kdc-server ~]# df -h |awk '{printf $2 "\t" $5 "\n"}'
Size    Use%
898M    0%
910M    0%
910M    2%
910M    0%
17G     12%
1014M   15%
910M    0%
182M    0%

#打印目录的信息
[root@kdc-server ~]# awk '{print $NF}' /etc/passwd 
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
Management:/:/sbin/nologin
bus:/:/sbin/nologin
polkitd:/:/sbin/nologin
SSH:/var/empty/sshd:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
chrony:x:998:996::/var/lib/chrony:/sbin/nologin
carlos:x:1000:1000:carlos:/home/carlos:/bin/bash
Manager:/var/lib/cloudera-scm-server:/sbin/nologin
apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin
Daemon:/var/lib/rpcbind:/sbin/nologin

#以:为分隔符,打印目录的信息
[root@kdc-server ~]# awk 'BEGIN{FS=":"}{print $NF}' /etc/passwd 
/bin/bash
/sbin/nologin
/sbin/nologin
/sbin/nologin
/sbin/nologin
/bin/sync
/sbin/shutdown
/sbin/halt
/sbin/nologin
/sbin/nologin
/sbin/nologin
/sbin/nologin
/sbin/nologin
/sbin/nologin
/sbin/nologin
/sbin/nologin
/sbin/nologin
/sbin/nologin
/sbin/nologin
/bin/bash
/sbin/nologin
/sbin/nologin
/sbin/nologin
[root@kdc-server ~]# awk '{print $NF}' /etc/passwd 
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
Management:/:/sbin/nologin
bus:/:/sbin/nologin
polkitd:/:/sbin/nologin
SSH:/var/empty/sshd:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
chrony:x:998:996::/var/lib/chrony:/sbin/nologin
carlos:x:1000:1000:carlos:/home/carlos:/bin/bash
Manager:/var/lib/cloudera-scm-server:/sbin/nologin
apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin
Daemon:/var/lib/rpcbind:/sbin/nologin

#以:为分隔符,打印目录的信息,并去重统计
[root@kdc-server ~]# awk 'BEGIN{FS=":"}{print $NF}' /etc/passwd | uniq -c
      1 /bin/bash
      4 /sbin/nologin
      1 /bin/sync
      1 /sbin/shutdown
      1 /sbin/halt
     11 /sbin/nologin
      1 /bin/bash
      3 /sbin/nologin
2.2.2 脚本内容

#打印1.log日志中第一个参数,即IP地址;
#排序,去重统计出现的次数,即访问数量;
#再次逆序排序,可以查看在最前方统计次数的排序结果
awk '{print $1}' 1.log|sort |uniq -c |sort -n -r

2.3 练习题003

写一个脚本计算一下linux系统所有进程占用内存大小的和。

  • ps命令用法
  • for循环
  • 加法运算
 2.3.1 知识巩固
ps的用法

#显示内存信息(截取部分内容),RSS即内存占用大小
[root@kdc-server ~]# ps aux
USER        PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root          1  0.0  0.3 128008  6664 ?        Ss   13:04   0:02 /usr/lib/systemd/systemd --switched-root --system --deserialize 22
root          2  0.0  0.0      0     0 ?        S    13:04   0:00 [kthreadd]
root          4  0.0  0.0      0     0 ?        S<   13:04   0:00 [kworker/0:0H]
root          6  0.0  0.0      0     0 ?        S    13:04   0:03 [ksoftirqd/0]
root          7  0.0  0.0      0     0 ?        S    13:04   0:00 [migration/0]
root          8  0.0  0.0      0     0 ?        S    13:04   0:00 [rcu_bh]
root          9  0.0  0.0      0     0 ?        S    13:04   0:07 [rcu_sched]
root         10  0.0  0.0      0     0 ?        S<   13:04   0:00 [lru-add-drain]
root         11  0.0  0.0      0     0 ?        S    13:04   0:01 [watchdog/0]
root         12  0.0  0.0      0     0 ?        S    13:04   0:01 [watchdog/1]
root         13  0.0  0.0      0     0 ?        S    13:04   0:00 [migration/1]

for循环用法

for n in 范围
do
    表达式
done


free的用法
[root@kdc-server shell]# free
              total        used        free      shared  buff/cache   available
Mem:        1863032      344296     1332812        9848      185924     1362948
Swap:       2097148           0     2097148
2.3.2 脚本内容
#! /bin/bash

sum=0
for n in `ps aux | grep -v 'TIME COMMAND' | awk '{print $6}t'`
do
        sum=$[$sum+$n]
done
echo $sum

2.4 备份数据库

题目要求
设计一个shell脚本来备份数据库,首先在本地服务器上保存一份数据,然后再远程拷贝一份,本地保存一周的数据,远程保存一个月。

假定,我们知道mysql root账号的密码,要备份的库为discuz,本地备份目录为/bak/mysql, 远程服务器ip为192.168.123.30, 远程提供了一个rsync服务,备份的地址是 192.168.123.30::backup  . 写完脚本后,需要加入到cron中,每天凌晨3点执行。

核心要点
备份数据库的命令
同步到远程去的命令
本地一周,可以用date +%w做为后缀,远程一个月可以用date +%d做为后缀

 2.4.1 知识巩固
#打印时间
[root@kdc-server shell]# date +%F
2024-05-01
#打印一周的第几天[0-6]
[root@kdc-server shell]# date +%w
3
#打印一个月的第几天
[root@kdc-server shell]# date +%d
01

#mysql备份脚本语法
mysqldump -u username -p dbname [tbname ...]> filename.sql

#恢复脚本
mysql -u root -p < C:\all.sql

#从本地同步远程
# 默认SSH端口
rsync -avz -e ssh /home/bear/mydir root@114.215.183.37:/home/bear/workdir

# 指定SSH端口
rsync -avz -e 'ssh -p 5555' /home/bear/mydir root@114.215.183.37:/home/bear/workdir

#从远程同步到本地
# 默认SSH端口
rsync -avzP -e ssh root@114.215.183.37:/home/bear/workdir /home/bear/mydir

# 指定SSH端口
rsync -avzP -e 'ssh -p 5555' root@114.215.183.37:/home/bear/workdir /home/bear/mydir
2.4.2 脚本内容
#! /bin/bash

#打印本周星期几[0-6]
d1=`date +%w`
#打印本月的天数[0-31]
d2=`date +%d`

local_dir=/bak/mysql
remote_dir=192.168.123.30::backup

#mysql备份数据库脚本到本地
mysqldump -uroot -proot discuz > $local_dir/discuz.sql.$d1
#同步到远程
rsync -az $local_dir/discuz.sql.$d1 $remote_bakdir/discuz.sql.$d2

2.5  监控502


题目要求
服务器上跑的是LNMP环境,近期总是有502现象。502为网站访问的状态码,200正常,502错误是nginx最为普遍的错误状态码。

由于502只是暂时的,并且只要一重启php-fpm服务则502消失,但不重启的话,则会一直持续很长时间。

所以有必要写一个监控脚本,监控访问日志的状态码,一旦发生502,则自动重启一下php-fpm。

我们设定:

1)access_log  /data/log/access.log

2)脚本死循环,每10s检测一次(假设每10s钟的日志条数为300左右)

3)重启php-fpm的方法是  /etc/init.d/php-fpm restart

核心要点
用curl检测状态码是否是502或者通过分析访问日志判断状态码的比率
重启php-fpm服务的命令

2.5.1 知识巩固
#grep的用法
grep [options] pattern [files]

pattern - 表示要查找的字符串或正则表达式。
files - 表示要查找的文件名,可以同时查找多个文件,如果省略 files 参数,则默认从标准输入中读取数据。

-i:忽略大小写进行匹配。
-v:反向查找,只打印不匹配的行。
-n:显示匹配行的行号。
-r:递归查找子目录中的文件。
-l:只打印匹配的文件名。
-c:只打印匹配的行数。

[root@kdc-server shell]# echo "hello world" | grep -c world
1

#在文本中匹配带有error的日志
[root@kdc-server shell]# grep -i error app.log

#结合tail命令实时查看error日志
[root@kdc-server shell]# tail -f app.log | grep -i error

[root@kdc-server shell]# tail -f app.log | grep -A 9 -i error

-A 9: (after)匹配日志后的后9行日志
-B 9: (before)匹配日志后的前9行日志
-C 9: 匹配日志后的前后9行日志

#wc的用法
wc (word count)命令常用于计算文件的行数、字数和字节数

-l , --lines : 显示行数;
-w , --words : 显示字数;
-m , --chars : 显示字符数;
-c , --bytes : 显示字节数;
-L , --max-line-length : 显示最长行的长度

[root@kdc-server shell]# wc -l /root/shell/sh_008.sh 
25 /root/shell/sh_008.sh
[root@kdc-server shell]# wc /root/shell/sh_008.sh 
 25  59 430 /root/shell/sh_008.sh
[root@kdc-server shell]# wc -w /root/shell/sh_008.sh 
59 /root/shell/sh_008.sh
[root@kdc-server shell]# wc -m /root/shell/sh_008.sh 
422 /root/shell/sh_008.sh
[root@kdc-server shell]# wc -L /root/shell/sh_008.sh 
80 /root/shell/sh_008.sh
2.5.2 脚本内容
#! /bin/bash

#日志存储的位置
log=/data/log/access.log

while :
do
    #从日志中最后300行找到502出现的次数,防止有些数字也有502 需要在前后加上空格
    502_n=`tail -n 300 $log | grep -c ' 502 '`
    #判断502状态码是否为空
    if [ -z "$502_n"]
    then
        exit
    fi

   #判断502出现次数是否大于100
   if [$502_n -gt 100 ]
   then
        #重启php,将错误日志写入指定文件
        /etc/init.d/php-fpm restart >/dev/null 2>/tmp/php-fpm.err
        #查询进程是否已经启动
        fpm_p_n = `pgrep -l php-fpm |wc -l`
        #判断进程出现的次数,如果为0就是启动失败
        if [ $fpm_p_n -eq 0 ]
        then 
          #发送邮件
          python mail.py xxx@xx.com  "php.fpm重启失败" "`head -tmp/php-fpm.err`"
          exit
        fi
   fi

#暂停10秒,每10秒监控一次
sleep 10
done

2.6 删除行

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

2.6.1 内容回顾
#sed的用法

# 将第3行中所有的 bin 替换成 BIN
[root@kdc-server shell]# sed '3 s/bin/BIN/g' /etc/passwd   
# 将第2到5行中所有的 bin 替换成 BIN 
[root@kdc-server shell]#sed '2,5 s/bin/BIN/g' /etc/passwd  
# 将第10行到最后一行中所有的 bin 替换成 BIN 
[root@kdc-server shell]#sed '10,$ s/bin/BIN/g' /etc/passwd 
2.6.2 脚本内容
#!/bin/bash
#打印前五行,并删除含中带字母的行
sed -n '1,5'p 1.txt |sed '/[a-zA-Z]/d'
#删除前面5行,原来的6-10变成了1-5;在匹配带字母的内容替换成空;
sed '1,5d' 1.txt |sed '1,5s/[a-zA-Z]//g'

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值