Linux实战——Shell编程练习(更新12题)

1.公钥批量分发

shell 实现 100 台服务器的公钥的批量分发;LLD 规划:100 台服务器 ip 为:192.168.42.101-201,root 密码:123456。

#远程机器的用户名和密码
password=123456
username=root
#将本机的公钥复制到远程机器的authorized_keys文件中
main(){
sshpass -p $password ssh-copy-id -o StrictHostKeyChecking=no $1 >/dev/null 2>&1
if [ $? -eq 0 ]
then
    echo "192.168.42.$1 is successful..."
fi
}
#检查sshpass工具是否安装
basecheck(){
which sshpass >/dev/null 2>&1
if [ $? -ne 0 ]
then
    yum install sshpass -y >/dev/null 2>&1
fi
}
#检查网络是否畅通,若通畅则发送ssh公钥
netcheck(){
for j in {101..201}
do
    ping -c 1 192.168.42.$j >/dev/null 2>&1
    if [ $? -eq 0 ]
    then
        main $j
    else
        echo "192.168.42.$j 网络不通畅..."
    fi
    done
}
basecheck
netcheck

2.网址中的域名统计

处理以下文件内容,将域名取出并进行计数排序。

http://www.baidu.com/index.html
http://www.baidu.com/1.html
http://post.baidu.com/index.html
http://mp3.baidu.com/index.html
http://www.baidu.com/3.html
http://post.baidu.com/2.html

得到如下结果:

域名出现的次数 域名
2 www.baidu.com
2 post.baidu.com
1 mp3.baidu.com
cat <<EOF
域名出现的次数 域名
EOF
array=(
"http://www.baidu.com/index.html"
"http://www.baidu.com/1.html"
"http://post.baidu.com/index.html"
"http://mp3.baidu.com/index.html"
"http://www.baidu.com/3.html"
"http://post.baidu.com/2.html"
)
#检查临时域名文件是否存在,存在则删除
check(){
test -f yuming.txt
if [ $? -eq 0 ]
then
    rm -rf yuming.txt
fi
}
#域名统计处理及结果输出
operate(){
for var in ${array[@]}
do
    echo $var >> yuming.txt
done
awk -F ‘/‘ ‘{print $3}‘ yuming.txt |sort -r|uniq  -c
}
check
operate
check

其他方法

cut -d / -f3 file.txt |sort -r |uniq -c
awk -F "/"‘{S[$3]=S[$3]+1}END{for(k in S) print k,S[k]}‘ file.txt|sort -r
sed -r ‘s#http://(.*)/.*#\1#g‘ file.txt |sort -r|uniq -c

3.shell+定时计划任务:归档备份

设计一个 shell 程序,在每天凌晨压缩打包/etc 目录下的所有内容,存放在/root/bak 目录里,且文件名为如下形式 yymmdd_etc.tar.gz(yy 为年,mm 为月,dd 为日),该目录保存 7 天内容;Shell 程序 fileback 存放在/usr/bin 目录下。

day="`date +%Y%m%d`"
dir=/root/bak
backupdir="`date +%Y%m%d`_etc.tar.gz"
#查看/root/bak目录是否存在,如果不存在,则创建目录
checkbak(){
if [ ! -e $dir ]
then
    mkdir $dir
fi
}
#压缩打包/etc目录下,存放在/root/bak目录里
backup(){
tar -zcvf /root/bak/$backupdir /etc/ > /dev/null 2>&1
echo "$backupdir 压缩打包成功 successful"
}
#清除7天前的过期文件
clean(){
find $dir -mtime +7 -exec rm -rf {} \;
if [ $? -eq 0 ]
then
    echo "过期数据清除成功 successful"
else
    echo "$day 过期数据清理失败 error,请及时关注"
fi
}
checkbak
backup
clean

4.shell开发运维管理工具(1)

shell 开发运维管理工具,要求:用户交互,当用户输入菜单号时,打印相关内容。

