(026) Linux之自顶向下设计

十年运维系列之基础篇 - Linux

作者:曾林 

联系:[email protected]

网站:www.jplatformx.com

版权:文章未经同意请勿转载


一、引言

      随着程序越来越大,越来越复杂,设计、编码和维护都将越来越困难。所以,在设计任何大型项目的时候,我们最好将庞大的、复杂的任务,拆分成一系列小的、简单的任务。

      想象一下,我们来描述一个常见的日常任务:你去超市买东西。我们可以按照如下的步骤来进行。

  1. 选择商品
  2. 结账
  3. 离开

但是,我们在结账这个环节则可能需要更多的细节。我们来继续将“结账”这个步骤进一步拆分为一系列的步骤。

  1. 排队
  2. 统计商品
  3. 付钱
  4. 收取零钱

这种先确定上层步骤,然后再逐步细化这些步骤的过程,称之为自顶向下的设计。

通过这种设计方式,我们可以将大而且复杂的任务分解成很多小而简单的任务。自顶向下设计是一种设计程序的常见方式,尤其适合shell编程。

 

二、shell函数

      所谓shell函数,本质上就是shell脚本中的迷你脚本。shell函数有两种语法形式。第一种如下所示:

function name    {
    commands
    return  
}

      其中name是指这个函数的名称,commands是这个函数中的一系列命令。第二种看起来如下所示:

name()    {
      commands
      return
}

      这两种形式等价,并且可以交替使用。如下,我们来提供一个简单的脚本来展示一下shell函数的使用。

#!/bin/bash

# Program to output a system information page

TITLE="System Information Report for $HOSTNAME"
CURRENT_TIME=$(date +"%x %r %Z")
TIME_STAMP="Generated $CURRENT_TIME, by $USER"

report_uptime()    {
    cat <<- _EOF_
                <H2>Report Uptime</H2>
                <PRE>$(uptime)</PRE>
   _EOF_
}

report_disk_space()    {
    cat <<- _EOF_
                <H2>Report disk space</H2>
                <PRE>$(df -h)</PRE>
    _EOF_
}

report_home_space()    {
    cat <<- _EOF_
                <H2>Report home space</H2>
                <PRE>$(du -sh /home/*)</PRE>
    _EOF_
}

cat << _EOF_
<HTML>
<HEAD>
    <TITLE>$TITLE</TITLE>
  </HEAD>
  <BODY>
      <H1>$TITLE</H1>
      <P>$TIME_STAMP<P>
      $(report_uptime)
      $(report_disk_space)
      $(report_home_space)
  </BODY>
</HTML>
_EOF_

 

三、局部变量

      在目前我们所编写的脚本中,所有的变量(包括常量)都是全局变量。全局变量在整个程序期间会一直存在。在很多情况下,这都不错。但是有时候,它会让shell函数的使用变得复杂。在shell函数中,经常需要的是局部变量。局部变量仅仅在定义它们的shell函数中有效,一旦shell函数终止,它们就不会存在。

      局部变量可以让程序员使用已经存在的变量名称,无论是脚本中的全局变量,还是其他shell函数中的变量,而不用考虑潜在的命名冲突。

      下面定义一个显示如何定义和使用局部变量的脚本示例。

  1 #!/bin/bash
  2 
  3 # local-vars: script to demenstrate local variables
  4 
  5 foo=0 # global variable foo
  6 
  7 funct_1()   {
  8     local foo
  9     foo=1
 10     echo "funct_1: foo = $foo"
 11 }
 12 
 13 funct_2()   {
 14     local foo
 15     foo=2
 16     echo "funct_2: foo = $foo"
 17 }
 18 
 19 echo "global: foo = $foo"
 20 funct_1
 21 echo "global: foo = $foo"
 22 funct_2
 23 echo "global: foo = $foo"

运行结果如下图:

技术分享

      可以看到,局部变量是通过在变量名前面添加单词local来定义的。这样,就创建并同时定义了一个shell函数中的局部变量。一旦出了这个shell函数,这个局部变量将不再存在。因此,在两个shell函数中对局部变量foo的赋值,不影响shell函数以外定义的变量foo的值。

 

四、保持脚本的运行

      在开发程序的时候,让程序保持可运行的状态会非常有用。通过这种方式,并经常测试,就可以在开发过程的早期检测到错误。这也会让问题的调试变得容易。例如,如果我们运行某个程序,并对它做了细微的改动,然后再次运行该程序,此时发生了问题。这可能是有可能最近的改动所造成的。通过添加空函数(程序员称之为stub),我们可以在早期验证程序的逻辑流程。当构建一个stub时,最好是包含一些能够为程序员提供反馈信息的东西,这些反馈信息可以显示正在执行的逻辑流程。

 

五、在.bashrc中添加shell函数

      shell函数可以很好的取代别名,并且实际上也是创建个人使用的小命令的首选方法。别名非常局限于命令的种类和它们支持的shell特性,而shell特性则允许任何可以编写为脚本的东西。例如,如果我们很喜欢为脚本开发report_disk_space这个shell函数,则可以为.bashrc文件创建一个相似的名为ds的函数。

ds()    {
    echo "Disk Space Utilization for $HOSTNAME"
    df -h
}

 

六、本章结束语

      在本章,我们介绍了一种常用的程序设计方法——自顶向下,并知道了如何使用shell函数按照要求来构建逐步细化的任务。我们还学习了如何使用局部变量时shell函数的相互独立,并独立于它们所在的程序。这样,我们就可以以可移植和可重用的方式编写shell函数,并将其用到多个程序中,从而节省大量的时间。

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。