shell示例


前言

学习linux笔记小实践三
shell 示例


一、Linux shell命令

  当一个用户登录Linux系统之后,系统初始化程序init就为每一个用户运行一个称为shell(外壳)的程序。
  那么,shell是什么呢?确切一点说,shell就是一个命令行解释器,它为用户提供了一个向Linux内核发送请求以便运行程序的界面系统级程序,用户可以用shell来启动、挂起、停止甚至是编写一些程序。当用户使用Linux Shell命令时是通过命令来完成所需工作的。一个命令就是用户和shell之间对话的一个基本单位,它是由多个字符组成并以换行结束的字符串。shell解释用户输入的命令,就象DOS里的command.com所做的一样,所不同的是,在DOS中,command.com只有一个,而在Linux下比较流行的shell有好几个,每个shell都各有千秋。一般的Linux系统都将bash作为默认的shell。

二、shell练习

1.login界面

在这里插入图片描述

[root@student100 ~]# cat h1.sh
#! /bin/bash
#
#登录界面
#
clear
grep "PRETTY_NAME" /etc/os-release | cut -d'=' -f2 | tr -d '"'
echo -n "Kernel $(uname -r) on an $(uname -p)"
echo
read -p "$(hostname -s) login: " uname
read -p "Password: " -s pas
echo
echo "$uname $pas" >> /tmp/.userinfo
exit 0

2.创建用户

(1)编写脚本创建用户rhel,密码为123456,主组为group文件中第10个组,要求登陆强制修改密码,密码有效期30天,提前5天告警,失效3天允许更改密码。

[root@student100 ~]# cat h2.sh 
#! /bin/bash
#
#创建用户,强制改密码
#
clear
gname=$(head -n 10 /etc/group | tail  -n 1 | cut -d':'  -f1)
useradd -g ${gname}  rhel
echo "123456" | passwd --stdin rhel
chage -d0 -M30 -W5 -I3 rhel
exit 0 

(2)编写脚本:提示用户输入用户名和密码,脚本自动创建相应的账户及配置密码。如果用户不输入账户名,则提示必须输入账户名并退出脚本;如果用户不输入密码,则统一使用默认的 123456 作为默认密码(密码输入时不应该被看见)

#! /bin/bash
#
read -p "输入用户名:"  name
if test -z "$name"
then
    echo "user name cant't empty."
    exit 1
fi
useradd  ${name}
read -p "输入密码:" -s  pas
#判断是否输入了密码
if [ -z "$pas" ]
then
    echo  "123456" | passwd --stdin  ${name}
else
    echo  "${pas}" | passwd --stdin  ${name}
fi
exit 0

(3)创建cw0n的10个账号,要求默认密码为 8位置的随机字符,将用户和密码记录到 /tmp/user.txt文件中

#! /bin/bash
#
for i in {1..10}
do
    useradd cw$i    
    num=$(date +%N|md5sum|cut -c 5-12)
    echo "$num" | passwd --stdin cw$i
    echo "cw$i : $num" >> /tmp/user.txt
done

3.nginx安装

编写脚本 检查系统nginx安装是否有配置,如果没有配置,已知nginx的源url为http://nginx.org/packages/centos/ r e l e a s e v e r / releasever/ releasever/basearch/

[root@student100 ~]# cat h3.sh  
#! /bin/bash
#
#检查nginx是否有配置,没有则安装
#
function show()
{
   while :
   do
      echo -n "."
      usleep  500000
   done
}
##########################
#清缓存
yum clean all   &>  /dev/null

# 在后台显示动态效果
echo -n "正则检查系统yum源"
show  &

#列出当前系统下所有仓库源,检查是否包含nginx
yum repolist | grep "nginx"   &> /dev/null
#结束后台show进程
kill -9  $!
#打印空行
echo

#如果源存在则直接退出
if test $? -eq  0
then
   echo  "nginx yum is exist."
   exit  0
fi

