首页 > 代码库 > 在案例中学习shell编程
在案例中学习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
总结:方法一更容易理解一点 ,方法二逻辑思维比较强,各有各的好处 。
在案例中学习shell编程