菜单
1. 磁盘分区
2. CPU 负载
3. 剩余内存
4. 退出
输入:1
输出:(主机名,系统版本,分区情况)
hostname:
system:系统版本
---------分区一-----------(分区变量输出)
path:分区一
size:大小
file_os:分区文件系统类型
mount_on:分区挂载点
----------分区二----------
path:分区二
size:大小
file_os:分区文件系统类型
mount_on:分区挂载点
输入:2
输出:
1 分钟平均负载:
5 分钟平均负载:
15 分钟平均负载:
输入:3
输出:
目前可用内存:
可用 Swap 分区:
输入:4
输出:
Bey…
cat <<EOF
---------------------------
        1.磁盘分区
        2.CPU负载
        3.剩余内存
        4.退出
---------------------------
EOF
while true
do
read -p "请选择功能(1~4):" num
case $num in
    1)
        echo "hostname:   `cat /etc/hostname | awk ‘BEGIN{FS="."}{print $1}‘`"
        echo "system:   `uname -r`"
        echo "------------------/dev/sda1--------------------------"
        echo "path:`df -h | awk ‘BEGIN{FS=" "}/^\/dev\/sda1/{print $1}‘`"
        echo "size:`df -h | awk ‘BEGIN{FS=" "}/^\/dev\/sda1/{print $2}‘`"
        echo "file_os:`df -T | awk ‘BEGIN{FS=" "}/^\/dev\/sda1/{print $2}‘`"
        echo "mount_on:`df -h | awk ‘BEGIN{FS=" "}/^\/dev\/sda1/{print $6}‘`"
        echo "------------------/dev/sda2--------------------------"
        echo "path:`df -h | awk ‘BEGIN{FS=" "}/^\/dev\/sda2/{print $1}‘`"
        echo "size:`df -h | awk ‘BEGIN{FS=" "}/^\/dev\/sda2/{print $2}‘`"
        echo "file_os:`df -T | awk ‘BEGIN{FS=" "}/^\/dev\/sda2/{print $2}‘`"
        echo "mount_on:`df -h | awk ‘BEGIN{FS=" "}/^\/dev\/sda2/{print $6}‘`"
       ;;
    2)
        echo "1分钟平均负载:`uptime | awk ‘BEGIN{FS="[ |,]"}{print $14}‘`"
        echo "10分钟平均负载:`uptime | awk ‘BEGIN{FS="[ |,]"}{print $16}‘`"
        echo "15分钟平均负载:`uptime | awk ‘BEGIN{FS="[ |,]"}{print $18}‘`"
        ;;
    3)
        echo "目前可用内存:`free -h | awk ‘BEGIN{FS=" "} /^M/ {print $4}‘`"
        echo "可用Swap分区:`free -h | awk ‘BEGIN{FS=" "} /^S/ {print $4}‘`"
        ;;
    4)
        exit 0
        ;;
    *)
        echo "请输入正确的菜单项!"
esac
done

5.shell解决就餐问题

shell 编程完成以下需求。

1 食堂:中国人(人民币)
2 食堂:外国人(美元)
汇率 6.798
菜单:
宫保鸡丁 (1)(荤): 8.6
鱼香肉丝 (2)(荤):2.5
豆芽炒青菜 (1)(素):5.5
椒盐蘑菇 (2)(素):1.9

倘若一哥们每天必须吃一个肉一个素;用脚本实现搭配的最低消费。

array=(
"宫保鸡丁 (1)(荤):8.6"
"鱼香肉丝 (2)(荤):2.5"
"豆芽炒青菜 (1)(素):5.5"
"椒盐蘑菇 (2)(素):1.9"
)
#检查临时菜单是否存在,存在则删除
check(){
test -f caidan.txt
if [ $? -eq 0 ]
then
    rm -rf caidan.txt
fi
test -f file01.tmp
if [ $? -eq 0 ]
then
    rm -rf file01.tmp
fi
}
#创建临时菜单文件
create(){
for var in ${array[@]}
do
    echo $var >> caidan.txt
done
}
#菜单文件处理及结果输出
operate(){
array01=(`cat caidan.txt |grep \(2\)`)
b=`cat caidan.txt |grep \(1\)`
a=`for j in ${array01[@]};do echo $j;done |awk -F: -v OFS=‘:‘ ‘{print $1,$2*6.798}‘`
for i in $b
do
    echo $i >> file01.tmp
done
for j in $a
do
    echo $j >> file01.tmp
done
array02=(`cat file01.tmp |grep \(荤\)`)
array03=(`cat file01.tmp |grep \(素\)`)
c=`for k in ${array02[@]};do echo $k;done |sort -n -k2 |head -1`
d=`for z in ${array03[@]};do echo $z;done |sort -n -k2 |head -1`
echo $c
echo $d
}
check
create
operate
check