echo -e "\033[32mcreating nginx yum.....\033[0m"
#不存在,建立nginx源
cat > /etc/yum.repos.d/nginx.repo << EOF
[nginx]
name="nginx install"
enabled=1
gpgchek=0
baseurl=http://nginx.org/packages/centos/\$releasever/\$basearch/
EOF
exit 0

4.判断冒险位

判断 /usr/bin/passwd文件是否有 set-user-id冒险位权限

[root@student100 ~]# cat h4.sh   
#! /bin/bash
#
#判断冒险位
#
clear
if [ -u /usr/bin/passwd ]
then
        echo "有冒险位"
else
        echo "没有冒险位"
fi
exit 0

5.判断文件

(1)判断 /tmp/a.txt是否存在且是否为空普通文件,如果是空的普通文件则删除

[root@student100 ~]# cat h5.sh
#! /bin/bash
#
#判断文件
#
clear
# 是否存在
if ! test -e  /tmp/a.txt
then
    echo  "'/tmp/a.txt' is not exist."
    exit 0
fi
#判断是否为普通文件 且是否为空
#if [  -f /tmp/a.txt ] && [ ! -s /tmp/a.txt ]
if [  -f /tmp/a.txt  -a  ! -s /tmp/a.txt ]
then
    echo  "'/tmp/a.txt' 是一个普通空文件,删除."
    rm  -rf   /tmp/a.txt
else
    echo  "'/tmp/a.txt' 它不是普通文件或者它不为空."
fi
exit 0

(2)以位置参数的用法,判断某个文件的类型
例如 ./xxx.sh /etc/passwd

#! /bin/bash
#
#检查是否传参正确
if [ $# -ne 1 ]
then
    echo "use error. use : $0  file"
    exit  1
fi
file=$1
#判断是否存在
if test ! -e  ${file}
then
    echo  "'${file}' is not exist."
    exit 2
fi
# 鉴定 file 类型
#方法一:直接使用 file命令鉴定
#file   ${file}
# 方法二: 使用 test测试 鉴定文件类型
#ps : -f  -d -p -s -b -c 判断文件类型时,如果是链接文件它会跟随链接,因此 -L 判断链接放在最前面
#if test -L ${file}
#then
#    echo  "a symbolic link"
#elif test -f ${file}
#then
#    echo  "a regular file"
#elif test -d ${file}
#then
#    echo  "a directory"
#elif test -S ${file}
#then
#    echo "a socket"
#elif test -p ${file}
#then
#    echo "a named pipe"
#elif test -b ${file}
#then
#    echo "block special"
#elif test -c ${file}
#then
#    echo  "character special"
#else
#    echo  "unknow."
#fi
#方法三:ls  -l 查看详细属性,然后截取 第一个字符,则为类型标识 - d s l p b c
key=$(ls -ld  ${file} | cut -c1)
case $key in
   '-')
      echo "a regular file"
      ;;
   'd')
      echo "a directory"
      ;;
   'l')
      echo "a symbolic link"
      ;;
   'p')
      echo "a named pipe"
      ;;
   's')
      echo "a socket."
      ;;
   'b')
      echo "block special"
      ;;
   'c')
      echo  "character special"
      ;;
    *)
      echo "unknow."
      ;;
esac
exit  0

(3)遍历 /tmp目录下是否有空文件,如果有则删除,并统计删除的数量

#! /bin/bash
#
#遍历 /tmp目录下是否有空文件,如果有则删除,并统计删除的数量
#
for i in $(ls /tmp)
do
    if [ "-" = "$(ls  -ld  /tmp/$file | cut -c1)" ]
    then
        echo "文件$i为空,删除"
        rm -rf /tmp/$i
        if [ $? -eq 0 ]    #如果删除成功,计数
        then
                let  "count++"
        fi
    fi
done
echo $sum

6.判断超级管理员

检测本机当前用户是否为超级管理员,如果是管理员root,则使用 yum 安装 vsftpd,如果不是,则提示您非管理员.

