• 在案例中学习shell编程


    1. 编写脚本/root/bin/systeminfo.sh, 显示当前主机系统信息,包括主机名,IPv4 地址,

    操作系统版本,内核版本,CPU 型号,内存大小,硬盘大小。

    分析:

    解释:

    此题是一堆命令的堆叠,首先我们很容易在命令行通过命令知道题目中的一些结果。

    主机名:hostname命令就可以了。
    IPV4地址:ifconfig命令是用来查看ip地址的,只是有很多多余内容,那么我们可以通过正则表达式,

                      以及cut命令即可截取。

    操作系统版本:使用cat /etc/redhat-relase即可查得。
    内核版本:uname -r 可以了。
    CPU型号:有一个文件是关于cpu的即/proc/cpuinfo,这里是要cpu的型号,我们使用grep

                      结合正则截取含有mode的就很容易得到想要的结果。

    内存大小:也有一个文件关于内存的即/proc/meminfo接下来就是截取的问题了。
    硬盘大小:使用命令 fdisk -l ,可以查看到详细信息,接下来使用grep和cut得到想要的列。

    在这里我们需要知道如何调用一个命令可以使用 $(命令)或·命令·这两种方式 。

    得到内存的大小,还可以使用free -m ,计算内存的大小时,如果需要转换单位,那就得

    知道如何进行变量之间的运算了,后面会提到 。

    看似简单的题,更让我们学会:

                              1.写脚本规范很重要

                              2.使用变量可以让脚本变得比较有调理

                              3.熟练使用正则可以让我们事半功倍 

    答:

    #!/bin/bash
    #------------------------
    #Filename:systeminfo.sh
    #Revision:1.0
    #Date:2017-08-08
    #Description:systeminfo
    #------------------------
    Ipv4=`ifconfig eth0 |grep "<inet>"|tr -s ' ' :|cut -d : -f 4`
    Sysmode=`cat /etc/redhat-release`
    Kermode=`uname -r`
    CPU=`lscpu|grep "Model name"|cut -d : -f 2|tr -s ' '`
    Ferr=$[$(cat /proc/meminfo |head -1|grep -o "[[:digit:]]+")/1024]
    Fdisk=`fdisk -l|head -n 2|tail -1 |cut -d , -f 1 |cut -d: -f2`
    echo "系统基本信息"
    echo "主机名:$(hostname)"
    echo "IPV4地址:$Ipv4"
    echo "系统版本:$Sysmode"
    echo "内核版本:$Kermode"
    echo "CPU型号:$CPU"
    echo "内存大小:${Ferr}MB"
    echo "硬盘大小:$Fdisk"
    unset Ipv4 Sysmode Kermode CPU Ferr Fdisk

    #########################################################

    最后讲一下关于变量之间的计算的,在这里只讲三种方法:

    方法一 :let  var=算数表达式  eg.  let  count=2+4     echo $count  就变成6了,推荐使用此发

    方法二:var=$[算数表达式 ]  eg.  count=$[2*3]   echo $count  变成6了

    方法三:var=((算数表达式))和上例差不多。

    2. 编写脚本/root/bin/sumid.sh,计算/etc/passwd文件中的第10个用户和第20用户的ID之和.

    分析:

    解释:

    既然是计算UID之和,那么我们首先必须知道如何得出UID,方法并不难,使用cut以冒号为分隔符,就可以得到我

    们想要的UID,剩下的事情就是如何计算两个数的和,在上一题中我们也教大家方法了,这次我们来详细讨论如

    何计算两个变量之和,还有我们需要注意的是,本题中是第10个用户和第20个用户UID之和,如何使该题的通用

    性增强呢,也就是说,当我们输入数字(代表第几个用户),就能计算之和,这是后我们就需要考虑使用位置

    变量,当然也会涉及正则表达式的内容。举个例子,加入我们输入的不是10和20,而是一个未知数,只能用

    $1和$2替代,得想办法筛选出$1行和$2行的UID并计算,我们可以使用cat -n 显示行号,然后利用正则筛选,

    用cut截取,下面我们来看看具体实现方法。

    答:

    #!/bin/bash
    #--------------------
    #Filename:sumid.sh
    #Revision:2.0
    #Description:UID sum
    #--------------------
    read -p "please you input two arg:" number1 number2
    root1=$(cat /etc/passwd | head -n $number1 |tail -1 | cut -d: -f3)
    root2=$(cat /etc/passwd | head -n $number2 |tail -1 | cut -d: -f3)
    let sumid=root1+root2
    echo "第$number1个用户和第$number2个用户UID之和为:$sumid"
    unset number1 number2 root1 root2

    ----------------------------------------------------------------------------------------------

    3. 编写脚本/root/bin/argsnumsh,接受一个文件路径作为参数;如果参数个数小于1,则提示用户

    “至少应该给一个参数”,并立即退出;如果参数个数不小于1,则显示第一个参数所指向的文件中的空白行数。

    分析 :

    解释: 

    首先我们知道位置变量有一个是计算参数个数的,即$#,下面我们只要利用好此变量就可以做判断。
    为了考虑全面一点,我们需要可以考虑文件是否存在的情况,最后一个难点是如何计算空白的数量。
    ^$我们知道是空白行,不要忘记考虑里面有空格的情况,所以最后结果为“^[[:space:]]*$”.

    答:

    #!/bin/bash
    #--------------------------
    #Filename:argsnumsh
    #Revision:3.0
    #Date:2017-08-10
    #Description:determine args
    #--------------------------
    [ $# -lt 1 ]&&echo "至少应该给一个参数"&&exit 1
    [ -f $1 ]||(echo "please you input exist file";exit 1)||exit 1
    Space=`grep "^[[:space:]]*$" $1|wc -l `
    [ $# -ge 1 ]&&echo "第一个参数文件的空白行为:${Space}行"&&exit 0
    unset Space

    4.编写一个脚本/root/bin/createuser.sh,脚本的执行语法必须是:createuser.sh -u username -m password,

    选项与参数间可支持多空格,但不能顺序颠倒。当未指定正确的选项或参数时,以错误输出方式提示

    “createuser.sh -u username -m password ”后退出脚本。用户名必须以字母开头,可包括数字和_。

    否则不合法。以错误输出提示用户"用户名仅包含字母数据和下划线",当用户名检测合法后,判断用户名

    是否已存在,若存在,再判断用户是否已设置过密码,若设置过密码,直接退出,未设置,则将密码设置

    为所指定的密码后以正确输出方式显示“username 密码已更新后退出”当用户名不存在,则创建用户,

    并为该用户设置所指定的密码后以正确输出方式显示“用户username已创建并更新密码”要求脚本执行

    过程中不能有非要求的其他输出结果出现。脚本在非正确方式退出时应反回给?参数非0值。

    分析:

    解释:

    这道题相对上面几道题是有一定难度的,但是细细分析还是有思路可循。首先是确定格式,可以想到会使用

    位置变量,$1,$2,$3.. 可以确定的有$1为 -u,$3为-m $2 和$4无法确定,但是可以确定参数个数,即$#为4,

    这时,我们使用简单的判断句是可以解决的。下面进行下一个任务,判断用户名是否合法,也就是对$2的判断,

    题目中要求用户名必须以字母开头,可包括数字和_,可以使用正则表达式,写出要求,这应该不难即

    “^[[:alpha:]]([[:alnum:]]|_)*”这里使用的是标准正则表达式,使用此条件去匹配用户提供的用户名,

    不合符提示题目中的语句。接下来判断用户名是否存在,使用的方法当然是使用id命令,若返回值为正确,

    那么接下来是判断密码的存在性,使用的方法是看/etc/shadow文件,观察密码位的情况,

    若用户不存在时就创建用户,并设置密码,这比较简单,下面解答。

    答:

    方法一:

    #!/bin/bash
    #-----------------------
    #Filename:createuser.sh
    #Revision:7.0
    #Date:2017-08-11
    #Description:create user
    #-----------------------
    #判断用户名是否规范,并且给出返回值
    decide=`echo $2|grep "^[[:alpha:]]([[:alnum:]]|_)*$" &>/dev/null;echo $?`
    #判断用户是否存在,并给出返回值
    id=`id $2 &>/dev/null;echo $?`
    #截取用户密码位
    mima=`getent shadow $2 |cut -d: -f 2`
    #判断第一个参数
    if [ "$1" != "-u" ];then
             echo "createuser.sh -u username -m password"
             exit 1
    fi

    #判断第三个参数
    if [ "$3" != "-m" ];then
              echo "createuser.sh -u username -m password"
              exit 1
    fi
    #判断参数个数
    if [ $# -ne 4 ];then
              echo " createuser.sh -u username -m password"
              exit 1
    fi
    #判断第二个参数
    if [ $decide -ne 0 ];then
               echo "用户仅包含字母数字和下划线"
               exit 1
    else
    if [ $id -eq 0 ];then
               if [ "$mima" == "!!" -o "$mima" == "" ];then
               echo "$4" |passwd --stdin $2 &>/dev/null
               echo "$2密码已更新"
               exit 1
    else
               exit 1
    fi
    else

             `useradd $2`
              `echo $4 |passwd --stdin $2 &>/dev/null`
              echo "用户$2已创建并更新密码"

              fi
    fi

    unset  decide  id mima

    方法二:

    [ $1 = "-u" -a $3 = "-m" -a $# -eq 4 ] &>/dev/null ||(echo createuser.sh -u username -m password 1>&2 && exit

    1)&&(echo$2|egrep "<^[[:alpha:]]([[:digit:]]|_|[[:alpha:]])*$>" &>/dev/null ||(echo 用户名仅包含字母数>

    据和下划线 1>&2 ;exit 1  ) &&(  `id $2 &>/dev/null` ||(`useradd $2` ;echo $4 |passwd --stdin $2 &>/dev/null &&

    echo 用户${2}已创建并更新密码;exit 1

                                    ) &&(getent shadow $2 |egrep '$'[[:digit:]]'$' &>/dev/null &&(echo 密码已存>

    在 1>&2 ;exit 0

                                         )||(

                                    echo $4 |passwd --stdin $2 &>/dev/null &&echo 用户${2}密码已更新;exit 1

                                    )||exit 1)||exit 1)||exit 1) ||exit 1

    总结:方法一更容易理解一点 ,方法二逻辑思维比较强,各有各的好处 。

     

  • 相关阅读:
    写一写这几天安卓开发遇到的坑
    安卓环境搭建
    正则表达式
    一段时间的总结
    路飞-登录页面
    路飞-腾讯云短信接口
    路飞-Redis
    路飞-git操作
    路飞-后台xadmin配置
    路飞-后台处理跨域问题
  • 原文地址:https://www.cnblogs.com/jiesying/p/7350635.html
Copyright © 2020-2023  润新知