佳音的博客

2007/07/27

Linux的Shell编程之Shell程序设计的流程控制[转]

Filed under: Uncategorized — 佳音 @ 11:33 上午


和其他高级程序设计语言一样,Shell提供了用来控制程序执行流程的命令,包括条件分支和循环结构,用户可以用这些命令创建非常复杂的程序。

  与传统语言不同的是,Shell用于指定条件值的不是布尔运算式,而是命令和字串。

  1.测试命令

  test命令用于检查某个条件是否成立,它可以进行数值、字符和文件3个方面的测试,其测试符和相应的功能分别如下。

  (1)数值测试:

  -eq 等于则为真。

  -ne 不等于则为真。

  -gt 大于则为真。

  -ge 大于等于则为真。

  -lt 小于则为真。

  -le 小于等于则为真。

  (2)字串测试:

  = 等于则为真。

  != 不相等则为真。

  -z字串 字串长度伪则为真。

  -n字串 字串长度不伪则为真。

  (3)文件测试:

  -e文件名 如果文件存在则为真。

  -r文件名 如果文件存在且可读则为真。

  -w文件名 如果文件存在且可写则为真。

  -x文件名 如果文件存在且可执行则为真。

  -s文件名 如果文件存在且至少有一个字符则为真。

  -d文件名 如果文件存在且为目录则为真。

  -f文件名 如果文件存在且为普通文件则为真。

  -c文件名 如果文件存在且为字符型特殊文件则为真。

  -b文件名 如果文件存在且为块特殊文件则为真。

  另外,Linux还提供了与(!)、或(-o)、非(-a)三个逻辑操作符,用于将测试条件连接起来,其优先顺序为:!最高,-a次之,-o最低。

  同时,bash也能完成简单的算术运算,格式如下:

  $[expression]

  例如:

  var1=2

  var2=$[var1*10+1]

  则var2的值为21。

  2.if条件语句

  Shell程序中的条件分支是通过if条件语句来实现的,其一般格式为:

  if 条件命令串

  then

  条件为真时的命令串

  else

  条件为假时的命令串

  fi

  3.for循环

  for循环对一个变量的可能的值都执行一个命令序列。赋给变量的几个数值既可以在程序内以数值列表的形式提供,也可以在程序以外以位置参数的形式提供。for循环的一般格式为:

  for变量名    [in数值列表]

  do

  若干个命令行

  done

  变量名可以是用户选择的任何字串,如果变量名是var,则在in之后给出的数值将顺序替换循环命令列表中的$var。如果省略了in,则变量var的取值将是位置参数。对变量的每一个可能的赋值都将执行do和done之间的命令列表。

  4.while和until循环

  while和until命令都是用命令的返回状态值来控制循环的。While循环的一般格式为:

  while

  若干个命令行1

  do

  若干个命令行2

  done

  只要while的“若干个命令行1”中最后一个命令的返回状态为真,while循环就继续执行do…done之间的“若干个命令行2”。

  until命令是另一种循环结构,它和while命令相似,其格式如下:

  until

   若干个命令行1

  do

   若干个命令行2

  done

  until循环和while循环的区别在于:while循环在条件为真时继续执行循环,而until则是在条件为假时继续执行循环。

  Shell还提供了true和false两条命令用于创建无限循环结构,它们的返回状态分别是总为0或总为非0。

  5.case条件选择

  if条件语句用于在两个选项中选定一项,而case条件选择为用户提供了根据字串或变量的值从多个选项中选择一项的方法,其格式如下:

  case string in

  exp-1)

  若干个命令行1

  ;;

  exp-2)

   若干个命令行2

  ;;

  ……

  *)

  其他命令行

  esac

  Shell通过计算字串string的值,将其结果依次和运算式exp-1, exp-2等进行比较,直到找到一个匹配的运算式为止。如果找到了匹配项,则执行它下面的命令直到遇到一对分号(;;)为止。

  在case运算式中也可以使用Shell的通配符(“*”、“?”、“[ ]”)。通常用 * 作为case命令的最后运算式以便在前面找不到任何相应的匹配项时执行“其他命令行”的命令。

  6.无条件控制语句break和continue

  break用于立即终止当前循环的执行,而contiune用于不执行循环中后面的语句而立即开始下一个循环的执行。这两个语句只有放在do和done之间才有效。

  7.函数定义

  在Shell中还可以定义函数。函数实际上也是由若干条Shell命令组成的,因此它与Shell程序形式上是相似的,不同的是它不是一个单独的进程,而是Shell程序的一部分。函数定义的基本格式为:

  functionname

  {

   若干命令行

  }

  调用函数的格式为:

  functionname param1 param2…

  Shell函数可以完成某些例行的工作,而且还可以有自己的退出状态,因此函数也可以作为if, while等控制结构的条件。

  在函数定义时不用带参数说明,但在调用函数时可以带有参数,此时Shell将把这些参数分别赋予相应的位置参数$1, $2, …及$*。

  8.命令分组

  在Shell中有两种命令分组的方法:()和{}。前者当Shell执行()中的命令时将再创建一个新的子进程,然后这个子进程去执行圆括弧中的命令。当用户在执行某个命令时不想让命令运行时对状态集合(如位置参数、环境变量、当前工作目录等)的改变影响到下面语句的执行时,就应该把这些命令放在圆括弧中,这样就能保证所有的改变只对子进程产生影响,而父进程不受任何干扰。{}用于将顺序执行的命令的输出结果用于另一个命令的输入(管道方式)。当我们要真正使用圆括弧和花括弧时(如计算运算式的优先顺序),则需要在其前面加上转义符(\)以便让Shell知道它们不是用于命令执行的控制所用。

  9.信号

  trap命令用于在Shell程序中捕捉信号,之后可以有3种反应方式:

  (1)执行一段程序来处理这一信号。

  (2)接受信号的默认操作。

  (3)忽视这一信号。

  trap对上面3种方式提供了3种基本形式:

  第一种形式的trap命令在Shell接收到与signal list清单中数值相同的信号时,将执行双引号中的命令串。

  trap ‘commands’ signal-list

  trap “commands” signal-list

  为了恢复信号的默认操作,使用第二种形式的trap命令:

  trap signal-list

  第三种形式的trap命令允许忽略信号:

  trap ” ” signal-list

  注意:

  (1)对信号11(段违例)不能捕捉,因为Shell本身需要捕捉该信号去进行内存的转储。

  (2)在trap中可以定义对信号0的处理(实际上没有这个信号),Shell程序在其终止(如执行exit语句)时发出该信号。

  (3)在捕捉到signal-list中指定的信号并执行完相应的命令之后,如果这些命令没有将Shell程序终止的话,Shell程序将继续执行收到信号时所执行的命令后面的命令,这样将很容易导致Shell程序无法终止。

  另外,在trap语句中,单引号和双引号是不同的。当Shell程序第一次碰到trap语句时,将把commands中的命令扫描一遍。此时若commands是用单引号括起来的话,那么Shell不会对commands中的变量和命令进行替换,否则commands中的变量和命令将用当时具体的值来替换。

]]>