[root@student100 ~]# cat h6.sh
#! /bin/bash
#
#判断超级管理员
#
clear
if [ "$(whoami)" = "root" ]
then
    echo "当前用户为超级管理员"
    yum install -y vsftpd
else
    echo "非超级管理员"
fi
exit 0

7.计算

公鸡5元一只,母鸡3元一只,小鸡1元3只,求100元刚好买100只鸡的买法.

#! /bin/bash
#
read -p "公鸡价格(默认5):" gjp
read -p "母鸡价格(默认3):" mjp
read -p "小鸡价格一块多少只(默认3只):" xjp
[ -z "$gjp" ] && gjp=5
[ -z "$mjp" ] && mjp=3
[ -z "$xjp" ] && xjp=3
[ $[$gjp+$mjp+$xjp] -eq 0 ] && echo "错误输入!" && exit 1

for x in $(seq 0 $[100/$gjp])
do
   for y in $(seq 0 $[100/$mjp])
   do
      xj=$[100-$x-$y]
      if [ $[$gjp*$x+$mjp*$y+$xj/$xjp] -eq 100 ] && [ $xj -ge $xjp ]
      then
         echo "公鸡:$x,母鸡:$y,小鸡:$xj"
      fi
   done
done

8.降序排序输出

输入三个数并进行降序排序输出

#! /bin/bash
#
read  -p "input 3 int number:" a b c
#检查输入是否合法`
ret=$(expr $a + $b + $c 2> /dev/null)
if test -z "${ret}"
then
    echo  "输入非法."
    exit 1
fi
######排序
#假设a is max
if [  $a -ge $b -a $a -ge $c ]
then
    if [ $b -ge $c ]
    then
        echo  "$a $b  $c"
    else
        echo  "$a $c  $b"
    fi
#假设b is max
elif test $b -ge $a -a $b -ge $c
then
    if test $a -ge $c
    then
        echo "$b $a $c"
    else
        echo "$b $c $a"
    fi
else
    if [ $a -ge $b ]
    then
        echo  "$c $a $b"
    else
        echo  "$c $b $a"
    fi
fi
#取消变量
unset  a
unset  b
unset  c
exit 0

9.判断用户类型

任意输入一个用户名,判断通过uid值用户的类型 (0:管理 1–999程序用户 1000+ 普通用户 不存在)

#! /bin/bash
#
read -p "input user name:" name
#检查输入
if test -z "$name"
then
    echo "name can't empty."
    exit 1
fi
uid=$(id -u ${name})
#用户不存在
if test -z "${uid}"
then
    exit 2
fi
if [ $uid -eq 0 ]
then
    echo "管理员用户"
elif [ $uid -gt 0 -a $uid -lt 999 ]
then
    echo "程序用户"
else
    echo  "普通用户"
fi
unset name
unset uid
exit 0

10.备份分区

编写脚本备份/boot分区,完全备份文件名为 boot-fully.bak,要求编脚本备份时如果完全备份不存在则实现完全备份,如果完全备份已经存在则实现差异备份,差异备份文件为 “mmddHHMM-boot.bak”; 并配置计划任务在每周五 凌晨3点执行备份脚本。

#! /bin/bash
#
#判断完全备份是否则
if test -e /opt/boot-fully.bak
then
   #差异备份
   xfsdump  -f /opt/$(date +"%m%d%H%M")-boot.bak -l1 -L "boot分区完差异备份" -M " "   /boot
else
   #完全备份
   xfsdump  -f /opt/boot-fully.bak -l0 -L "boot分区完全备份" -M " "   /boot
fi
exit 0

11.测试网段是否被使用

编写脚本测试网段 192.168.3.0/24下有哪些IP正则被使用,将正则被使用的IP记录到/tmp/yes.txt,没有被使用的记录到 /tmp/no.txt (分别实现for循环版本 和 while循环版本的 2个版本)

