Shell编程经验总结之―重定义和跨平台
时间:2005-11-16 来源:xwfang
忙里偷闲,又来无耻的介绍我的shell编程经验了J
我在Shell编程经验总结的第一篇文章中提到在shell编程中把执行语句封装成函数,并通过引入的方式实现代码重用的一个好处是实现函数重定义和跨平台,函数重定义有什么好处呢?还有有些人可能觉得shell本身就是跨平台的,为什么还存在跨平台的问题呢?下面将详细描述.
你写shell脚本的时候有没有写过和系统命令同名的函数?没有的话没有关系,可以马上试一下.
我想把ls改成 ls –l的效果(你可以直接用别名J),我在此就不考虑别名的情况了.看函数的实现.下面是tools.inc的内容.
#tools.inc
ls()
{
ls -l
}
下面是test.sh的内容.
#!/bin/bash
. /home/away/common/tools.inc
echo "begin"
ls
echo "end"
好,执行一下test.sh脚本,你会看到什么?程序core dump了,为什么,J
away@DXX-3900:~/test$ test.sh
begin
Segmentation fault
因为自身递归调用导致的,说明什么,你的ls是调用了你自己定义的ls函数.而不是系统的.
好了,现在我们把tools.inc添加一点内容变成
#tools.inc
#first ls
ls()
{
ls -l
}
#second ls
ls()
{
echo "my ls 2"
}
然后在和上面一样执行一下test.sh.
away@DXX-3900:~/test$ t.sh
begin
my ls 2
end
现在没有问题了,为什么?后面定义的ls函数覆盖了第一个定义的ls函数
现在应该明白了函数重定义了吧,有什么好处呢?具体好处就是实现了函数重定义(好像是废话哦,呵呵).其实有没有好处地球人都知道.我就不多说了.
上面知道了shell函数的重定义,现在就应该说说跨平台了.shell需要跨平台是因为各个unix/linux系统提供的命令的参数和输出结果不一致带来的问题.
比如:我想用shell编写一个从系统中获取系统中剩余空间的函数(此处只考虑已经创建文件系统的,裸设备不考虑在内),你可以用df –m 然后awk处理一下,取出第四个字段相加一下就可以了(linux下),在一般的linux下也许可以,但是在hp-unix下就不行了,hp下的df命令输出的格式是完全不一样的.到是bdf命令和df比较像.,然后你为了支持多个平台你的代码中就需要如下写:
OS_TYPE=`uname -s`
if [ "-${OS_TYPE}" = "-Linux" ]
then
{
echo "in linux os"
#df -k
#此处省略获取磁盘剩余空间的代码
}
elif [ "-${OS_TYPE}" = "-HP-UX" ]
then
{
echo "in hp-unix"
#bdf -k
#此处省略获取磁盘剩余空间的代码
}
elif [ "-${OS_TYPE}" = "-SunOS" ]
then
{
echo "in sun os"
#df -k
#此处省略获取磁盘剩余空间的代码
}
elif [ "-${OS_TYPE}" = "-AIX" ]
then
{
echo "in aix os"
#df -k
#此处省略获取磁盘剩余空间的代码
}
fi
你也可以把磁盘信息获取部分的代码封装成函数,你需要定义四个不同名的函数. get_disk_info_linux get_disk_info_hp get_disk_info_sun get_disk_info_ibm然后在if elif fi中调用这些函数. 如果系统中很多地方用到的系统命令名称或者因版本导致输出格式不一致的话,你将很快发现程序中到处充满了可恶的if elif fi之类的语句.还有可能这个get_disk_info*的函数在linux和sun,ibm平台实现都一样,而只有hp的实现不一样时,又有不一样的if语句.这样看起来代码就太恶心了.有没有办法解决呢?有,就是利用上面讲到的函数重定义.
我们可以创建下面几个文件tools.inc tools_linux.inc tools_hp.inc tools_sun.inc tools_ibm.inc, 然后在主脚本test.sh中实现如下:
#test.sh
OS_TYPE=`uname -s`
#这个tools.inc存放各个平台实现最大相同(这个地方后面会特别解释一下,呵呵)的函数
. /home/away/common/tools.inc
if [ "-${OS_TYPE}" = "-Linux" ]
then
{
. /home/away/common/ tools_linux.inc
}
elif [ "-${OS_TYPE}" = "-HP-UX" ]
then
{
. /home/away/common/tools_hp.inc
}
elif [ "-${OS_TYPE}" = "-SunOS" ]
then
{
. /home/away/common/tools_sun.inc
}
elif [ "-${OS_TYPE}" = "-AIX" ]
then
{
. /home/away/common/tools_ibm.inc
}
fi
main()
{
}
main “$@”
tools.inc的实现如下:
#tools.inc
get_disk_info()
{
echo "common get_disk_info function"
#df -k
#此处省略获取磁盘剩余空间的代码
}
tools_hp.inc实现如下:
#tools_hp.inc
get_disk_info()
{
echo "hp get_disk_info function"
#bdf -k
#此处省略获取磁盘剩余空间的代码
}
然后你就可以在相应的平台中写需要的函数了,如果这个函数的实现在最多的平台实现相同的话可以把这个函数写在tools.inc而相应的平台就不必再实现了,如果hp平台的实现不一样就可以在tools_hp.inc中实现这个函数,函数明都叫一样的比如上面的get_disk_info().这个就有点像c++中的虚函数的特性.tools.inc作为父类,而具体平台的有选择的进行了重新实现.
这样实现以后你会发现只有一个地方需要if fi之类的语句引入相应平台的文件,所有的函数实现放在具体的平台文件中.说到里面废话也说了差不多了,不知道对大家有没有什么帮助,虽然我们基本都用linux平台,但是也可能遇上因为linux版本不一样导致的问题,也可以通过这个方法解决.