6.shell开发运维管理工具(2)

编写1个弹出式菜单的shell程序并实现其简单的菜单功能

*******************************************************
*                         MENU                          *
*         1.copy                   2.rename             *
*         3.remove                 4.find               *
*                          5.exit                       * 
*******************************************************

用户按下数字1,则提示用户输入源和目的文件名后执行复制;输入数字2,则提示用户输入要更名的文件或目录后执行更名操作;输入数字3,则提示用户输入要删除的文件并执行删除操作;输入数字4,则提示用户输入要查找的文件并执行查找操作;输入数字5,则退出该菜单shell程序的执行。

#shell实现复制、重命名、删除、查找
cat << EOF
*******************************************************
*                         MENU                        *
*         1.copy                   2.rename           *
*         3.remove                 4.find             *
*                          5.exit                     *
*******************************************************
EOF
output(){
if [ $1 -eq 0 ]
then
    echo "success"
else
    echo "fail"
fi
}
while true
do
read -p "请选择功能(0-5):" num
case $num in
    1)
        read -p "请输入源和目的文件名(绝对路径):" s d
        cp -r $s $d
        output $?
        ;;
    2)
        read -p "请输入要更名的文件或目录(绝对路径):" old new
        mv $old $new
        output $?
        ;;
    3)
        read -p "请输入要删除的文件(绝对路径):" filename
        rm -rf $filename
        output $?
        ;;
    4)
        read -p "请输入要查找的文件:" name
        find / -name $name
        ;;
    5)
        exit
        ;;
    *)
        echo "请输入数字0-5!"
esac
done

Linux实战——Shell编程练习(更新12题)

7.自动删除用户账号

编写shell程序,实现自动删除50个用户账号的功能,账号名为stud1至stud50

#自动删除50个用户账号
j=0
for i in `seq 1 50`
do
    userdel -r stud$i &>/dev/null
    if [ $? -eq 0 ]
    then
        j=$(($j+1))
    else
        echo "用户账号stu$i不存在"
    fi
done
echo "$j个用户账号删除完毕,$(($i-$j))个用户账号不存在"

删除5个账号测试:
Linux实战——Shell编程练习(更新12题)

8.九九乘法表

#九九乘法表
for((i=1;i<=9;i++))
do
    for((j=1;j<=i;j++))
    do
#        echo -ne "$i*$j=$(($i*$j))\t"
        echo -ne "$(($i*$j))\t"
    done
    echo ""
done

9.文本处理面试题

(1)[腾讯面试题]:一个文本类型的文件,里面每行存放一个登陆者的IP(某些行是重复的),写一个shell脚本输出登陆次数最多的用户。
Ip_input.txt的内容假设如下:
219.217.49.14
175.43.4.87
87.48.98.1
59.73.38.25
219.217.50.14
59.92.48.32
219.217.49.14
59.72.38.142
59.73.38.25
219.217.49.14

#!/bin/bash
echo "登陆次数最多的用户IP为:`sort Ip_input.txt|uniq -c|sort -nr|awk ‘{print $2}‘|head -n 1`"

(2)腾讯shell试题
假设qq.tel文件内容:
12334:13510014336
12345:12334555666
12334:12343453453
12099:13598989899
12334:12345454545
12099:12343454544
请分类如下:
[12334]
13510014336
12343453453
...........
[12099]
13598989899
12343454544
............
sort qq.tel|awk -F: ‘{if(tmp!=$1){tmp=$1;print "["tmp"]";}print $2}‘
(3) 文件内容如下:
100
a 100
b -50
c -20
d -30
要求输出结果为:
100
a 100
200
b -50
150
c -20
130
d -30
awk ‘NR==1{sum=$1;print $0}NR!=1{print $0;sum=sum-$2;print sum}‘ file
(4)文件内容如下:
123abc456
456def123
567abc789
789def567
要求输出:
456ABC123
123DEF456
789ABC567
567DEF789
sed -r ‘s/([1-9]{3})([a-f]{3})([1-9]{3})/\3\2\1/;y/abcdef/ABCDEF/‘ file
(5)文件内容如下
1.1.1.1 11
1.1.1.1 22
1.1.1.1 33
1.1.1.1 44
2.2.2.2 11
2.2.2.2 22
2.2.2.2 33
2.2.2.2 44
要求使用awk将文件输出:
1.1.1.1 11 22 33 44
2.2.2.2 11 22 33 44
awk ‘{sum[$1]=sum[$1]" "$2}END{for(var in sum)print var sum[var]}‘ file