#! /bin/bash
#
IP=1
while [ $IP -le 5 ]
do
    ping -c 2 -w 2 192.168.3.$IP &> /dev/null
    if [ $? -eq 0 ]
    then
        echo "192.168.3.$IP正在使用"
        echo "192.168.3.$IP" >> /tmp/yes.txt
    else
        echo "192.168.3.$IP没有在使用"
        echo "192.168.3.$IP" >> /tmp/no.txt
    fi
    let "IP=IP+1"
done
#! /bin/bash
#
for IP in {1..5}
do
    #{ }& 可做多进程运行,但不可控
    ping -c 2 -w 2 192.168.3.$IP &> /dev/null
    if [ $? -eq 0 ]
    then
        echo "192.168.3.$IP正在使用"
        echo "192.168.3.$IP" >> /tmp/yes.txt
    else
        echo "192.168.3.$IP没有在使用"
        echo "192.168.3.$IP" >> /tmp/no.txt
    fi
done

12.统计

(1)用for…in循环统计系统下哪些用户是不可登陆的,总数为多少?

#! /bin/bash
#
#grep -v /etc/passwd | cut -d':' -f1        grep -v /etc/passwd 
for i in $(grep nologin /etc/passwd | cut -d':' -f1)
do
   echo $i
   let "sum=sum+1"
done
echo $sum

(2)统计系统下所有的tcp状态的数量 ?
#netstat -nat | grep “^tcp” | awk ‘{print $6}’ 列出系统下所有的TCP状态命令

#! /bin/bash
#
declare -A tcps
for t in $(netstat -nat | grep "^tcp" | awk '{print $6}' )   或  netstat -nat | awk '/^tcp/{print $NF}'
do
    let "tcps[$t]++"    
done
for i in ${!tcps[*]}
do
    echo "$i : ${tcps[$i]}"
done

(3)写脚本 统计/etc/passwd文件中 数字、字母、标点符号的数量, 并统计 其中统计字母分别出现多少次(例如 a多少次 b多少次…字母不区分大小写)

#!/bin/bash
#
#定义字母数组,统计对应的字母出现的次数
declare -A  alphas
#grep -o  "[[:print:]]" /etc/passwd 获取到文件中每个字符,用于for in 遍历
for c in $(grep -o  "[[:print:]]" /etc/passwd)
do
    case $c in
       [[:digit:]])  #数字
           let "d++"
           ;;
       [[:punct:]])  #标点符号
           let "p++"
           ;;
       [[:alpha:]]) #字母
           let "a++"
           #如果是大写转换为小写
           ch=$(echo "$c" | tr "[:upper:]"  "[:lower:]")
           let "alphas[$ch]++"
    esac
done
#打印结果
echo "数字总计    :$d个"
echo "标点符号总计:$p个"
echo "字母总计    :$a个"
echo "对应的字母出现的次数"
for idx in ${!alphas[@]}
do
    echo "$idx : ${alphas[$idx]}"
done

13.判断是否对称

任意输入一个内容,判断它是否为对称的输出yes/no(例如: a b 1 2 3 11 aa 121 aba 123321 abccba)

#! /bin/bash
#
read  -p  "任意输入:"  str
if test -z "$str"
then
     echo  "input can't empty."
     exit 1
fi
#################################
#方法一: 通过rev命令将 str 逆置
#t=$(echo "$str"|rev)

#方法二:通过循环逐个去str中字符,再组合为逆置
#for idx in $(seq 1  $(expr length "$str"))
#do
#     t=$(expr substr  "$str" $idx  1)$t
#done