2007/07/20

http 状态代码 状态信息 含义

Filed under: Uncategorized — 佳音 @ 2:51 下午

下表显示了常见的HTTP 1.1状态代码以及它们对应的状态信息和含义。
应当谨慎地使用那些只有HTTP 1.1支持的状态代码,
因为许多浏览器还只能够支持HTTP 1.0。
如果你使用了HTTP 1.1特有的状态代码,最好能够检查一下请求的HTTP版本号。

状态代码

2007/07/17

Lighttpd+Squid+Apache搭建高效率Web服务器[转]

Filed under: Uncategorized — 佳音 @ 6:40 下午

架构原理

源: http://blog.sina.com.cn/u/4cbfbde50100093l

Apache通常是开源界的首选Web服务器,因为它的强大和可靠,已经具有了品牌效应,可以适用于绝大部分的应用场合。但是它的强大有时候却显得笨重,配置文件得让人望而生畏,高并发情况下效率不太高。而轻量级的Web服务器Lighttpd却 是后起之秀,其静态文件的响应能力远高于Apache,据说是Apache的2-3倍。Lighttpd的高性能和易用性,足以打动我们,在它能够胜任的 领域,尽量用它。Lighttpd对PHP的支持也很好,还可以通过Fastcgi方式支持其他的语言,比如Python。

毕竟Lighttpd是轻量级的服务器,功能上不能跟Apache比,某些应用无法胜任。比如Lighttpd还不支持缓存,而现在的绝大部分站点 都是用程序生成动态内容,没有缓存的话即使程序的效率再高也很难满足大访问量的需求,而且让程序不停的去做同一件事情也实在没有意义。首先,Web程序是 需要做缓存处理的,即把反复使用的数据做缓存。即使这样也还不够,单单是启动Web处理程序的代价就不少,缓存最后生成的静态页面是必不可少的。而做这个 是 Squid的强项,它本是做代理的,支持高效的缓存,可以用来给站点做反向代理加速。把Squid放在Apache或者Lighttpd的前端来缓存 Web服务器生成的动态内容,而Web应用程序只需要适当地设置页面实效时间即可。

即使是大部分内容动态生成的网站,仍免不了会有一些静态元素,比如图片、JS脚本、CSS等等,将Squid放在Apache或者Lighttp前 端后,反而会使性能下降,毕竟处理HTTP请求是Web服务器的强项。而且已经存在于文件系统中的静态内容再在Squid中缓存一下,浪费内存和硬盘空 间。因此可以考虑将Lighttpd再放在Squid的前面,构成 Lighttpd+Squid+Apache的一条处理链,Lighttpd在最前面,专门用来处理静态内容的请求,把动态内容请求通过proxy模块转 发给Squid,如果Squid中有该请求的内容且没有过期,则直接返回给Lighttpd。新请求或者过期的页面请求交由Apache中Web程序来处 理。经过Lighttpd和Squid的两级过滤,Apache需要处理的请求将大大减少,减少了Web应用程序的压力。同时这样的构架,便于把不同的处 理分散到多台计算机上进行,由Lighttpd在前面统一把关。

在这种架构下,每一级都是可以进行单独优化的,比如Lighttpd可以采用异步IO方式,Squid可以启用内存来缓存,Apache可以启用MPM 等,并且每一级都可以使用多台机器来均衡负载,伸缩性很好。

实例讲解

下面以daviesliu.net和rainbud.net域下面的几个站点为例来介绍一下此方案的具体做法。daviesliu.net域下有几个用 mod_python实现的blog站点,几个php的站点,一个mod_python的小程序,以后可能还会架设几个PHP和Django的站点。而服务器非常弱,CPU为Celeron 500,内存为PC 100 384M,因此比较关注Web服务器的效率。这几个站点都是采用虚拟主机方式,开在同一台机器的同一个端口上。

Lighttpd服务于80端口,Squid运行在3128端口,Apache运行在81端口。

Lighttpd的配置

多个域名采用/var/www/domain/subdomain 的目录结构,用evhost模块配置document-root如下:

evhost.path-pattern

Powered by 00RZ