shell脚本高级进阶小总结

经过一周脚本的折磨,觉得还是有一定的收获,所以就把一些不容易理解的并且容易忘记的难点做一个总结。shell脚本中主要有两大模块,第一就是流程控制的脚本,第二就是函数控制的脚本。

▲首先,流程控制包括顺序执行,选择执行,循环执行。主要的条件语句就是if。那就来先说说if语句吧!

1.if语句分为单分支,双分支和多分支,并且可以嵌套。

2.多分支分为如下几种情况

if
判断条件1; then

条件为真的分支代码

elif 判断条件2; then

条件为真的分支代码

elif 判断条件3; then

条件为真的分支代码

else

以上条件都为假的分支代码

fi

逐条件进行判断,第一次遇为“真”条件时,执行其分支,而后结束整个if语句

------------下面来举一些多分支的示例吧

1.判断/var/目录下所有文件的类型

for i in /var/* ;do

if [ -b $i ];then

echo "$i块设备文件"

elif [ -c $i ];then

echo "$i字符文件"

elif [ -d $i ];then

echo "$i目录文件"

elif [ -f $i ];then

echo "$i普通文件"

elif [ -h $i ];then

echo "$i链接文件"

elif [ -p $i ];then

echo "$i管道文件"

elif [ -s $i ];then

echo "$i套接字文件"

else

echo "$i该文件不存在"

fi

done

▲其次,再来说说select选择语句,这个语句一般可以跟case语句合并使用,case和select的语法格式如下。

1.case的语法格式,支持glob风格的通配符:

*: 任意长度任意字符

?: 任意单个字符

[]:指定范围内的任意单个字符

a|b: a或b

case 变量引用 in

PAT1)

分支1

;;

PAT2)

分支2

;;

...

*)

默认分支

;;

esac

2.select主要用于创建菜单,按数字顺序排列的菜单项将显示在标准输入上,并显示 PS3
提示符,等待用户输入用户输入菜单列表中的某个数字,执行相应的命令用户输入被保存在内置变量 REPLY 中

------------举例说明,打印菜单

PS3="please choose the menu: "

select menu in  mifan hulatang jiaozi lamian huimian quit

do

case $REPLY in

1|4)

echo "the price is 20"

;;

2)

echo "the price is 12"

;;

3|5)

echo "the price is 30"

;;

6)

break

;;

*)

echo "no the option"

esac

done

▲然后说一下用的比较多的循环语句。循环语句包括for循环和while循环。

  1. for循环语句

    °格式如下:for 变量名 in 列表;do
            循环体
            done
    °执行机制:依次将列表中的元素赋值给“变量名;每次赋值后即执行一次循环体;直到列表中的元素耗尽,循环结束。
    °列表生成方式:
            (1) 直接给出列表
            (2) 整数列表:
            (a) {start..end}
            (b) $(seq [start [step]] end)
            (3) 返回列表的命令
               $(COMMAND)
            (4) 使用glob, 如: *.sh
            (5) 变量引用;
               [email protected], $*

------------举例说明,添加10个用户user1-user10,密码为8位随机字符

for i in {1..10} ; do

useradd user$i

echo "user$i is created..."

password=`tr -dc ‘A-Za-z1-9‘ <
/dev/urandom |head -c8`

echo $password | passwd --stdin $i &>
/dev/null

done

------------举例说明,/etc/rc.d/rc3.d目录下分别有多个以K开头和以S开头的文件;分别读取每个文件,以K开头的输出为文件加stop,以S开头的输出为文件名加start,如K34filename
stop S66filename start

for i in /etc/rc.d/rc3.d/[SK]* ;do

if [ $(basename $i |cut -c1) ==
"k"  ];then

echo `basename $i` stop

else

echo `basename $i` start

fi

done

2.while循环语句

。格式如下:while CONDITION; do

循环体

done

。CONDITION:循环控制条件;进入循环之前,先做一次判断;每一次循环之后会再次做判断;条件为“true”,则执行一次循环;直到条件测试状态为“false”终止循环,所以CONDTION一般应该有循环控制变量;而此变量的值会在循环体不断地被修正。

-----------举例说明,编写脚本,利用变量RANDOM生成10个随机数字,输出这个10数字,并显示其中的最大值和最小值

let
i=0,min=max=$RANDOM                                     echo
"$min"

while [ $i
-lt 9 ];do

ran=$RANDOM

echo "$ran"

if [ $ran -le $max ];then

let max=ran

fi

if [ $ran -le $min ];then

let min=ran

fi

let i+=1

done

echo "最大值是$max,最小值是$min"

-----------举例说明,后续六个字符串:efbaf275cd、4be9c40b8b、44b2395c46、f8c8873ce0、b902c16c8b、ad865d2f63是通过对随机数变量RANDOM随机执行命令:

echo $RANDOM|md5sum|cut –c1-10后的结果,请破解这些字符串对应的RANDOM值

num_array=(efbaf275cd
4be9c40b8b 44b2395c46 f8c8873ce0 b902c16c8

b
ad865d2f63)

for raw_num
in `seq 0 65535`;do

suijijiami=`echo
$raw_num | md5sum |cut -c 1-10`

for num in ${num_array[*]};do

if [ "$suijijiami" == "$num"
];then

echo "$raw_num*****>$num_array"

fi

done

done

解析:这一题其实不难,主要就是要会反向思维,因为这些字符串都是通过随机数加密后而成,我们都知道随机数的一共有65536个数字,也就是说这些加密后的字符串本身没有加密时肯定都是在0到65535之间,所以我们可以把所有的随机数按照题目要求的方式随机加密,然后用for语句匹配我们自己随机加密的字符串是否跟题目上的字符串相同,如果相同,就取出相同字符串所对应的随机数,然后就得出了结果。

▲函数的使用,函数function是由若干条shell命令组成的语句块,实现代码重用和模块化编程它与shell程序形式上是相似的,不同的是它不是一个单独的进程,不能独立运行,而是shell程序的一部分,函数和shell程序比较相似,区别在于:Shell程序在子Shell中运行而Shell函数在当前Shell中运行。因此在当前Shell中,函数可以对shell中变量进行修改。

。函数声明最好定义在一个单独的文件中,不要加上shebang机制。然后调用直接调用函数source|.
函数名,因为函数本身不需要运行,只要在调用的的时候在shell脚本中运行就可以了。

。函数变量默认的是全局变量,所以要定义本地变量只影响函数内部,避免修改函数外的变量值。

。函数不能用exit退出,因为函数本身没有开启子进程会退出整个脚本

。函数的格式:func1 () { local name=mage;echo func1;echo $name; }

-----------举例说明

编写服务脚本/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为当前脚本名

.
/etc/init.d/functions

scripts="/var/lock/subsys/`basename
$0`"

start(){

if [ -e $scripts ];then

echo
"服务已经启动,不需要再次启动"

else

touch $scripts

action  "启动成功" true

fi

}

stop(){

if [ -e $scripts ];then

rm -f $scripts

action  "停止完成"
true

else

echo  "服务未启动,无需停止"

fi

}

restart(){

if [ -e $scripts ];then

stop

start

else

start

fi

}

status(){

if [ -e $scripts ];then

action "`basename $0` is running......" true

else

action "`basename $0` is stopped......" true

fi

}

case $1 in

"start")

start

;;

"stop")

stop

;;

"restart")

restart

;;

"status")

status

;;

*)

echo  "输入参数有误:`basename
$0`  is stop|start|restart|status"

;;

esac

解析:本题的要求就是模仿一个服务的各种状态,当启动的时候,存在这个服务脚本文件,则显示已经启动了不需要再次启动,如果不存在这个服务脚本就创建这个服务脚本文件,并且提示启动成功。在停止服务的时候有这个服务脚本就删除掉这个脚本,并显示停止成功,如果本身就没有这个文件,就显示服务本身就没有启动,无需停止。在重启服务的时候,如果有这个脚本就先停止服务然后重启,如果不存在这个脚本就直接重启。状态就是如果有这个文件就显示服务开启,如果没有就显示服务停止。

-----------举例说明

编写脚本/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退出

.
/etc/init.d/functions

while true;

do

read -p "请输入一个可执行的命令(quit 退出):"
command

if [
"$command" == "quit" ] ; then

exit 1

else

cmd_path=`which $command`

mkdir -p /mnt/sysroot$cmd_path

cp $cmd_path /mnt/sysroot$cmd_path && action " $cmd_path
/mnt/sysroot$cmd_path " true

list=`ldd /bin/ls |grep -o "/lib.* "|tr -d " "`

[ -e /mnt/sysroot/lib64 -a -e /mnt/sysroot/lib ] || mkdir -p
/mnt/sysroot/{lib64,lib}

for i in $list;do

cp $i /mnt/sysroot$i && action "$i  /mnt/sysroot$i "
true

done

fi

done

解析:这题看起来麻烦,其实做的时候并不是很麻烦,就是执行一个脚本,复制命令的路径到指定的路径下,然后把库文件也同时复制过来。要求就是不改变原来的路径,并且提示用户退出的时候再退出,不提示就可以一直复制。有一个需要注意的地方就是如果多次复制一个命令的时候不要重复复制,避免出错。

最后一题还有些地方不是很完善,希望看到的大神帮忙指正。关于脚本的就先写到这里了,有时间再补充。。。。。。

时间: 2024-12-28 15:14:58

shell脚本高级进阶小总结的相关文章

SHELL脚本编程进阶(二)

写在前面(最重要) 本文部分资料和示例援引自以下书籍.在此,感谢原作者的创作,以及所有译者的付出,向他们致敬. Advanced Bash-Scripting Guide <高级Bash脚本编程指南>Revision 10中文版 Linux脚本编程执导 其中 <高级Bash脚本编程指南>Revision 10中文版 是 <Advanced Bash-Scripting Guide> 的中文翻译版,文档翻译正在进行中,再次感谢译者付出. 前言 在之前的文章 Linux 基

shell脚本编程进阶练习题

这两天学习了shell脚本编程进阶,作为一枚文科生,小编觉得...恩..脚本很烧脑.....,不过小编还是做了些题,稍作总结后,呈给各位看官,内容如下: 一.条件选择if语句 选择执行: 注意:if语句可嵌套 单分支 if 判断条件;then 条件为真的分支代码 fi 双分支 if 判断条件; then 条件为真的分支代码 else 条件为假的分支代码 fi 多分支 if 判断条件1; then 条件为真的分支代码 elif 判断条件2; then 条件为真的分支代码 elif 判断条件3; t

shell脚本基础进阶(四)----作业

20150913-15作业 1.描述shell程序的运行原理(可附带必要的图形说明) shell脚本基础进阶(一)----shell介绍 2.总结shell编程中所涉及到的所有知识点(如:变量.语法.命令状态等等等,要带图的哟) shell脚本基础进阶(二)----变量及运算符 3.总结课程所讲的所有循环语句.条件判断的使用方法及其相关示例:(if (jpg|png is not exist):echo "You say a XX") shell脚本基础进阶(三)----流程控制语句

java 调用bash shell脚本阻塞的小问题的解决

java  调用bash shell脚本阻塞的小问题的解决 背景 使用java实现的web端,web端相应用户的界面操作,使用java调用bash实现的shell脚本进行实际的操作,操作完成返回执行结果给web 界面显示. 现象: Java 进程阻塞.使用ps命令可以看到被调用的shell 的执行进程状态为S 分析 Shell子进程的状态是S 睡眠状态,也就是该进程在等待某个条件满足,方能继续执行. Java程序在调用Runtime.getRuntime().exec(jyName)之后,lin

SHELL脚本编程进阶(一)

写在前面(最重要) 本文部分资料和示例援引自以下书籍.在此,感谢原作者的创作,以及所有译者的付出,向他们致敬. Advanced Bash-Scripting Guide <高级Bash脚本编程指南>Revision 10中文版 Linux脚本编程执导 其中 <高级Bash脚本编程指南>Revision 10中文版 是 <Advanced Bash-Scripting Guide> 的中文翻译版,文档翻译正在进行中,再次感谢译者付出. 前言 在之前的文章中,我们已经详细

第14章,Shell脚本编程进阶

更多内容请点击: Linux学习从入门到打死也不放弃,完全笔记整理(持续更新,求收藏,求点赞~~~~) http://blog.51cto.com/13683480/2095439 本章内容: 条件判断 循环 信号捕捉 函数 数组 高级字符串操作 高级变量 Expect 过程式编程语言执行方式: 顺序执行,选择执行,循环执行 条件选择----------------------------------------------------------------------- if语句: 结构: 

shell脚本基础的小实验1

shell脚本入门小实验 编写一个小脚本程序sumsquare.sh,用来计算两个整数的平方和. 例如:当执行sumsquare.sh时 输入3和4,输出的结果为:25; 当执行sumsquare.sh时输入5和6,输出结果为:61 让我们想想两数的平方和 在shell上怎么先做平方再就和,平方就一个数的2次方也就是这个数乘以本身 我们就用输入3和4做例:字面意思就是当你输入3和4 得到的结果是25 那么就是说我们要先做3和4这两个数的平方:3的平方3X3=9;4的平方4X4=16:就和9+16

shell脚本基础进阶(二)----变量及运算符

变量及运算符 变量 变量,即可变化的量,实质是定义一段内存空间,这段空间可以存取任意符合定义的数据类型的数据. 一.bash变量命名: 1.只能包含字母.数字和下划线,并且不能以数字开头 2.不应该跟系统中已有的环境变量重名 3.最好能见名知意 二.bash变量分类: 1.本地变量:只在当前shell进程中有意义 2.环境变量:当前shell进程及子进程中有意义 3.局部变量:某个函数执行过程中有意义 4.位置参数变量:在脚本中引用传递给脚本的参数: 扩展:在shell中,一行命令行中,命令被自

shell脚本基础进阶(一)----shell介绍

shell介绍 既然说到bash编程,那就先从程序设计开始吧,先说什么是程序?个人的话解释:程序就是对数据的加工处理过程.那么,程序设计构成就可以写成这个等式:程序=数据结构+指令算法. 数据结构:即非数值计算的程序设计问题中的计算机的操作对象以及它们之间的关系和操作 指令算法:即对特定问题求解步骤的一种描述,是对指令的有序序列 程序根据在编程过程中对数据和指令的侧重点不同,可以将程序分为两种类型: 1.面向过程的编程:以指令为中心,设计算法,数据服务于算法: 2.面向对象的编程:以数据为中心,