#方法三:通过普通变量特殊引用 进行逆置
for  idx  in $(seq 0  $[${#str}-1])
do
    t=${str:$idx:1}$t
done

if [ "$str" = "$t" ]
then
    echo   "'$str'  yes."
else
    echo   "'$str'  no ."
fi

(4)写一个while死循环,从0 开始打印数字,每隔半秒打印一个,当打印到10的时候结束。

#! /bin/bash
#
num=0
while :
do
   if [ $num -le 10 ]
   then
       echo "$num"
       let "num++"
   fi
   sleep 0.5
done

14.打印

(1)打印99乘法表
1*1=1
1*2=2 2*2=4
1*3=3 2*3=6 3*3=9

#! /bin/bash
#
#打印99乘法表
#
for i in {1..9}
do
   for j in $(seq 1 $i)
   do
      x=$[i*j]
      echo -n "$j*$i=$x "
   done
   echo
done

(2)打印以下图形(边长为8的空正方形)
* * * * * * * * * * * **
*          *
*          *
*          *
* * * * * * * * * * * **

#! /bin/bash
#
#打印边长为8的空正方形
#
for i in {1..8}
do
   for j in {1..8}
   do
      if [ $j -eq 1 -o $j -eq 8 -o $i -eq 1 -o $i -eq 8 ]
      then
          echo -n "* "
      else
          echo -n "  "
      fi
   done
   echo
done

(3)for循环 打印100以内所有包含数字’7’的数据 且求所有数据和。

#! /bin/bash
#
for i in {1..100}
do
   if echo $i | grep "7"
   then
       echo $i
       let "sum=sum+i"
   fi
done
echo $sum

15.猜数字

RANDOM 变量可以产生一个0–32767的随机正整数,利用该变量产生一个 0–1000范围的随机数,然后编写一个猜数字的小游戏,猜错提示 太大或太小,直到猜对为止,统计猜的次数。

#! /bin/bash
#
count=0
#产生0--1000的随机值
echo "=====seed:$seed"
while :
do
     read  -p "猜一个1000以内的数字:"  num
     #判断num是否输入为数字
     if [[ ! "$num" =~  ^[0-9]+$ ]]
     then
          continue
     fi

     #累加次数
     let "count++"

     #如果输入时数字,则判断
     if [ $num -eq $seed ]
     then
         echo  "恭喜你,猜对了.总计猜测次数为:$count"
         #打破(结束)循环
         break
     elif [ $num -gt $seed ]
     then
         echo  "太大了."
     else
         echo  "太小了."
     fi
done

16.监控程序

写一个监控程序,监控系统下 1分钟内是否有新的登陆失败的用户记录到 /tmp/failed.txt下,并统计如果某个用户在1分钟内登陆失败3次及以上则 通过 wall 广播警告提示 “xxxx 用户正在被爆破.”

#! /bin/bash
#
#统计当前登陆失败的用户信息
lastb > /tmp/lastb_old.txt
while :
do
    sleep  60
    lastb > /tmp/lastb_new.txt
    #对比上一次的差异
    diff /tmp/lastb_old.txt   /tmp/lastb_new.txt | grep "^>"|cut -d' ' -f2| sort | uniq | tee /tmp/failed.txt

    #并统计用户在1分钟内登陆失败的次数记录到txt临时文件中
    diff /tmp/lastb_old.txt   /tmp/lastb_new.txt | grep "^>"|cut -d' ' -f2|tee /tmp/failed.txt|sort|uniq -c > ./txt
    for nu in $(grep -woE "[0-9]+"  ./txt)
    do
        #检索出失败次数大于等于3次的
        if [ $nu -ge 3 ]
        then
            name=$(grep -wE "$nu"  ./txt | awk '{print $2}')
            wall "$name 登陆失败 ${nu} 次......"
        fi
    done    

    #将本次的处理过的新结果作为 老结果数据,为下一次检查做准备
    cat /tmp/lastb_new.txt   >  /tmp/lastb_old.txt
done

17.判断组是否存在

编写脚本判断itgrp组是否存在,如果存在将 root 加入该组,不存在输出 “‘itgrp’ group is not exist.”

#! /bin/bash
#
grep -w "itgrp" /etc/group &> /dev/null
if [ $? -eq 0 ]
then
    echo "存在"
    gpasswd -a root itgrp
else
    echo "'itgrp' group is not exist."
fi

18.菜单

(1)用while+echo+case实现菜单 且根据对应的选择执行对应的动作 1.打印A 2.打印# 3.打印B 4.退出

#! /bin/bash
#
echo "##############"
echo "#  1. 打印A  #"
echo "#  2. 打印#  #"
echo "#  3. 打印B  #"
echo "#  4. 退出   #"
echo "##############"
while :
do
    read -p "请输入请求:" n
    case $n in
        1)
          echo "A"
          ;;
        2)
          echo "#"
          ;;
        3)
          echo "B"
          ;;
        4)
          break
          ;;
    esac
