linux脚本进阶例题解析
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linux脚本进阶例题解析相关的知识,希望对你有一定的参考价值。
例题一:编写脚本/root/bin/createuser.sh,实现如下功能:
使用一个用户名做为参数,如果指定参数的用户存在,就显示其存在,否则添加之;并生成8位随机口令并存在一个文件中,初步提示改口令,显示添加的用户的id号等信息
#!/bin/bash # ------------------------------------------ # Filename: useradd.sh # Revision: null # Date: 2017-09-11 21:47:22 # Author: 赵东 # Email: [email protected] # Website: null # Description: new file # ------------------------------------------ for i in {1..10};do pw=`cat /dev/urandom |tr -dc [[:alnum:][:graph:]]|head -c 8` #生成8位随机字符密码 useradd user$i &> /dev/null if [ $? -eq 0 ];then echo $pw | passwd --stdin user$i &> /dev/null echo "user user$i password is $pw" else echo "user$i already exist" fi done #for i in {1..10};do userdel -r user$i;done 删除生成的用户
本题重点:
①生成指定长度的随机数
cat /dev/urandom |tr -dc [[:alnum:][:graph:]]|head -c 8
/dev/urandom中包含了无数个随机字符,常用于随机数的生成,这里我们只需要保留其中的英文和数字,从而截取前8个字符
②从标准输入设置用户密码
echo string | passwd --stdin username &> /dev/null
例题二:编写脚本/root/bin/checkint.sh,判断用户输入的参数是否为正整数
#!/bin/bash # ------------------------------------------ # Filename: checkint.sh # Revision: null # Date: 2017-09-11 20:54:50 # Author: 赵东 # Email: [email protected] # Website: null # Description: new file # ------------------------------------------ read -p "Please input a number: " num if [[ $num =~ ^[1-9]+[0-9]*$ ]];then echo "true" else echo "false";exit 20 fi
本题重点:
而事实上,正整数只是不包括负号‘-’小数点‘.’且开头不为0的数字的集合,这样想起来就很容易表达了,所以正整数的表达方式如下
[[ $num =~ ^[1-9]+[0-9]*$ ]]
例题三:/etc/rc.d/rc3.d目录下分别有多个以K开头和以S开头的文件;分别读取每个文件,以K开头的输出为文件加stop,以S开头的输出为文件名加start,如K34filename stop
#!/bin/bash # ------------------------------------------ # Filename: startorstop.sh # Revision: null # Date: 2017-09-12 08:43:15 # Author: 赵东 # Email: [email protected] # Website: null # Description: new file # ------------------------------------------ ls /etc/rc.d/rc3.d/ | while read filename;do case $filename in K*) echo "$filename start" ;; S*) echo "$filename stop" ;; esac done
本题重点:
①while的特殊用法:以行为单位遍历文件内容和遍历指定目录下的文件名
用法一: 遍历文件内容
while read line;do
循环体
done < 文件路径
其中line为自定义变量,表示文件的行
用法二:配合管道进行遍历,管道前可接命令,如果有多个命令,则用“;”隔开(超好用!!)
ls /path/dirname | while read filename;do
循环体
done
②case判断语句中的判断条件支持glob风格的通配符,例如以下常用几种:
*:任意长度字符
?:任意单个字符
[]:任意范围内的单个字符
a|b:a或b
例题四:打印九九乘法表
#!/bin/bash # ------------------------------------------ # Filename: 99.sh # Revision: null # Date: 2017-08-25 00:49:26 # Author: zhaodong # Email: [email protected] # Website: null # Description: new file # ------------------------------------------ echo "99乘法表" for i in `seq 1 9`;do for j in `seq 1 $i`;do echo -en "${i}X${j}=$[$i*$j]\t" done echo done
本题重点:
如何输出指定范围内的数字或字母???
情况一:没有引用变量
{1..100} {a..z}
情况二:引用变量值
`seq 1 $num` `seq a $alpha` ( 注意:seq 是一个命令,所以引用命令结果需要加``或$() )
例题五:
后续六个字符串:efbaf275cd、4be9c40b8b、44b2395c46、f8c8873ce0、b902c16c8b、ad865d2f63是通过对随机数变量RANDOM随机执行命令:
echo $RANDOM|md5sum|cut –c1-10后的结果,请破解这些字符串对应的RANDOM值
#!/bin/bash # ------------------------------------------ # Filename: md5.sh # Revision: null # Date: 2017-09-12 21:15:21 # Author: 赵东 # Email: [email protected] # Website: null # Description: new file # ------------------------------------------ read -p "Please input your passwd: " md5_pwd i=1 while [ $i -le 60000 ];do #穷举60000次 rdm_num=$RANDOM a=`echo ${rdm_num}|md5sum|cut -c1-10` if [ $a == $md5_pwd ];then result=`echo $rdm_num` break else let i++ continue fi done echo "result= " $result unset i md5_pwd
例题六:
编写服务脚本/root/bin/testsrv.sh,完成如下要求
(1) 脚本可接受参数:start, stop, restart, status
(2) 如果参数非此四者之一,提示使用格式后报错退出
(3) 如是start:则创建/var/lock/subsys/SCRIPT_NAME, 并显示“启动成功”
考虑:如果事先已经启动过一次,该如何处理?
(4) 如是stop:则删除/var/lock/subsys/SCRIPT_NAME, 并显示“停止完成”
考虑:如果事先已然停止过了,该如何处理?
(5) 如是restart,则先stop, 再start
考虑:如果本来没有start,如何处理?
(6) 如是status, 则如果/var/lock/subsys/SCRIPT_NAME文件存在,则显示“SCRIPT_NAMEis running...”
如果/var/lock/subsys/SCRIPT_NAME文件不存在,则显示“SCRIPT_NAME is stopped...”
其中:SCRIPT_NAME为当前脚本名
#!/bin/bash # ------------------------------------------ # Filename: testsrv.sh # Revision: null # Date: 2017-09-13 22:12:10 # Author: 赵东 # Email: [email protected] # Website: null # Description: new file # ------------------------------------------ . /etc/init.d/functions #调用函数 filename=`echo /var/lock/subsys/testsrv.sh` #设置文件名 ls $filename &> /dev/null && exist=true || exist=false #检查文件是否存在 if [ $# -eq 1 ];then #判断位置参数是否为一个 if [ "$1" == "start" ]||[ "$1" == "stop" ]||[ "$1" == "restart" ]||[ "$1" == "status" ];then #判断位置参数的值 case $1 in start) if [ "$exist" == "false" ];then touch $filename action "successfull start it" true elif [ "$exist" == "true" ];then action "Already running..." false fi ;; stop) if [ "$exist" == "true" ];then rm -rf $filename action "successfull stop it" true elif [ "$exist" == "false" ];then action "failed stop it" false fi ;; restart) if [ "$exist" == "false" ];then action "Stopping it:" false touch $filename echo "starting..." action "Restart successfull" true elif [ "$exist" == "true" ];then rm -rf $filename echo "stopping..." touch $filename echo "starting..." action "Restart successfull" true fi ;; status) if [ "$exist" == "true" ];then echo "`basename $filename` is running..." elif [ "$exist" == "false" ];then echo "`basename $filename` is stopped..." fi esac else echo "usage: `basename $filename` {start|stop|restart|status} " exit 1 fi else echo "Useage is: `basename $filename` {arg} " exit 2 fi
本题重点:
函数的调用
当在脚本中引用函数文件中的函数时,正确步骤如下:
步骤1: . /source 函数文件名 f-----执行函数文件(之所以使用这种方式是为了避免进入二级bash从而影响变量的使用)
步骤2: 函数名 -----调用函数
例题七:
编写脚本/root/bin/copycmd.sh
(1) 提示用户输入一个可执行命令名称
(2) 获取此命令所依赖到的所有库文件列表
(3) 复制命令至某目标目录(例如/mnt/sysroot)下的对应路径下;如:/bin/bash ==> /mnt/sysroot/bin/bash
/usr/bin/passwd==> /mnt/sysroot/usr/bin/passwd
(4) 复制此命令依赖到的所有库文件至目标目录下的对应路径下:如:/lib64/ld-linux-x86-64.so.2 ==> /mnt/sysroot/lib64/ld-linux-x86-64.so.2
(5)每次复制完成一个命令后,不要退出,而是提示用户键入新的要复制的命令,并重复完成上述功能;直到用户输入quit退出
#!/bin/bash # ------------------------------------------ # Filename: copycmd.sh # Revision: null # Date: 2017-09-14 20:04:12 # Author: 赵东 # Email: [email protected] # Website: null # Description: new file # ------------------------------------------ while true;do read -p "Please Input a command(Input "q" or "quit" can be quit): " com command_exist=`which $com &> /dev/null;echo $?` #判断命令是否存在的变量,存在为0 if [ "$com" == "q" ]||[ "$com" == "quit" ] ;then #1.判断是否用户是否想退出 break elif [ `echo $command_exist` != 0 ];then #2.判断命令是否存在 echo -e "\033[1;31mCommand $com unexist\033[0m" continue else binary=`which $com | tail -1` #二进制文件路径 libfile=`ldd $binary | cut -d‘>‘ -f2|grep /|cut -d‘(‘ -f1` #所有库文件 路径 dirname=/mnt/sysroot`dirname $binary` #二进制文件目标目录 echo -e "\033[1;32m1.The list of "$com" dependence lib files is:\033[0m" echo "$libfile" #3.显示所有库文件 if [ -e /mnt/sysroot$binary ];then #4.判断二进制文件是否已拷贝 echo -e "\033[1;31mCommand already copied\033[0m" else mkdir -p $dirname cp -a $binary $dirname #5.复制二进制文件到目标目录 echo -e "\033[1;32m2.Binary files copy successfull\033[0m\n$binary===========>/mnt/sysroot$binary" echo -e "\033[1;32m3.Copying lib files:\033[0m" for i in `echo $libfile`;do #5.遍历库文件,并依次复制库文件 mkdir -p /mnt/sysroot`dirname $i` #创建新的库目录 cp -a $i /mnt/sysroot`dirname $i` echo -e "$i===========>/mnt/sysroot${i}\n" done echo -e "\033[1;32mLib files copy successfull\033[0m" fi fi done
本体重点:
①显示指定命令的二进制文件
which command | tail -1 为啥要截最后一行呢??因为命令可能存在别名,比如下边这种情况
[[email protected] ~]# which ls alias ls=‘ls --color=auto‘ /bin/ls
②截取指定命令的所有库文件
ldd `which command | tail -1 ` | cut -d‘>‘ -f2|grep /|cut -d‘(‘ -f1
以上是关于linux脚本进阶例题解析的主要内容,如果未能解决你的问题,请参考以下文章
Linux基础之bash脚本编程进阶篇-选择执行语句(if,case)
❥十大排序算法❥爆肝两万字保姆级教程(文字解析+图解+代码实现+例题)