侧边栏壁纸
博主头像
张种恩的技术小栈博主等级

行动起来,活在当下

  • 累计撰写 748 篇文章
  • 累计创建 65 个标签
  • 累计收到 39 条评论

目 录CONTENT

文章目录

Shell 练习

zze
zze
2020-04-11 / 0 评论 / 0 点赞 / 684 阅读 / 18227 字

不定期更新相关视频,抖音点击左上角加号后扫一扫右方侧边栏二维码关注我~正在更新《Shell其实很简单》系列

练习一

选择

1、函数内如何设置局部变量 (A

  • A:local
  • B:export
  • C:source
  • D:function

2、以下哪一种指令显示的结果为 $test (C)

  • A:\echo $test
  • B:echo "$test"
  • C:echo '$test'
  • D:echo "${test}"

3、一个 bash shell 脚本的第 1 行是什么 (A)

  • A:#!/bin/bash
  • B:#/bin/bash
  • C:#/bin/csh
  • D:/bin/bash

4、以下参数,如何在执中查看执行过程 (A)

  • A:-x
  • B:-X
  • C:-s
  • D:-S

简答

1、如何显示默认的环境变量

使用 printenvenv 命令。

2、如何设置环境变量与局部变量

/etc/profile/etc/bashrc~/.bash_profile~/.bashrc 下使用 export 命令导出的变量为环境变量,在函数块中使用 local 定义的变量为局部变量。

编程

1、按照时间生成文件 2018-05-22.log 将每天的磁盘使用状态写入到对应日期的文件

$ df -h | awk 'NR==2{print "总容量: "$2,"\n已使用:"$3,"\n剩余可用:"$4,"\n使用率:"$5}' > `date +%F`.log

2、统计Nginx日志中每个IP的访问量有多少,日志如下:

192.168.56.1 - - [21/May/2018:20:44:06 -0400] "GET /index.html HTTP/1.0" 404 169 "-" "ApacheBench/2.3" "-"/code/index.html
$ cat access.log | awk '{print $1}' | sort | uniq -c | sort -nr

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

$ ps -e -o 'rss' | awk '{total+=$1}END{print total/1024"M"}'
109.605M

5、在 /backup 下创建 10 个 .txt 的文件,找到 /backup 目录下所有后缀名为 .txt 的文件

  1. 批量修改 txttxt.bak
  2. 把所有的 .bak 文件打包压缩为 123.tar.gz
  3. 批量还原文件的名字,及把增加的 .bak再删除
#!/bin/bash
ls /backup/*.txt | xargs -n1 | xargs -i mv {} {}.bak
tar zPcf 123.tar.gz /backup/*.bak
for file_name in `ls /backup/*.bak`;do
        mv ${file_name} ${file_name%.*}
done

练习二

填空

1、写出以下位置参数的作用

  • $0:脚本名称
  • $n:第 n 个参数值
  • $#:参数个数
  • $*:所有参数,当外层使用 "" 时当做一整个字符串处理
  • $@:所有参数,当外层使用 "" 时每个参数作为一个单独的字符串

2、写出以下特殊变量的作用

  • $?:上一条命令的退出状态码
  • $$:当前脚本进程号
  • $!:上一个后台运行的进程的进程号
  • $_:命令指定的最后一个参数

3、写出以下字母比较符的作用

  • -eq:相等
  • -ne:不相等
  • -gt:大于
  • -ge:大于等于
  • -lt:小于
  • -le:小于等于

4、写出下面特殊变量扩展的意义

  • ${oldboy}:输出变量 oldboy 的值
  • ${#oldboy}:输出变量 oldboy 的值的长度
  • ${url#*.}:自左向右删除字符串开头到第一次出现 . 的位置
  • ${url##*.}:自左向右删除字符串开头至最后一次出现 . 字符之间的所有字符
  • ${url%.*}:自右向左删除字符串尾部到第一次出现 . 的位置
  • ${url%%.*}:自右向左删除字符串尾部到最后一次出现 . 的位置

简答

1、写出 3 个以上可用于计算的命令

  • expr
  • bc
  • let

编程

1、输入两个整数计算这两个整数的相加,相减,相乘,相除,求余的结果

#!/bin/bash
read -p 'input num1: ' num1
read -p 'input num2: ' num2

echo "$num1 + $num2 = $[ num1 + num2] "
echo "$num1 - $num2 = $[ num1 - num2] "
echo "$num1 * $num2 = $[ num1 * num2] "
echo "$num1 / $num2 = $[ num1 / num2] "

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

$ sed -r '1,5{/[a-z]+/d};6,10{s/[a-z]//g}' text.txt

3、打印下面这句话中字母数小于 5 的单词

I am lizhenya teacher I am 18
$ echo I am lizhenya teacher I am 18 | awk 'BEGIN{RS=" "} length($1)<5{print $1}' 
I
am
I
am
18

4、写个 shell,看看你的 linux 系统中是否有自定义用户(普通用户),若是有,一共有几个?

$ cat /etc/passwd | awk -F: '$3>=1000 && $NF != "/sbin/nologin"{total+=1}END{print "一共有"total"个普通用户"}'
一共有3个普通用户

5、写一个 shell 脚本来看看你使用最多的命令是哪些,列出你最常用的命令 top10

$ history | awk '{print $2}' | sort | uniq -c | sort -nr | head -10 | awk 'BEGIN{ idx=1 } {print idx,$2;idx+=1}'

6、编写一个脚本,计算 100 以内所有能被 3 整除数字的和

#!/bin/bash
total=0
for ((i=1;i<=100;i++));do
        [ $[ i % 3 ] -eq 0 ] && let total=$total+$i
done
echo "1 ~ 100 内能被 3 整除数字的和为 $total"

练习三

填空

1、填写以下字符串测试操作符的意义

  • -n:字符串不为空;
  • -z:字符串为空;

2、写出下面条件测试的含义

  • [ -e dir|file ]:是否存在指定的目录为文件;
  • [ -d dir ]:是否存在指定的目录;
  • [ -f file ]:是否存在指定的文件;
  • [ -r file ]:当前用户对指定文件是否有读权限;
  • [ -x file ]:当前用户对指定文件是否有执行权限;
  • [ -w file ]:当前用户对指定文件是否有写权限;

简答

1、定义变量内容,不加引号、单引号、双引号、反引号结果有什么不同?应该怎么用?(3分)

  • 不加引号:直接使用指定的内容,内容中有变量时变量会被替换,但是当内容中有空格时会报错;
  • 单引号:按单引号中的内容原样输出;
  • 双引号:会转义内容中的变量;
  • 反引号:会将内容交给 bash 指定,将执行结果赋值给变量;

编程

1、将下面的条件表达式改写为 if 条件语句

[ -f /etc/hosts ] && echo !

#!/bin/bash
if [ -f /etc/hosts ];then
    echo !
fi

2、写一个脚本,实现判断 10.0.1.0/24 网络里,当前在线用户的 IP 有哪些?

#!/bin/bash
for ip in 10.0.1.{1..253};do
        ping -c 1 -W 1 -i 0.01 $ip &> /dev/null && echo $ip
done

3、用 shell 处理以下内容

the squid project provides a number of resources toassist users design,implement and support squid installations. Please browsethe documentation and support sections for more infomation

按单词出现频率降序排序

$ cat 1.txt | awk -F"[.,]" 'BEGIN{RS=" "} {print $1;if($2!="")print $2}' | sort | uniq -c | sort -nr | awk '{print $2}'

按字母出现频率降序排序!

$ cat 1.txt | sed -r 's/[^a-z]//g;s/([a-z])/\1 /g;' | xargs -n1 | sort | uniq -c | sort -nr | awk '{print $2}'

4、使用 ps aux 查看系统进程发现有 100 多个 test.sh 脚本正在运行,如何杀死所有的 test.sh

$ ps aux | grep 'test.sh' | grep 'grep' -v | awk '{print $2}' | xargs -i kill -9 {}

5、写一个猜数字脚本,当用户输入的数字和预设数字(随机生成一个 0-100 的数字)一样时,直接退出,否则让用户一直输入,并且提示用户的数字比预设数字大或者小

#!/bin/bash
random_num=$[RANDOM%100]
echo $random_num
read -p 'input a num: ' input_num
 
until [ $input_num -eq $random_num ]
do
        [ $input_num -gt $random_num ] && echo '大了' || echo '小了'
        read -p 'input a num: ' input_num
done
echo '恭喜你猜中了'

6、用 Shell 实现,把一个文本文档中只有一个数字的行给打印出来

$ cat 1.txt | awk '$0 ~ /^\s*[0-9]+\s*$/{print $0}' | egrep -o '[0-9]+'

7、写一个 Shell 脚本通过 curl 命令返回的状态码来判定所访问的网站是否正常,比如当前状态码 200,才算正常。

#!/bin/bash
curl -sI $1 | head -1 | grep '200 OK' &> /dev/null
if [ $? -eq 0 ];then
        echo "正常"
else 
        echo "不正常"
fi

练习四

1、使用 while 循环使 1 加到 100

#!/bin/bash
i=1

while [ $i -lt 100 ];do
        let i++
done
echo $i

2、查看磁盘/当前使用状态,如果使用率超过 80% 则把结果输出到/var/log/disk.err

#!/bin/bash

disk_used=`df -h | awk 'NR==2{print $(NF-1)}'`
disk_used=${disk_used/%\%*}

if [ $disk_used -gt 80 ];then
        echo "${disk_used}%" > /var/log/disk.err
fi

3、脚本批量创建 10 个用户,密码统一为 123,需要对用户输入是否为数字和输入的名字是否为空做判断

#!/bin/bash

passwd='123'
count=1
until [ $count -gt 10 ];do
        read -p "[${count}]输入要创建用户的用户名: " username
        if [[ $username =~ ^[0-9]+$ ]] || [ -z $username ];then
                echo "用户名不能为空或纯数字"
                continue
        fi
        if `id $username &> /dev/null`;then
                echo "该用户已存在"
                continue
        fi
        useradd $username && echo $passwd | passwd $username --stdin &> /dev/null && echo "$username 用户已创建!"
        let count++
done

4、使用 case 语句编写 nginx 启动脚本

#!/bin/bash
case "$1" in
'stop') 
        nginx -s stop &> /dev/null
        ;;
'start')
        nginx &> /dev/null
        ;;
'reload')
        nginx -s reload &> /dev/null
        ;;
*)
        echo 'unknown option!!!'
        ;;
esac

if [ $? -eq 0 ];then
        echo "$1 success !!"
else
        echo "$1 failed !!!"
fi

5、要求:
• 执行脚本后,输入英文名字全拼,产生随机数 1-99 之间的数字,数字越大就去参加项目实践,前面已经抓到的数字,下次不能在出现相同数字。
• 第一个输入名字后,屏幕输出信息,并将名字和数字记录到文件里,程序不能退出继续等待别的学生输入。

#!/bin/bash
random_num(){
        while :;do
                random_num=$[RANDOM%100]
                cat users.txt | awk '{print $2}' | egrep "^${random_num}$" &> /dev/null && continue
                break
        done
        echo $random_num
}

while :;do
        read -p '输入名字的拼音(退出请输入 exit): ' username
        if [ $username == 'exit' ];then
                echo '当前前三名: '
                cat users.txt | awk '{print $2,$1}' | sort -nr | head -3
                exit 0
        fi
        echo "$username $(random_num)" >> users.txt
done

6、打印一个菜单如下,然后用循环加case语句输出用户输入菜单选项的结果(8分)

  • h 显示命令帮助
  • f 显示登陆信息
  • d 显示磁盘挂载
  • m 查看内存使用
  • u 查看系统负载
  • q 退出程序
#!/bin/bash
show_help(){
        help_text="
        \t\t|----------------|\n
        \t\t| h 显示命令帮助 |\n
        \t\t| f 显示登陆信息 |\n
        \t\t| d 显示磁盘挂载 |\n
        \t\t| m 查看内存使用 |\n
        \t\t| u 查看系统负载 |\n
        \t\t| q 退出程序\t |\n
        \t\t|----------------|\n
        "
        echo -e $help_text
}
show_help

while :;do
        read -p 'choose a option: ' option
        case $option in
                'h')
                        show_help
                ;;
                'f')
                        last
                ;;
                'd')
                        df -h
                ;;
                'm')
                        free -m
                ;;
                'u')
                        uptime
                ;;
                'q')
                        exit 0
                ;;
        esac
done

练习五

简答

1、写出 breakcontinueexitreturn 的区别

  • break:直接中断循环,继续向下执行
  • continue:终止当前循环,继续下一次循环
  • exit:直接终止当前程序的执行
  • return:用来返回一个函数的执行状态码,值为 0~255 之间

2、查看数组的索引与数组中元素的个数

  • 数组索引:${!test_arr[@]}
  • 元素格式:${#arr[*]}

3、数组 array=(1 2 3 4 5 6) 现在将数组中的 3 替换为 C

array[2]='C'

4、如何定义普通数组与关联数组

  • 普通数组直接使用 (item1 item2 item3 ...) 的方式定义即可
  • 关联数组需要使用 declare -A arr 显式声明

编程

1、生成 0-100 之间的随机数,并相加,直到大于 1000,输出相加的结果

#!/bin/bash
sum=0

until [ $sum -gt 1000 ];do
        rand_num=$[RANDOM%100]
        let sum+=$rand_num
done

echo $sum

2、生成 0-100 之间的随机数,并相加,直到大于1000,并判断最后一个随机数字能否被 3 整除

#!/bin/bash
sum=0

until [ $sum -gt 1000 ];do
        rand_num=$[RANDOM%100]
        let sum+=$rand_num
done

echo $sum
if [ $[rand_num % 3] -eq 0 ];then
        echo "最后一个随机数是 $rand_num, 能被 3 整除"
else
        echo "最后一个随机数是 $rand_num, 不能被 3 整除"
fi

3、判断 /tmp 目录下是否有大于 4k 的文件,如果有则输出该文件的大小与创建时间

$ ll /tmp/ | awk '$5>4096{print "大小: "$5/1024"K","创建时间: "$6,$7,$8}'  
大小: 6.38379K 创建时间: Apr 11 12:00

4、数组 array=(1 2 3 4 5 6) 使用脚本打印出每个元素(每行显示一个元素)

#!/bin/bash
array=(1 2 3 4 5 6)
for i in ${array[*]};do
        echo $i
done

5、使用数组判断 I am oldboy teacher welcome to training class 中字母数大于 6 的单词

#!/bin/bash
array=(I am oldboy teacher welcome to training class)
for word in ${array[*]};do
        [ ${#word} -gt 6 ] && echo $word
done

练习六

1、检测服务器中重要的文件是否被修改吗如果被修改则报警(使用指纹)

#!/bin/bash
check_file="/etc/check_file"
# 将重要的文件或目录保存在数组中
important_path=(/etc/ /backup/)

[ $# -gt 1 ] && [ $1 == 'rebuild' ] && rm -f $check_file

if [ -e $check_file ];then
        echo -e '校验失败的文件如下:\n'
        md5sum -c $check_file 2> /dev/null | grep ': FAILED'
        # 编写报警代码
else
        echo '初始化校验文件'
        for path in ${important_path[*]};do
                if [ -f $path ];then
                        md5sum $path >> $check_file
                elif [ -d $path ];then
                        find $path -type f | xargs -i md5sum {} >> $check_file
                else
                        echo "$path: 路径错误, 只能是普通文件或目录"
                fi
        done
fi

2、计算 nginx 日志中访问最多的 10 个 IP 使用的流量总和

$ awk '{print $1}' access.log | sort | uniq -c | sort -nr -k1 | head -n 10 | awk '{total+=$1} END{print total}'

3、防止DOS攻击(检测 nignx 日志若某个 IP 短时间的 PV 过大则使用防火墙将其禁掉)

#!/bin/bash
# 下例使用 iptables 让每秒请求超过十个的 IP 禁止访问
for ip in `cat access.log | awk '{print $1" "$4}' | sort | uniq -c | awk '$1>2{print $2}'`;do
        iptables -L | egrep ".*DROP.*$ip.*" &> /dev/null || iptables -t filter -A INPUT -s $ip -p tcp -j DROP 
done

4、实时监控服务器 CPU 使用率大于 80%、磁盘使用率大于 80%,内存使用率大于 80% 时报警

#!/bin/bash
cpu_used=`vmstat | awk 'NR==3{print (100-$(NF-2))}'`
disk_used=`df -h | awk 'NR==2{sub("%","");print $(NF-1)}'`
mem_used=`free -m | awk 'NR==2{print $3/$2*100}'`
mem_used=${mem_used%.*}

if [ $cpu_used -gt 80 ];then
        echo 'CPU 过载'
fi
if [ $disk_used -gt 80 ];then
        echo '磁盘过载'
fi
if [ $mem_used -gt 80 ];then
        echo '内存过载'
fi

5、使用源码编译安装 nignx(脚本可以重复执行)。

#!/bin/bash
#

nginx_version='1.16.1'
file_name="nginx-${nginx_version}"

# 安装编译安装需要的依赖包
yum -y install gcc gcc-c++ make automake autoconf libtool pcre* zlib openssl openssl-devel libxml2 libxml2-dev libxslt-devel gd-devel perl-devel perl-ExtUtils-Embed gperftools gperftools-*
# 添加 nginx 用户
id nginx &> /dev/null || useradd -s /sbin/nologin -M nginx
# 检查是否已安装了 nginx
if [ -f /usr/sbin/nginx ];then
        echo "已安装了如下版本的 nginx:"
        /usr/sbin/nginx -v
        exit 1
fi
# 下载 Nginx
[ -f /tmp/${file_name}.tar.gz ] || wget https://mirrors.huaweicloud.com/nginx/${file_name}.tar.gz -O /tmp/${file_name}.tar.gz
[ $? -eq 0 ] && echo '下载源码包成功' || echo '下载源码包失败'
# 解压
cd /tmp && tar xf ${file_name}.tar.gz
 [ $? -eq 0 ] && echo '解压成功' || echo '解压失败'
# 编译
cd /tmp/nginx-${nginx_version} && ./configure --prefix=/usr/share/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --http-client-body-temp-path=/var/lib/nginx/tmp/client_body --http-proxy-temp-path=/var/lib/nginx/tmp/proxy --http-fastcgi-temp-path=/var/lib/nginx/tmp/fastcgi --http-uwsgi-temp-path=/var/lib/nginx/tmp/uwsgi --http-scgi-temp-path=/var/lib/nginx/tmp/scgi --pid-path=/run/nginx.pid --lock-path=/run/lock/subsys/nginx --user=nginx --group=nginx --with-file-aio --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-stream_ssl_preread_module --with-http_addition_module --with-http_xslt_module=dynamic --with-http_image_filter_module=dynamic --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_degradation_module --with-http_slice_module --with-http_stub_status_module --with-http_perl_module=dynamic --with-http_auth_request_module --with-mail=dynamic --with-mail_ssl_module --with-pcre --with-pcre-jit --with-stream=dynamic --with-stream_ssl_module --with-google_perftools_module --with-debug --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -m64 -mtune=generic' --with-ld-opt='-Wl,-z,relro -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -Wl,-E'
# 安装
make && make install
[ $? -eq 0 ] && echo '安装成功' || echo '安装失败'
# 初始化目录
mkdir /var/lib/nginx/tmp/ -p

6、数据库分库分表备份到 /tmp

0

评论区