done

(2)用select将某个目录底下的所有普通空文件实现菜单选择 可以删除某个文件,并包含菜单项 all删除所有,quit退出
PS:某个目录通过 位置参数传入

#! /bin/bash
#
#如果有传路径则 遍历对应的路径,如果没有则遍历当前目录
path="./"
if test -n "$1"
then
    path=$1
fi

if test $(ls -ld ${path}|cut -c1) != "d"
then
   echo "参数必须是一个目录路径." > /dev/fd/2
   exit 1
fi
###########
PS3=">># "
select fname in $(find  ${path} -mount  -empty) all  quit
do
     case $fname in
         all)
           #find  ${path} -mount  -empty -exec rm -rf {} \;
           find  ${path} -mount  -empty  -delete
           ;;
         quit)
           break
           ;;
         *)
          rm  -rf  $fname
     esac
done

(3)编写一个脚本提供菜单选择收集系统以下信息:

当前登陆的用户名
主机名
当前的IP地址、掩码地址、DNS、缺省网关
当前是否可以通信外网
内存及交换内存信息
挂载的文件系统信息(除tmpfs devtmpfs)
CPU负载状况
所有可登陆的系统账号 并统计个数
最近登陆失败的账号(仅打印出用户名,要求去重)

#! /bin/bash
#
function showNetworkInfo()
{
    echo "IP      :$(ifconfig ens33|awk '/netmask/{print $2}')"
    echo "NETMASK :$(ifconfig ens33|awk '/netmask/{print $4}')"
    echo "DNS     :$(awk '/^nameserver/{print $2}' /etc/resolv.conf | tr '\n'  '  ' )"
    echo "DefRoute:$(ip route list | awk '/^default/{print $3}')"
}
echo "#############################################"
echo "#  1. 当前登陆的用户名                      #"
echo "#  2. 主机名                                #"
echo "#  3. 当前的IP地址、掩码地址、DNS、缺省网关 #"
echo "#  4. 当前是否可以通信外网                  #"
echo "#  5. 内存及交换内存信息                    #"
echo "#  6. 挂载的文件系统信息                    #"
echo "#  7. CPU负载状况                           #"
echo "#  8. 所有可登陆的系统账号 并统计个数       #"
echo "#  9. 最近登陆失败的账号                    #"
echo "#  10.退出                                  #"
echo "#############################################"
while :
do
    read -p "请输入选项:" n
    echo -e "\033[34m"
    case $n in
        1)
          whoami
          ;;
        2)
          hostname
          ;;
        3)
          showNetworkInfo                        
          ;;
        4)
          if ping -c 2 14.119.104.189    或   www.baidu.com
          then
             echo "可以通信外网"
          else
             echo "不可以通信外网"
          fi
          ;;
        5)
          free -m
          ;;
        6)
          df -TH | grep "^/"
          ;;
        7)
          top -n 1 | awk 'FNR==1{print $10,$11,$12,$13,$14}'
          ;;
        8)
          grep "bash$" /etc/passwd | cut -d':' -f1  或 awk -F':' '/bash$/{print $1;count++}END{print "总计:" count "个"}' /~/
          echo "总计$(grep "bash$" /etc/passwd | wc -l)个"
          ;;
        9)
          lastb | cut -d' ' -f1 | uniq | grep -v "btmp"  或  awk '$1 !~ /btmp/{print $1}' | sort | uniq
          ;;
        10)
          break
          ;;
    esac
    echo -e "\033[0m"

    read -p "[any key continue]"  -n1
done

总结

本文总结了shell的一些实例,用于学习笔记。

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值