一、实验目的:
熟悉UNIX的基本SHELL程序设计方法,包括:
(1)命令行参数检测;
(2)变量设置;
(3)文件状态检测与特定信息读取;
(4)程序运行控制。
二、实验原理:
(1)SHELL程序的主要用途
在SHELL程序中不仅仅可以使用命令的集合,而且可以安排自动化处理过程,因此可以通过编写SHELL程序使大量的任务执行实现自动化。SHELL比较擅长完成系统管理任务,尤其适合完成那些易用性、可维护性和便携性比执行效率更优先的任务。我们可以使用任意一种文本编辑器完成SHELL程序的编写,在SHELL编程中要遵循一定的程序设计规则和变量使用规则。
(2)SHELL程序的执行与调试
在bash的SHELL程序设计中,程序必须以下面的行开始:
#!/bin/bash |
这里符号#!用来告诉系统,后面给出的参数是用来执行该文件的程序。
利用vi,gedit等文本编辑器编写Shell脚本的格式是固定的,如下:
#!/bin/sh #comments Your commands go here |
filename.sh,文件名后缀sh表明这是一个Bash脚本文件
当编辑完一个SHELL脚本后,要使该脚本能够执行,还必须使该脚本文件具有可执行权。需要执行命令:
chmod +x filename |
在shell程序中,以#开头到一个行结束的句子表示注释信息。建议大家在编写shell程序时养成添加注释的习惯,因为注释不仅能给其他需要熟悉该程序的人以帮助,也能给出脚本编写者设计原理的提示。
进行shell程序设计时,必定会用到变量。Shell编程中使用的变量有自己的特色,即所有的变量都是由字符串组成的,而且对变量无须进行声明,可直接进行变量赋值操作。
(3)SHELL程序注意事项
SHELL编程中除了需要遵守一些规则外,还有一些注意事项,如果做得好会对编程有促进,这里列出几条仅供大家参考,更多的内容还需自己通过编程积累。
因为LINUX中命令使用的是小写字符,因此在SHELL编程中可以使用大写字符表示变量以示区别。
在SHELL语句中加入必要的注释,以便以后阅读和维护,注释以”#”开头。
对SHELL变量进行数字运算时,使用乘法符号”*”时,要用转义符”\”进行转义。例子:multiplication=` expr $j \* $j`
由于SHELL对命令中多余的空格不进行任何处理,因此程序员可以利用这一特性调整程序缩进格式,达到增强程序可读性的效果。
在对函数命名时最好能使用有含义且容易理解的名字,即使函数名能够比较准确地表达函数所完成的任务。同时建议对于较大的程序要建立函数命名和变量命名对照表。
如果一行未完成,可以在行尾加上“这个符号 表明下一行与此行会合并为同一行。
(4)SHELL简单调试
最简单的调试命令当然是使用echo命令。可以使用echo在任何怀疑出错的地方打印任何变量值。另外还可以利用Bash中提供的选项进行检查
-n,读一遍脚本中的命令但不执行,用于检查脚本中的语法错误。
-v,一边执行脚本,一边将执行过的脚本命令打印到标准输出。
-x,提供跟踪执行信息,将执行的每一条命令和结果依次打印出来。该选项会显示刚刚执行的命令及参数。用户可以通过set命令打开-x选项或在启动Shell使用-x选项将Shell设置成跟踪模式。
使用这些选项有三种方法(注意:避免几种调试选项混用)
1.在命令行提供参数:$sh -x script.sh
2.脚本开头提供参数:#!/bin/sh -x
3.在脚本中用set命令启用or禁用参数:其中set -x表示启用,set +x表示禁用。
三、实验内容:
编写一个SHELL程序,动态检测指定文件的状态信息,当文件的大小发生改变时,给出提示信息,并继续前进检测。当文件的大小的变化次数或持续检查无变化次数达到一定值时,退出检查,程序结束,具体步骤如下:
(1)清屏;
(2)提示用户输入要检测其状态的文件名;
(3)显示该文件的状态信息(提示:该状态信息可由命令ls –l 来得到),或找不到该文件时的错误提示;
(4)用cut命令,或用sed或awk命令来截取状态信息中文件的大小并保存;
(5)每隔5秒钟检测一次该文件大小的信息,并与保存的文件原来的大小相比较;
(6)如果文件大小未改变,则屏幕显示不变,并继续每隔5秒钟检测一次;
(7)如果文件大小已改变,则保存新的文件大小,并在屏幕上显示:
file [ filename ] size changed(括号中的filename为本程序运行时用户输入的被检测的文件名)。程序继续每隔5秒钟检测一次文件的大小;
(8)程序循环执行5~7步的操作。当被检测的文件或者已累计改变了两次大小,或者已连续被检测了十次还未改变大小时,给出相应提示,然后清屏退出。
参考代码如下:
#!/bin/bashclear# 提示用户输入要检测的文件名
echo "Please enter the filename to monitor:"
read filename# 检查文件是否存在,如果存在,显示状态信息;否则,提示错误信息
if [ -e $filename ]
thenls -l $filenameoldsize=$(ls -l $filename | awk '{print $5}')
elseecho "File not found: $filename"exit
fi# 初始化计数器
count1=0
count2=0# 循环检测文件大小
while true
do# 暂停5秒钟sleep 5# 检查文件是否存在if [ ! -e $filename ]thenecho "File not found: $filename"breakfi# 获取文件当前的大小newsize=$(ls -l $filename | awk '{print $5}')# 如果文件大小未改变,则继续循环if [ $newsize -eq $oldsize ]thenecho "test file's status ..."count2=$((count2+1))else# 如果文件大小已改变,则更新文件大小,打印提示信息,并继续循环oldsize=$newsizeecho "file [ $filename ] size changed"count1=$((count1+1))fi# 更新标志位if [ $count1 -ge 2 ]thenecho "File size changed twice"breakfiif [ $count2 -ge 10 ]thenecho "File size unchanged for 10 times"breakfi
done
#检测文件结束
echo "Monitoring finished"
sleep 5
# 清屏并退出程序
clear