Chinaunix首页 | 论坛 | 博客
  • 博客访问: 874984
  • 博文数量: 372
  • 博客积分: 10063
  • 博客等级: 中将
  • 技术积分: 4220
  • 用 户 组: 普通用户
  • 注册时间: 2012-02-24 11:36
文章分类

全部博文(372)

文章存档

2012年(372)

分类: 虚拟化

2012-03-20 20:45:56

写出健壮的Bash脚本

本文链接:http://codingstandards.iteye.com/blog/1458592

也就是在Bash中使用防御性编程。

什么是防御性编程? 写道
什么是防御性编程?

顾名思义,防御性编程是一种细致、谨慎的编程方法。为了开发可靠的软件,我们要设计系统中的每个组件,以使其尽可能地"保护"自己。我们通过明确地在代码中对设想进行检查,击碎了未记录下来的设想。这是一种努力,防止(或至少是观察)我们的代码以将会展现错误行为的方式被调用。

set -u / set -o nounset

对没有初始化的变量做替换时,报错退出。

help set 写道
-u Treat unset variables as an error when substituting.

-o option-name
nounset same as -u

set -e / set -o errexit

如果执行命令的退出码不是0时,脚本立即退出。这样可以避免某些程序片段没有做错误检查而导致不可预期的结果。

help set 写道
-e Exit immediately if a command exits with a non-zero status.

-o option-name
errexit same as -e

使用 "$VAR" 而不是 $VAR

对于引用变量,最好写在双引号中,而不是让它裸奔

因为VAR变量的值中包含空白时,就有可能造成程序出错

使用 "$@" 而不是 $@

因为如果某个参数中包含空白时,不加引号的$@会有问题,含空格的参数将会分裂成多个

处理信号 signal

在编写C代码时通常会在程序开始时使用signal()设置信号处理函数,使程序更加健壮。

在Bash中,可以使用 trap 对信号处理,比如删除临时文件、杀死进程等。

trap command signal [signal ...]

避免出现竞态条件
help set 写道
-C If set, disallow existing regular files to be overwritten
by redirection of output.

-o option-name
noclobber same as -C

使用文件锁的情况,最好如下处理,以避免竞态条件:

Bash代码 复制代码 收藏代码
  1. if ( set -o noclobber; echo "$$" > "$lockfile") 2> /dev/null; then
  2. trap 'rm -f "$lockfile"; exit $?' INT TERM EXIT
  3. #critical-section
  4. rm -f "$lockfile"
  5. trap - INT TERM EXIT
  6. else
  7. echo "Failed to acquire lockfile: $lockfile"
  8. echo "held by $(cat $lockfile)"
  9. fi
if ( set -o noclobber; echo "$$" > "$lockfile") 2> /dev/null; then trap 'rm -f "$lockfile"; exit $?' INT TERM EXIT #critical-section rm -f "$lockfile" trap - INT TERM EXIT else echo "Failed to acquire lockfile: $lockfile" echo "held by $(cat $lockfile)" fi

保持原子化(事务化)

要么全部做,要么什么都不做。

比如:下面的代码展示的将文件中的一个字符串替换成另一个字符串,保证所有文件都被替换,或者都不被替换。

思路是先把要处理的文件复制到一个临时目录,进行替换操作,然后再替换原来的。即使 Ctrl+C 终止,也不会出现部分被替换的情况。

Bash代码 复制代码 收藏代码
  1. cp -a /var/www /var/www-tmp
  2. for file in $(find /var/www-tmp -type -f -name "*.html"); do
  3. perl -pi -e 's/' $file
  4. done
  5. mv /var/www /var/www-old
  6. mv /var/www-tmp /var/www
cp -a /var/www /var/www-tmp for file in $(find /var/www-tmp -type -f -name "*.html"); do perl -pi -e 's/' $file done mv /var/www /var/www-old mv /var/www-tmp /var/www

更详细的内容,请参看

阅读(567) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~