10.判断一个指定的脚本是否有语法错误

写一个脚本,判断一个指定的脚本是否是语法错误。如果有错误,则提醒用户键入Q或者q:无视错误并退出;其它任何键可以通过vim打开这个指定的脚本。

#!/bin/bash
read -p "please input check script:" file
if [ -f $file ]
then
    sh -n $file >/dev/null 2>&1
    if [ $? -ne 0 ]
    then
        read -p "you input $file syntax error,[Type q/Q to exit or Type other to edit]" answer
        case $answer in
            Q|q)
                exit 0
                ;;
            *)
                vim $file
                ;;
        esac
    fi
else
    echo $file is not exist
    exit 1
fi

11.wget下载管理

创建一个函数,能接受两个参数:
1)第一个参数为URL,即可下载的文件;第二个参数为目录,即下载后保存的位置;
2)如果用户给的目录不存在,则提示用户是否创建;如果创建就继续执行,否则,函数返回一个51的错误值给调用脚本;
3)如果给的目录存在,则下载文件;下载命令执行结束后测试文件下载成功与否;如果成功,则返回0给调用脚本,否则,返回52给调用脚本;

#!/bin/bash
#根据用户输入创建保存目录或退出执行
checkmk(){
if [ $2 == "y" ]
then
    mkdir -p $1
    tmp2=0
elif [ $2 == "n" ]
then
    tmp2=51
else
    echo "[y/n]输入错误error"
fi
return $tmp2
}
#检查下载保存目录是否存在,若存在则下载,否则询问是否创建保存目录
checkdir(){
if [ -d $1 ]
then
    tmp=0
else
    tmp=51
    read -p "是否要创建目录$1[y/n]?" answer
    checkmk $1 $answer
    temp=$?
    if [ $temp -ne 0 ]
    then
    echo "用户不同意创建目录,错误码:$temp"
    else
        tmp=0
        echo "$1目录创建成功"
    fi
fi
return $tmp
}
#下载文件
download(){
checkdir $2
tmp1=$?
if [ $tmp1 -eq 0 ]
then
    wget -P $2 -rnd $1 >/dev/null 2>&1
    if [ $? -eq 0 ]
    then
        tmp2=0
    else
        tmp2=52
    fi
fi
return $tmp2
}
#主函数接受两个参数:URL和目录
main(){
download $1 $2
if [ $? -eq 0 ]
then
    echo "wget is successful"
else
    echo "wget is error,错误码:52"
fi
}
main $1 $2

Linux实战——Shell编程练习(更新12题)

12.解压缩程序

编写一个shell程序,分别能够解压gz、bz2、xz和zip格式文件,其他文件给出提出信息“不认识文件类型”
建立测试文件:
# tar czvf a.tar.gz *.sh
# tar cjvf b.tar.bz2 *.sh
# tar cJvf c.tar.xz *.sh
# zip d.zip *.sh

#!/bin/bash
check(){
if [ $1 -eq 0 ]
then
    echo "$file decompressed successfully"
else
    echo "$file decompressed failed"
fi
}
read -p "请输入要解压文件的名称:" file
if [ -f $file ]
then
    case $file in
        *gz)
            tar xzvf $file >/dev/null
            check $?
        ;;
        *bz2)
            tar xjvf $file >/dev/null
            check $?
        ;;
        *xz)
            tar xJvf $file >/dev/null
            check $?
        ;;
        *zip)
            unzip -n $file >/dev/null
            check $?
        ;;
         *)
            echo "文件格式不正确,无法解压"
    esac
else
    echo "$file文件不存在"
fi

Linux实战——Shell编程练习(更新12题)